]> git.mxchange.org Git - friendica.git/blob - bin/composer.phar
Merge pull request #8530 from MrPetovan/task/8498-move-poke-to-src
[friendica.git] / bin / composer.phar
1 #!/usr/bin/env php
2 <?php
3 /*
4  * This file is part of Composer.
5  *
6  * (c) Nils Adermann <naderman@naderman.de>
7  *     Jordi Boggiano <j.boggiano@seld.be>
8  *
9  * For the full copyright and license information, please view
10  * the license that is located at the bottom of this file.
11  */
12
13 // Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264
14 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)) {
15     if (version_compare(phpversion('apc'), '3.0.12', '>=')) {
16         ini_set('apc.cache_by_default', 0);
17     } else {
18         fwrite(STDERR, 'Warning: APC <= 3.0.12 may cause fatal errors when running composer commands.'.PHP_EOL);
19         fwrite(STDERR, 'Update APC, or set apc.enable_cli or apc.cache_by_default to 0 in your php.ini.'.PHP_EOL);
20     }
21 }
22
23 Phar::mapPhar('composer.phar');
24 require 'phar://composer.phar/bin/composer';
25
26 __HALT_COMPILER(); ?>\r
27 ¨\95\0\0ø\ 1\0\0\11\0\0\0\ 1\0\r\0\0\0composer.phar\0\0\0\0+\0\0\0src/Composer/Autoload/AutoloadGenerator.phpüc\0\0\98Þ\1d^üc\0\0ÊÇv`¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php¨\12\0\0\98Þ\1d\12\0\0   \99f\11\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpç\13\0\0\98Þ\1d\13\0\0³\9bî\1d\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpØ\ 2\0\0\98Þ\1d\ 2\0\0ö÷;\87\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.php\9e\14\0\0\98Þ\1d^\9e\14\0\0\19lG\ f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÜ\v\0\0\98Þ\1d\v\0\0\1a\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpñ\18\0\0\98Þ\1d\18\0\0XgFð¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Command/CheckPlatformReqsCommand.php        \ f\0\0\98Þ\1d\ f\0\0*Þ¯T¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.phpµ\ 5\0\0\98Þ\1d\ 5\0\0vÿy\83\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\15M\0\0\98Þ\1d^\15M\0\0Û=\ 4\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.phpß5\0\0\98Þ\1d^ß5\0\0ü\90_÷¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.phpø\ 2\0\0\98Þ\1d\ 2\0\0ªe\11á¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpåM\0\0\98Þ\1d^åM\0\0\13hÇÔ¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.phpL\f\0\0\98Þ\1d^L\f\0\0°E²ù¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpï\a\0\0\98Þ\1d\a\0\0Xr\9c¾¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpz      \0\0\98Þ\1d^z \0\0³çå?¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.php\ 4\ f\0\0\98Þ\1d^\ 4\ f\0\0qLB\8e\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.php¯Q\0\0\98Þ\1d^¯Q\0\0\9cÁ    ´¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpT\14\0\0\98Þ\1d^T\14\0\0Þùõ\9b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php\82\ e\0\0\98Þ\1d^\82\ e\0\0±s'\ e\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php\ f\f\0\0\98Þ\1d^\ f\f\0\0ا\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.php\12\ 3\0\0\98Þ\1d^\12\ 3\0\0_¤éS¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.phpá\18\0\0\98Þ\1d\18\0\0½í\9d\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php"'\0\0\98Þ\1d^"'\0\0ü¤Ø²¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php=\ f\0\0\98Þ\1d^=\ f\0\0rºmܶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.php¯\ 5\0\0\98Þ\1d\ 5\0\0?=\10Ѷ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpU   \0\0\98Þ\1d^U \0\0\85ß\ f\ f\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.php;3\0\0\98Þ\1d^;3\0\0\98\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.phphq\0\0\98Þ\1d^hq\0\0+a_\11\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php\96\15\0\0\98Þ\1d^\96\15\0\0ù\1cjض\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.phpò\r\0\0\98Þ\1d\r\0\0íA\0Ƕ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.phpñ#\0\0\98Þ\1d^ñ#\0\0p\F\19\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.php¤\14\0\0\98Þ\1d\14\0\0N\9aý\ 5\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpN\v\0\0\98Þ\1d^N\v\0\0Ý\86¤A¶\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phph$\0\0\98Þ\1d^h$\0\0»\89\1dÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0\98Þ\1d^\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php²\13\0\0\98Þ\1d\13\0\0QiÃb¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.phpý6\0\0\98Þ\1d^ý6\0\0ò|-\ f\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0\98Þ\1d^3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.php'\10\0\0\98Þ\1d^'\10\0\0¹Ô\8e¼¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0\98Þ\1d^\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.phpµ\ 3\0\0\98Þ\1d\ 3\0\0\19᫤¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0\98Þ\1d^C\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0\98Þ\1d\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0\98Þ\1d\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0\98Þ\1d\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0\98Þ\1d\ 1\0\0&¢e
28\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0\98Þ\1d^I\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0\98Þ\1d^h\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0\98Þ\1d\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php¯"\0\0\98Þ\1d^¯"\0\0\r ¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.phpú\17\0\0\98Þ\1d\17\0\0\16]D5¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0\98Þ\1d^\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php?\19\0\0\98Þ\1d^?\19\0\0¬\91\9cü¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php\18\ 5\0\0\98Þ\1d^\18\ 5\0\0tZÅɶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
29 \0\0\98Þ\1d
30 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpÊ\1e\0\0\98Þ\1d\1e\0\0D¦õZ¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\11\ 6\0\0\98Þ\1d^\11\ 6\0\0\9bCü$¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0\98Þ\1d^i\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0\98Þ\1d\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.php\ 5\ 4\0\0\98Þ\1d^\ 5\ 4\0\0\8fGd7¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php\9d:\0\0\98Þ\1d^\9d:\0\0æ¯Ép¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\99\ 1\0\0\98Þ\1d^\99\ 1\0\0X\12g6¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpô\a\0\0\98Þ\1d\a\0\0×|Ŧ¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.php×\13\0\0\98Þ\1d\13\0\0Vmì\9f\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.phpÆ      \0\0\98Þ\1d^Æ \0\0G s0¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0\98Þ\1d\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.php`\15\0\0\98Þ\1d^`\15\0\0#ÏX\14\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0\98Þ\1d\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0\98Þ\1d\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.phpG\1c\0\0\98Þ\1d^G\1c\0\0ä\11Oж\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
31 \ 1\0\0\98Þ\1d^
32 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php\82\v\0\0\98Þ\1d^\82\v\0\0Ü\81Ii¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php³6\0\0\98Þ\1d^³6\0\0¦Ü(9¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0\98Þ\1d\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php\94\b\0\0\98Þ\1d^\94\b\0\0ßis̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpé\14\0\0\98Þ\1d\14\0\0$²FQ¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0\98Þ\1d^u\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.php\9e\a\0\0\98Þ\1d^\9e\a\0\0Öüñ9¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0\98Þ\1d\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0\98Þ\1d^\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpG\14\0\0\98Þ\1d^G\14\0\0M#j\1d\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0\98Þ\1d\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0\98Þ\1d^=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0\98Þ\1d\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php¡\16\0\0\98Þ\1d\16\0\0(   à>¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0\98Þ\1d\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.phpk\15\0\0\98Þ\1d^k\15\0\0Òo\94ζ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0\98Þ\1d\ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.php$4\0\0\98Þ\1d^$4\0\0\ 1x\8b\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0\98Þ\1d\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0\98Þ\1d^v\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0\98Þ\1d^f\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.php_=\0\0\98Þ\1d^_=\0\0x"\10Ŷ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.phpõ\11\0\0\98Þ\1d\11\0\0¸´
33\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php¾\ 6\0\0\98Þ\1d\ 6\0\0X~d\1e\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php\1f\19\0\0\98Þ\1d^\1f\19\0\0\1füw·¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0\98Þ\1d\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0\98Þ\1d\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.php\15\9f\0\0\98Þ\1d^\15\9f\0\0亻\ 6\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php
34 \12\0\0\98Þ\1d^
35 \12\0\0t¤{ø¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0\98Þ\1d\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0\98Þ\1d^-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0\98Þ\1d^\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0\98Þ\1d\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0\98Þ\1d\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php%\14\0\0\98Þ\1d^%\14\0\0\f»\8f̶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.phpÊ\a\0\0\98Þ\1d\a\0\0Ùti·¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0\98Þ\1d^+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0\98Þ\1d^e\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0\98Þ\1d\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpø\f\0\0\98Þ\1d\f\0\0\95\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0\98Þ\1d\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\8b\ 6\0\0\98Þ\1d^\8b\ 6\0\0\ fÒX8¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0\98Þ\1d^\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php:\a\0\0\98Þ\1d^:\a\0\0\82´UV¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.php[\14\0\0\98Þ\1d^[\14\0\0°\90Ë\99\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.phpb\ 6\0\0\98Þ\1d^b\ 6\0\0\12ÝN\9a\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.phpÀ3\0\0\98Þ\1d^À3\0\0\90\99 \7f\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0\98Þ\1d^\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php§\17\0\0\98Þ\1d\17\0\0Õ\94R\99\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php      \ 2\0\0\98Þ\1d\ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0\98Þ\1d\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.phpÝ\f\0\0\98Þ\1d\f\0\0í<´B¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0\98Þ\1d^\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0\98Þ\1d^\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0\98Þ\1d^\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpr\ 3\0\0\98Þ\1d^r\ 3\0\03\91Mh¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\v\ 5\0\0\98Þ\1d^\v\ 5\0\0\r\95¦S¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php?\ 6\0\0\98Þ\1d^?\ 6\0\0®\97      u¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php½\ 4\0\0\98Þ\1d\ 4\0\0\82¨¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php\11\ e\0\0\98Þ\1d^\11\ e\0\0D|\9fȶ\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Comparer/Comparer.phpR\b\0\0\98Þ\1d^R\b\0\0Ïسî¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0\98Þ\1d\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0\98Þ\1d\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpW\f\0\0\98Þ\1d^W\f\0\0¿éÁ¦¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0\98Þ\1d^\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0\98Þ\1d^\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0\98Þ\1d^d\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0\98Þ\1d^\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0\98Þ\1d^i\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0\98Þ\1d^X\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.phpN\1e\0\0\98Þ\1d^N\1e\0\0â\ 3Q¬¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0\98Þ\1d^E\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0\98Þ\1d\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0\98Þ\1d\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.phpó\19\0\0\98Þ\1d\19\0\0l\94.ض\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.php(>\0\0\98Þ\1d^(>\0\0\ 6\84´P¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php¥!\0\0\98Þ\1d^¥!\0\0/=xö¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0\98Þ\1d\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php\\b\0\0\98Þ\1d^\\b\0\0xåp¨¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f        \0\0\98Þ\1d^\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0\98Þ\1d^\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0\98Þ\1d\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpÏ!\0\0\98Þ\1d^Ï!\0\0(\94Ü.¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.php¥\ 5\0\0\98Þ\1d\ 5\0\0ô´\16à¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0\98Þ\1d^K\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0\98Þ\1d^W\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0\98Þ\1d^\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0\98Þ\1d^\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0\98Þ\1d\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpö\0\0\0\98Þ\1d\0\0\0á1=z¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0\98Þ\1d\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.phpª$\0\0\98Þ\1d^ª$\0\0m\89\83ä¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Plugin/PreCommandRunEvent.phpõ\ 1\0\0\98Þ\1d\ 1\0\0:ðd\1e\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0\98Þ\1d^`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0\98Þ\1d^\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0\98Þ\1d^\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.phpí\b\0\0\98Þ\1d\b\0\0q9OS¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php\8a\ f\0\0\98Þ\1d^\8a\ f\0\0\13äÝ÷¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php0U\0\0\98Þ\1d^0U\0\0Ã7L\86\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0\98Þ\1d^;\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0\98Þ\1d^\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.phpp\ 5\0\0\98Þ\1d^p\ 5\0\0#\18ù\7f\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0\98Þ\1d\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0\98Þ\1d\0\0\0V
36 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0\98Þ\1d^\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0\98Þ\1d^n\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0\98Þ\1d^j\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.php¡\f\0\0\98Þ\1d\f\0\0\vXWL¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0\98Þ\1d^I\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0\98Þ\1d\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0\98Þ\1d\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.php®        \0\0\98Þ\1d^® \0\0\99ÖÛú¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0\98Þ\1d^& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0\98Þ\1d^q\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0\98Þ\1d^q\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0\98Þ\1d^\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0\98Þ\1d\ 3\0\0\9f\r¸\f\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ReleaseInfo.php\92\ 1\0\0\98Þ\1d^\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0\98Þ\1d\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.phpå\1f\0\0\98Þ\1d\1f\0\0»G÷å¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php`\12\0\0\98Þ\1d^`\12\0\0K¾du¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0\98Þ\1d\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php2
37 \0\0\98Þ\1d^2
38 \0\0á\855#¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0\98Þ\1d^o\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.php\95 \0\0\98Þ\1d^\95 \0\0$©Rç¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php³\13\0\0\98Þ\1d\13\0\0ÐCk\ 3\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpë\ 5\0\0\98Þ\1d\ 5\0\0\9c´½X¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.php\90\12\0\0\98Þ\1d^\90\12\0\0ù\13\96\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.php})\0\0\98Þ\1d^})\0\0ê¦x®¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.php]%\0\0\98Þ\1d^]%\0\0sÇø\r\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpå\ 5\0\0\98Þ\1d\ 5\0\0@)\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpB\12\0\0\98Þ\1d^B\12\0\0»\7f\83î¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.phpù     \0\0\98Þ\1d^ù \0\0&½tÙ¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php¤\1c\0\0\98Þ\1d\1c\0\0\1e\11\1f\f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
39 \0\0\98Þ\1d
40 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0\98Þ\1d\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.phpÙ*\0\0\98Þ\1d^Ù*\0\0~Á£f¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/VersionCacheInterface.php\94\0\0\0\98Þ\1d^\94\0\0\0A?Rï¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0\98Þ\1d^\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0\98Þ\1d^\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0\98Þ\1d^W\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpº\ 4\0\0\98Þ\1d\ 4\0\0ò\9d»¤¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0\98Þ\1d^\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0\98Þ\1d^P\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0\98Þ\1d^\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0\98Þ\1d\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0\98Þ\1d\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php*\15\0\0\98Þ\1d^*\15\0\0,L\9a\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0\98Þ\1d\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.php÷\13\0\0\98Þ\1d\13\0\0v\95Í\ 4\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php»\ 4\0\0\98Þ\1d\ 4\0\0O\9brk¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.phpr/\0\0\98Þ\1d^r/\0\0\eÒ^j¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.php<.\0\0\98Þ\1d^<.\0\0*%\9bû¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.php|\r\0\0\98Þ\1d^|\r\0\0`0tü¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php¬\r\0\0\98Þ\1d\r\0\0B3\vë¶\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Util/Hg.php¾\a\0\0\98Þ\1d\a\0\0\f\9d\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.phph\ 2\0\0\98Þ\1d^h\ 2\0\0;F\b\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0\98Þ\1d\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Util/PackageSorter.phpÞ\ 5\0\0\98Þ\1d\ 5\0\0ê×ìY¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php¸2\0\0\98Þ\1d^¸2\0\0Ás&}¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0\98Þ\1d\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.php$\r\0\0\98Þ\1d^$\r\0\0¨Nó\1e\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.phpøn\0\0\98Þ\1d^øn\0\0?\9b\1a\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpé\ 2\0\0\98Þ\1d\ 2\0\0\93Vjf¶\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0\98Þ\1d^\ 3\ 1\0\0¾7
41 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.php\ 6\10\0\0\98Þ\1d^\ 6\10\0\0\85ù¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php,\14\0\0\98Þ\1d^,\14\0\0Ì\r\9eĶ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpL
42 \0\0\98Þ\1d^L
43 \0\0"\fi\1e\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Url.php£\a\0\0\98Þ\1d\a\0\03\9cÉܶ\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Zip.php´\ 5\0\0\98Þ\1d\ 5\0\0°\ 4³¶¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.phpð\ 1\0\0\98Þ\1d\ 1\0\0zÓf~¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0\98Þ\1d\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.php\934\0\0\98Þ\1d^\934\0\0²z\8d\96\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0\98Þ\1d\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.json!\98\0\0\98Þ\1d^!\98\0\0CF¶±¶\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.json%
44 \0\0\98Þ\1d^%
45 \0\0ïBð\a\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.jsonÓ\98\0\0\98Þ\1d\98\0\0Id¤÷¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Resources/bin/hiddeninput.exe\0$\0\0\98Þ\1d^\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php=X\0\0\98Þ\1d^=X\0\0\8f S\92\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.phpî"\0\0\98Þ\1d^î"\0\0x°jÕ¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpØ\a\0\0\98Þ\1d\a\0\0¦Ú-:¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0\98Þ\1d^Z\b\0\0»w\ 4\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpé\0\0\0\98Þ\1d\0\0\0RÛÔe¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpÐ\b\0\0\98Þ\1d\b\0\0\99\8e5°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\8f\a\0\0\98Þ\1d^\8f\a\0\0¿N\ f\95\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0\98Þ\1d\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpÜ\r\0\0\98Þ\1d\r\0\0\9dɶ\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¶\ e\0\0\98Þ\1d\ e\0\0·Ô;ݶ\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php¼\1e\0\0\98Þ\1d\1e\0\0òç\ 6\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ 1\1c\0\0\98Þ\1d^\ 1\1c\0\0\7fb{<¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php°\ 1\0\0\98Þ\1d\ 1\0\0\a!\0ȶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0\98Þ\1d\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0\98Þ\1d^\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0\98Þ\1d^z\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0\98Þ\1d\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0\98Þ\1d^f\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0\98Þ\1d\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0\98Þ\1d\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0\98Þ\1d^\92\0\0\0ÍO\e¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/console/Exception/RuntimeException.php\96\0\0\0\98Þ\1d^\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php6\ e\0\0\98Þ\1d^6\ e\0\0?=¨\ 4\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0\98Þ\1d^\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpF\10\0\0\98Þ\1d^F\10\0\0\1d𦴶\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\84\ 1\0\0\98Þ\1d^\84\ 1\0\0÷½\10\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.php@\ 5\0\0\98Þ\1d^@\ 5\0\0G¨ýU¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpy\b\0\0\98Þ\1d^y\b\0\0Ì8Æж\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpw\ 5\0\0\98Þ\1d^w\ 5\0\0\ 1\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.php\ 3\1f\0\0\98Þ\1d^\ 3\1f\0\0¹ÜÃ_¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpd\ 4\0\0\98Þ\1d^d\ 4\0\0§×,¸¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php«\a\0\0\98Þ\1d\a\0\0!\90§\97\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpå\0\0\0\98Þ\1d\0\0\0\1f\8a \18\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÊ\a\0\0\98Þ\1d\a\0\0áÏW"¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0\98Þ\1d^c\ 1\0\0\ 6Ìø\83\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÓ      \0\0\98Þ\1d^Ó \0\0©w\82\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phpl%\0\0\98Þ\1d^l%\0\0 díÛ¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php]\e\0\0\98Þ\1d^]\e\0\0ù»\89\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpN\14\0\0\98Þ\1d^N\14\0\0ÿ§³l¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.phpl\1d\0\0\98Þ\1d^l\1d\0\0Nt\bó¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.php\96
46 \0\0\98Þ\1d^\96
47 \0\0-\fØ\1a\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.phpÄ*\0\0\98Þ\1d^Ä*\0\0¾\99ØT¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\81\ 3\0\0\98Þ\1d^\81\ 3\0\0å\16V^¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\ e\f\0\0\98Þ\1d^\ e\f\0\0\9b\99\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÊ\0\0\0\98Þ\1d\0\0\0az\1f\1c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php 
48 \0\0\98Þ\1d
49 \0\0_ÍI"¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\ f\16\0\0\98Þ\1d^\ f\16\0\0×ö\86\9b\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php)\v\0\0\98Þ\1d^)\v\0\0¥Ñ\ 6\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.php£\v\0\0\98Þ\1d\v\0\0\13f¡?¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\12\ 6\0\0\98Þ\1d^\12\ 6\0\0D\r£\ 6\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\98\0\0\0\98Þ\1d^\98\0\0\0­\ fO°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\86\19\0\0\98Þ\1d^\86\19\0\0¤U)¤¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php£\ 3\0\0\98Þ\1d\ 3\0\0ÆB\8c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\14\f\0\0\98Þ\1d^\14\f\0\0\¢Ü=¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\9a\ 6\0\0\98Þ\1d^\9a\ 6\0\0\9eµ\rè¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php0    \0\0\98Þ\1d^0 \0\0\85\8d\r¸¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.php_\ 1\0\0\98Þ\1d^_\ 1\0\0\8b >P¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.php±\a\0\0\98Þ\1d\a\0\0nì!f¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpà\0\0\0\98Þ\1d\0\0\0\87\86Æʶ\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0\98Þ\1d\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\98  \0\0\98Þ\1d^\98 \0\00p\ 4\b\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\17\ 3\0\0\98Þ\1d^\17\ 3\0\0\0ì\ 6\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.php\9d\ 6\0\0\98Þ\1d^\9d\ 6\0\0Ä\92Oç¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpx
50 \0\0\98Þ\1d^x
51 \0\0W\16\80\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpè\ 2\0\0\98Þ\1d\ 2\0\0/\1dÔ\8f\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.phpΠ    \0\0\98Þ\1d^Π\0\0lF\ f\10\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpæ\ f\0\0\98Þ\1d\ f\0\0¼XÒA¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php\\ 5\0\0\98Þ\1d^\\ 5\0\0wפ\ 4\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÏ\ 3\0\0\98Þ\1d\ 3\0\0&nÅѶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.phpä\1f\0\0\98Þ\1d\1f\0\0­å (¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÏ\ 5\0\0\98Þ\1d\ 5\0\0s\9e9i¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.phpª\ 6\0\0\98Þ\1d\ 6\0\0¬K\f\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0\98Þ\1d^t\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.php,\ 3\0\0\98Þ\1d^,\ 3\0\0Ë~\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.phpµ\1d\0\0\98Þ\1d\1d\0\01rEÓ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\1dH\0\0\98Þ\1d^\1dH\0\0¹:D#¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\96\ 1\0\0\98Þ\1d^\96\ 1\0\0i\89æô¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0\98Þ\1d^\98\ 1\0\0-
52 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0\98Þ\1d^\ 2\ 1\0\0®+Ãê¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.php\ e\a\0\0\98Þ\1d^\ e\a\0\0\e\17\99Ķ\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpW\ 2\0\0\98Þ\1d^W\ 2\0\0?àèK¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php¼\16\0\0\98Þ\1d\16\0\0\11\15\f׶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0\98Þ\1d^~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\9a\ 1\0\0\98Þ\1d^\9a\ 1\0\0\81ñJÀ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\98\ 1\0\0\98Þ\1d^\98\ 1\0\0nöêض\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php)3\0\0\98Þ\1d^)3\0\0\81h5=¶\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.phpA\12\0\0\98Þ\1d^A\12\0\0Ϥ¹l¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0\98Þ\1d^\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpx\b\0\0\98Þ\1d^x\b\0\0~ò"\7f\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpO\ 5\0\0\98Þ\1d^O\ 5\0\0\8d\9e¦*¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0\98Þ\1d^i\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0\98Þ\1d\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0\98Þ\1d^\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0\98Þ\1d\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.phpc4\0\0\98Þ\1d^c4\0\0\8b×@þ¶\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.phpö\ 5\0\0\98Þ\1d\ 5\0\0\9fZµ1¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0\98Þ\1d^\\v\0\0h\19\88\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\8f\19\0\0\98Þ\1d^\8f\19\0\0HC\80\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php\9b\ 3\0\0\98Þ\1d^\9b\ 3\0\0M\aþ\e\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php3\a\0\0\98Þ\1d^3\a\0\075$·¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0\98Þ\1d^\15\a\0\0\9f\1c`]¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0\98Þ\1d\a\0\0Þdè;¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8d\ 3\0\0\98Þ\1d^\8d\ 3\0\0¾ü\9cµ¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php#\ 3\0\0\98Þ\1d^#\ 3\0\0\16°\1fζ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php|\ 3\0\0\98Þ\1d^|\ 3\0\0ITÇͶ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0\98Þ\1d^\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¬\ 2\0\0\98Þ\1d\ 2\0\0w\1e\18\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0\98Þ\1d^\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0\98Þ\1d^)\ 1\0\0x\1f§e¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpº\ 2\0\0\98Þ\1d\ 2\0\0\98þ\15\98\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0\98Þ\1d^\a\ 6\0\0i¥:Ŷ\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpf\ 4\0\0\98Þ\1d^f\ 4\0\0DÞcj¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 4\ f\0\0\98Þ\1d^\ 4\ f\0\0ü(Ã϶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0\98Þ\1d\ 1\0\0\p4\86\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.phpc.\0\0\98Þ\1d^c.\0\0:\885g¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpL\ 5\0\0\98Þ\1d^L\ 5\0\0jÍ9׶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php]\ 2\0\0\98Þ\1d^]\ 2\0\0ÎoÅƶ\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpx\ 2\0\0\98Þ\1d^x\ 2\0\0\ fô\ 3\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpî\ 1\0\0\98Þ\1d\ 1\0\0üÍ\9d\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpí\ 5\0\0\98Þ\1d\ 5\0\0n\ 5õH¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php#\ 6\0\0\98Þ\1d^#\ 6\0\0G?T½¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpZ\ 2\0\0\98Þ\1d^Z\ 2\0\0(\1a&ø¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0\98Þ\1d^5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0\98Þ\1d^r\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0\98Þ\1d\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php-\ 5\0\0\98Þ\1d^-\ 5\0\0ºÎÒ_¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÐ\ 1\0\0\98Þ\1d\ 1\0\0\12\82\b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\15   \0\0\98Þ\1d^\15 \0\0ë]í»¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpe\ 2\0\0\98Þ\1d^e\ 2\0\0\9f\92áé¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php+\ 6\0\0\98Þ\1d^+\ 6\0\0õÝË ¶\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.php>\v\0\0\98Þ\1d^>\v\0\0_~u\f\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpr\ 4\0\0\98Þ\1d^r\ 4\0\0þ\1dpN¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.php\ 6\ 3\0\0\98Þ\1d^\ 6\ 3\0\0þ\0íù¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/polyfill-ctype/Ctype.phpH   \0\0\98Þ\1d^H \0\0³\9dÕݶ\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/polyfill-ctype/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0´`e0¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/polyfill-ctype/bootstrap.phpI\ 3\0\0\98Þ\1d^I\ 3\0\0\8fD!e¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0\1f\93\ª¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.php\19G\0\0\98Þ\1d^\19G\0\0ÉS|G¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php÷@\0\0\98Þ\1d^÷@\0\0õ\10\9eض\ 1\0\0\0\0\0\0F\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpã\17\0\0\98Þ\1d\17\0\0öy_\95\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpfA\0\0\98Þ\1d^fA\0\0Úf\94߶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php\82\11\0\0\98Þ\1d^\82\11\0\0À\91 \8a\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0\98Þ\1d^f\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0\98Þ\1d\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0\98Þ\1d^\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0\98Þ\1d^x\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0\98Þ\1d^\1f\ 4\0\0\7fï\ e«¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0\98Þ\1d^\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9d\ 4\0\0\98Þ\1d^\9d\ 4\0\0ûus\80\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpÏ\ 4\0\0\98Þ\1d\ 4\0\0Î%h\1c\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpü\ 3\0\0\98Þ\1d\ 3\0\0\87jûü¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php½\a\0\0\98Þ\1d\a\0\0æ\18\86\ 1\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0\98Þ\1d^D\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.php>\b\0\0\98Þ\1d^>\b\0\0ª\95ir¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.phpp\f\0\0\98Þ\1d^p\f\0\0âU~ɶ\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php·R\0\0\98Þ\1d^·R\0\0\8a\18`Õ¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpâ
53 \0\0\98Þ\1d
54 \0\0\86\1eM¶¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpQ\ 6\0\0\98Þ\1d^Q\ 6\0\0b-$m¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0\98Þ\1d^"\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0\98Þ\1d^*\ 1\0\0\19\95pñ¶\ 1\0\0\0\0\0\05\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php82\0\0\98Þ\1d^82\0\0ªÃZt¶\ 1\0\0\0\0\0\00\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php\ 6\ f\0\0\98Þ\1d^\ 6\ f\0\0%ÿ3N¶\ 1\0\0\0\0\0\0;\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php\1e\ 1\0\0\98Þ\1d^\1e\ 1\0\0\89²\10ñ¶\ 1\0\0\0\0\0\04\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php>\0\0\0\98Þ\1d^>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0\98Þ\1d\ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0\98Þ\1d\ 1\0\0f\e\12\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php¡      \0\0\98Þ\1d^¡ \0\0\86wÌl¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php\8f
55 \0\0\98Þ\1d^\8f
56 \0\0ÍèÓ¯¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php§\r\0\0\98Þ\1d\r\0\0\9b\18\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php¼\ 1\0\0\98Þ\1d\ 1\0\0ÿ Q\9c\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php]\ 3\0\0\98Þ\1d^]\ 3\0\0V\8eU<¶\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.phpã\f\0\0\98Þ\1d\f\0\0á0;\16\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php\85\14\0\0\98Þ\1d^\85\14\0\0\93T\9cÚ¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php\87       \0\0\98Þ\1d^\87 \0\0ï\9b\18\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.phpÃ\11\0\0\98Þ\1d\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php0 \0\0\98Þ\1d^0 \0\0×j´\98\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php\7f\ 4\0\0\98Þ\1d^\7f\ 4\0\0¥w\9a\87\ 1\0\0\0\0\0\0X\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.phpa\ 4\0\0\98Þ\1d^a\ 4\0\0\v     qö\ 1\0\0\0\0\0\0Y\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php\97\ 2\0\0\98Þ\1d^\97\ 2\0\04~¾ ¶\ 1\0\0\0\0\0\0\\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php\89\ 1\0\0\98Þ\1d^\89\ 1\0\0\93µ+j¶\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php&\ f\0\0\98Þ\1d^&\ f\0\04\98©T¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.phpa"\0\0\98Þ\1d^a"\0\0\8fMÙë¶\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0\98Þ\1d\ 6\0\0\ 6{N\96\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.phpI\0\0\0\98Þ\1d^I\0\0\0%|\19°¶\ 1\0\0\0\0\0\0V\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php\95\0\0\0\98Þ\1d^\95\0\0\0\8bàG\ 5\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.phpl\0\0\0\98Þ\1d^l\0\0\0A!L׶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.phpl\0\0\0\98Þ\1d^l\0\0\0è2÷þ¶\ 1\0\0\0\0\0\0]\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.phpu\0\0\0\98Þ\1d^u\0\0\0=hç\a\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.phpw\0\0\0\98Þ\1d^w\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0\98Þ\1d\ 2\0\0\r
57\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0\98Þ\1d^o\0\0\0píÛù¶\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php\85\0\0\0\98Þ\1d^\85\0\0\0\b%\85\97\ 1\0\0\0\0\0\0^\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php\80\0\0\0\98Þ\1d^\80\0\0\0u-#1¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpj\0\0\0\98Þ\1d^j\0\0\0å\1a>\8f\ 1\0\0\0\0\0\0Q\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.phpf\0\0\0\98Þ\1d^f\0\0\0¬¤\84þ¶\ 1\0\0\0\0\0\0K\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.phpþ\ 5\0\0\98Þ\1d\ 5\0\0M\8f\84õ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php \ 2\0\0\98Þ\1d\ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\9c\r\0\0\98Þ\1d^\9c\r\0\0\ 2åfO¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php\ 1\ 1\0\0\98Þ\1d^\ 1\ 1\0\0o\8a+}¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.phpá\0\0\0\98Þ\1d\0\0\0[þA\81\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php¥\ 4\0\0\98Þ\1d\ 4\0\0Ô§Lb¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php%\ 5\0\0\98Þ\1d^%\ 5\0\05"\10 ¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php,\ 2\0\0\98Þ\1d^,\ 2\0\01\955þ¶\ 1\0\0\0\0\0\0X\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php®\0\0\0\98Þ\1d\0\0\0ÿ\8bÁå¶\ 1\0\0\0\0\0\0C\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php\ 5\v\0\0\98Þ\1d^\ 5\v\0\0£\9f)à¶\ 1\0\0\0\0\0\0D\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.phpF\14\0\0\98Þ\1d^F\14\0\0¨IaD¶\ 1\0\0\0\0\0\0H\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php\83\0\0\0\98Þ\1d^\83\0\0\0\12J\80\1f\ 1\0\0\0\0\0\0I\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php\85\0\0\0\98Þ\1d^\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpv\ 5\0\0\98Þ\1d^v\ 5\0\0õÍ\ 5\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0\98Þ\1d^\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpH\14\0\0\98Þ\1d^H\14\0\0Í\89T\ 4\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0\98Þ\1d^\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0\98Þ\1d^\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.phpî\ 2\0\0\98Þ\1d\ 2\0\0Õ­w-¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.php\92\f\0\0\98Þ\1d^\92\f\0\0I\ f&â¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0\98Þ\1d\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpä\ 1\0\0\98Þ\1d\ 1\0\0ïõ\82³¶\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php,\ 5\0\0\98Þ\1d^,\ 5\0\0\ 2\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.php\82\ 6\0\0\98Þ\1d^\82\ 6\0\0?n\1aݶ\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¸*\0\0\98Þ\1d^¸*\0\0GLÇí¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0\98Þ\1d^\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.phpç\1d\0\0\98Þ\1d\1d\0\0\ 1ë¶\ 1\0\0\0\0\0\0&\0\0\0vendor/composer/xdebug-handler/LICENSE)\ 4\0\0\98Þ\1d^)\ 4\0\0#Ô;^¶\ 1\0\0\0\0\0\00\0\0\0vendor/composer/xdebug-handler/src/PhpConfig.php´\ 2\0\0\98Þ\1d\ 2\0\0*D\92\0\ 1\0\0\0\0\0\0.\0\0\0vendor/composer/xdebug-handler/src/Process.phpp   \0\0\98Þ\1d^p \0\0i,i\91\ 1\0\0\0\0\0\0-\0\0\0vendor/composer/xdebug-handler/src/Status.php\ f
58 \0\0\98Þ\1d^\ f
59 \0\0$\9fv-¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/xdebug-handler/src/XdebugHandler.php/!\0\0\98Þ\1d^/!\0\0L)-&¶\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0\98Þ\1d^=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0\98Þ\1d^;\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0\98Þ\1d^`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0\98Þ\1d\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0\98Þ\1d^|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0\98Þ\1d\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÈ\ 2\0\0\98Þ\1d\ 2\0\0\9a\1fx\1d\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpk\ 4\0\0\98Þ\1d^k\ 4\0\0£}\89\92\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php \0\0\0\98Þ\1d\0\0\0ÆDi¯¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.phpj\r\0\0\98Þ\1d^j\r\0\0Nÿ\11\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/Test/TestLogger.php<\b\0\0\98Þ\1d^<\b\0\0þ(åI¶\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0\98Þ\1d^\82\0\0\0Öf¤@¶\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0\98Þ\1d^d\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php÷\ 4\0\0\98Þ\1d\ 4\0\0Å*\9a\16\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0\98Þ\1d^d\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.php\1f\ 1\0\0\98Þ\1d^\1f\ 1\0\0¥\0 ®¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0\98Þ\1d^I\a\0\0þ\15ö,¶\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php§
60 \0\0\98Þ\1d
61 \0\0\9cç(»¶\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php¨\18\0\0\98Þ\1d\18\0\0xää`¶\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pemÇi\ 3\0\98Þ\1d^Çi\ 3\0\9f\87\ 1\0\0\0\0\0\0\f\0\0\0bin/composerÊ\ 6\0\0\98Þ\1d\ 6\0\0ÿêP\17\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0\98Þ\1d^.\ 4\0\0 Õ\b\ 3\ 1\0\0\0\0\0\0<?php
62
63
64
65
66
67
68
69
70
71
72
73 namespace Composer\Autoload;
74
75 use Composer\Config;
76 use Composer\EventDispatcher\EventDispatcher;
77 use Composer\Installer\InstallationManager;
78 use Composer\IO\IOInterface;
79 use Composer\Package\AliasPackage;
80 use Composer\Package\PackageInterface;
81 use Composer\Repository\InstalledRepositoryInterface;
82 use Composer\Util\Filesystem;
83 use Composer\Script\ScriptEvents;
84 use Composer\Util\PackageSorter;
85
86
87
88
89
90 class AutoloadGenerator
91 {
92
93
94
95 private $eventDispatcher;
96
97
98
99
100 private $io;
101
102
103
104
105 private $devMode = false;
106
107
108
109
110 private $classMapAuthoritative = false;
111
112
113
114
115 private $apcu = false;
116
117
118
119
120 private $runScripts = false;
121
122 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
123 {
124 $this->eventDispatcher = $eventDispatcher;
125 $this->io = $io;
126 }
127
128 public function setDevMode($devMode = true)
129 {
130 $this->devMode = (bool) $devMode;
131 }
132
133
134
135
136
137
138
139 public function setClassMapAuthoritative($classMapAuthoritative)
140 {
141 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
142 }
143
144
145
146
147
148
149 public function setApcu($apcu)
150 {
151 $this->apcu = (bool) $apcu;
152 }
153
154
155
156
157
158
159 public function setRunScripts($runScripts = true)
160 {
161 $this->runScripts = (bool) $runScripts;
162 }
163
164 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
165 {
166 if ($this->classMapAuthoritative) {
167
168  $scanPsr0Packages = true;
169 }
170 if ($this->runScripts) {
171 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
172 'optimize' => (bool) $scanPsr0Packages,
173 ));
174 }
175
176 $filesystem = new Filesystem();
177 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
178
179  
180  
181  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
182 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
183 $useGlobalIncludePath = (bool) $config->get('use-include-path');
184 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
185 $targetDir = $vendorPath.'/'.$targetDir;
186 $filesystem->ensureDirectoryExists($targetDir);
187
188 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
189 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
190 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
191
192 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
193 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
194
195 $namespacesFile = <<<EOF
196 <?php
197
198 // autoload_namespaces.php @generated by Composer
199
200 \$vendorDir = $vendorPathCode52;
201 \$baseDir = $appBaseDirCode;
202
203 return array(
204
205 EOF;
206
207 $psr4File = <<<EOF
208 <?php
209
210 // autoload_psr4.php @generated by Composer
211
212 \$vendorDir = $vendorPathCode52;
213 \$baseDir = $appBaseDirCode;
214
215 return array(
216
217 EOF;
218
219
220  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
221 $autoloads = $this->parseAutoloads($packageMap, $mainPackage, $this->devMode === false);
222
223
224  foreach ($autoloads['psr-0'] as $namespace => $paths) {
225 $exportedPaths = array();
226 foreach ($paths as $path) {
227 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
228 }
229 $exportedPrefix = var_export($namespace, true);
230 $namespacesFile .= "    $exportedPrefix => ";
231 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
232 }
233 $namespacesFile .= ");\n";
234
235
236  foreach ($autoloads['psr-4'] as $namespace => $paths) {
237 $exportedPaths = array();
238 foreach ($paths as $path) {
239 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
240 }
241 $exportedPrefix = var_export($namespace, true);
242 $psr4File .= "    $exportedPrefix => ";
243 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
244 }
245 $psr4File .= ");\n";
246
247 $classmapFile = <<<EOF
248 <?php
249
250 // autoload_classmap.php @generated by Composer
251
252 \$vendorDir = $vendorPathCode52;
253 \$baseDir = $appBaseDirCode;
254
255 return array(
256
257 EOF;
258
259
260  $targetDirLoader = null;
261 $mainAutoload = $mainPackage->getAutoload();
262 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
263 $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
264 $prefixes = implode(', ', array_map(function ($prefix) {
265 return var_export($prefix, true);
266 }, array_keys($mainAutoload['psr-0'])));
267 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
268
269 $targetDirLoader = <<<EOF
270
271     public static function autoload(\$class)
272     {
273         \$dir = $baseDirFromTargetDirCode . '/';
274         \$prefixes = array($prefixes);
275         foreach (\$prefixes as \$prefix) {
276             if (0 !== strpos(\$class, \$prefix)) {
277                 continue;
278             }
279             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
280             if (!\$path = stream_resolve_include_path(\$path)) {
281                 return false;
282             }
283             require \$path;
284
285             return true;
286         }
287     }
288
289 EOF;
290 }
291
292 $blacklist = null;
293 if (!empty($autoloads['exclude-from-classmap'])) {
294 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
295 }
296
297
298  $classMap = array();
299 if ($scanPsr0Packages) {
300 $namespacesToScan = array();
301
302
303  foreach (array('psr-0', 'psr-4') as $psrType) {
304 foreach ($autoloads[$psrType] as $namespace => $paths) {
305 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
306 }
307 }
308
309 krsort($namespacesToScan);
310
311 foreach ($namespacesToScan as $namespace => $groups) {
312 foreach ($groups as $group) {
313 foreach ($group['paths'] as $dir) {
314 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
315 if (!is_dir($dir)) {
316 continue;
317 }
318
319 $namespaceFilter = $namespace === '' ? null : $namespace;
320 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
321 }
322 }
323 }
324 }
325
326 foreach ($autoloads['classmap'] as $dir) {
327 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
328 }
329
330 ksort($classMap);
331 foreach ($classMap as $class => $code) {
332 $classmapFile .= '    '.var_export($class, true).' => '.$code;
333 }
334 $classmapFile .= ");\n";
335
336 if (!$suffix) {
337 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
338 $content = file_get_contents($vendorPath.'/autoload.php');
339 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
340 $suffix = $match[1];
341 }
342 }
343
344 if (!$suffix) {
345 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
346 }
347 }
348
349 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
350 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
351 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
352 $includePathFilePath = $targetDir.'/include_paths.php';
353 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
354 file_put_contents($includePathFilePath, $includePathFileContents);
355 } elseif (file_exists($includePathFilePath)) {
356 unlink($includePathFilePath);
357 }
358 $includeFilesFilePath = $targetDir.'/autoload_files.php';
359 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
360 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
361 } elseif (file_exists($includeFilesFilePath)) {
362 unlink($includeFilesFilePath);
363 }
364 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
365 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
366 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
367
368 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
369 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
370
371 if ($this->runScripts) {
372 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
373 'optimize' => (bool) $scanPsr0Packages,
374 ));
375 }
376
377 return count($classMap);
378 }
379
380 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
381 {
382 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
383 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
384 if (!isset($classMap[$class])) {
385 $classMap[$class] = $pathCode;
386 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
387 $this->io->writeError(
388 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
389 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
390 );
391 }
392 }
393
394 return $classMap;
395 }
396
397 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
398 {
399 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
400 }
401
402 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
403 {
404
405  $packageMap = array(array($mainPackage, ''));
406
407 foreach ($packages as $package) {
408 if ($package instanceof AliasPackage) {
409 continue;
410 }
411 $this->validatePackage($package);
412
413 $packageMap[] = array(
414 $package,
415 $installationManager->getInstallPath($package),
416 );
417 }
418
419 return $packageMap;
420 }
421
422
423
424
425
426
427 protected function validatePackage(PackageInterface $package)
428 {
429 $autoload = $package->getAutoload();
430 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
431 $name = $package->getName();
432 $package->getTargetDir();
433 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
434 }
435 if (!empty($autoload['psr-4'])) {
436 foreach ($autoload['psr-4'] as $namespace => $dirs) {
437 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
438 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
439 }
440 }
441 }
442 }
443
444
445
446
447
448
449
450
451
452 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage, $filterOutRequireDevPackages = false)
453 {
454 $mainPackageMap = array_shift($packageMap);
455 if ($filterOutRequireDevPackages) {
456 $packageMap = $this->filterPackageMap($packageMap, $mainPackage);
457 }
458 $sortedPackageMap = $this->sortPackageMap($packageMap);
459 $sortedPackageMap[] = $mainPackageMap;
460 array_unshift($packageMap, $mainPackageMap);
461
462 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
463 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
464 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
465 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
466 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
467
468 krsort($psr0);
469 krsort($psr4);
470
471 return array(
472 'psr-0' => $psr0,
473 'psr-4' => $psr4,
474 'classmap' => $classmap,
475 'files' => $files,
476 'exclude-from-classmap' => $exclude,
477 );
478 }
479
480
481
482
483
484
485
486 public function createLoader(array $autoloads)
487 {
488 $loader = new ClassLoader();
489
490 if (isset($autoloads['psr-0'])) {
491 foreach ($autoloads['psr-0'] as $namespace => $path) {
492 $loader->add($namespace, $path);
493 }
494 }
495
496 if (isset($autoloads['psr-4'])) {
497 foreach ($autoloads['psr-4'] as $namespace => $path) {
498 $loader->addPsr4($namespace, $path);
499 }
500 }
501
502 if (isset($autoloads['classmap'])) {
503 $blacklist = null;
504 if (!empty($autoloads['exclude-from-classmap'])) {
505 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
506 }
507
508 foreach ($autoloads['classmap'] as $dir) {
509 try {
510 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
511 } catch (\RuntimeException $e) {
512 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
513 }
514 }
515 }
516
517 return $loader;
518 }
519
520 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
521 {
522 $includePaths = array();
523
524 foreach ($packageMap as $item) {
525 list($package, $installPath) = $item;
526
527 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
528 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
529 }
530
531 foreach ($package->getIncludePaths() as $includePath) {
532 $includePath = trim($includePath, '/');
533 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
534 }
535 }
536
537 if (!$includePaths) {
538 return;
539 }
540
541 $includePathsCode = '';
542 foreach ($includePaths as $path) {
543 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
544 }
545
546 return <<<EOF
547 <?php
548
549 // include_paths.php @generated by Composer
550
551 \$vendorDir = $vendorPathCode;
552 \$baseDir = $appBaseDirCode;
553
554 return array(
555 $includePathsCode);
556
557 EOF;
558 }
559
560 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
561 {
562 $filesCode = '';
563 foreach ($files as $fileIdentifier => $functionFile) {
564 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
565 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
566 }
567
568 if (!$filesCode) {
569 return false;
570 }
571
572 return <<<EOF
573 <?php
574
575 // autoload_files.php @generated by Composer
576
577 \$vendorDir = $vendorPathCode;
578 \$baseDir = $appBaseDirCode;
579
580 return array(
581 $filesCode);
582
583 EOF;
584 }
585
586 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
587 {
588 if (!$filesystem->isAbsolutePath($path)) {
589 $path = $basePath . '/' . $path;
590 }
591 $path = $filesystem->normalizePath($path);
592
593 $baseDir = '';
594 if (strpos($path.'/', $vendorPath.'/') === 0) {
595 $path = substr($path, strlen($vendorPath));
596 $baseDir = '$vendorDir';
597
598 if ($path !== false) {
599 $baseDir .= " . ";
600 }
601 } else {
602 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
603 if (!$filesystem->isAbsolutePath($path)) {
604 $baseDir = '$baseDir . ';
605 $path = '/' . $path;
606 }
607 }
608
609 if (strpos($path, '.phar') !== false) {
610 $baseDir = "'phar://' . " . $baseDir;
611 }
612
613 return $baseDir . (($path !== false) ? var_export($path, true) : "");
614 }
615
616 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
617 {
618 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
619 if ("'" === $lastChar || '"' === $lastChar) {
620 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
621 } else {
622 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
623 }
624
625 return <<<AUTOLOAD
626 <?php
627
628 // autoload.php @generated by Composer
629
630 require_once $vendorPathToTargetDirCode;
631
632 return ComposerAutoloaderInit$suffix::getLoader();
633
634 AUTOLOAD;
635 }
636
637 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
638 {
639 $file = <<<HEADER
640 <?php
641
642 // autoload_real.php @generated by Composer
643
644 class ComposerAutoloaderInit$suffix
645 {
646     private static \$loader;
647
648     public static function loadClassLoader(\$class)
649     {
650         if ('Composer\\Autoload\\ClassLoader' === \$class) {
651             require __DIR__ . '/ClassLoader.php';
652         }
653     }
654
655     public static function getLoader()
656     {
657         if (null !== self::\$loader) {
658             return self::\$loader;
659         }
660
661         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
662         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
663         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
664
665
666 HEADER;
667
668 if ($useIncludePath) {
669 $file .= <<<'INCLUDE_PATH'
670         $includePaths = require __DIR__ . '/include_paths.php';
671         $includePaths[] = get_include_path();
672         set_include_path(implode(PATH_SEPARATOR, $includePaths));
673
674
675 INCLUDE_PATH;
676 }
677
678 $file .= <<<STATIC_INIT
679         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
680         if (\$useStaticLoader) {
681             require_once __DIR__ . '/autoload_static.php';
682
683             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
684         } else {
685
686 STATIC_INIT;
687
688 if (!$this->classMapAuthoritative) {
689 $file .= <<<'PSR04'
690             $map = require __DIR__ . '/autoload_namespaces.php';
691             foreach ($map as $namespace => $path) {
692                 $loader->set($namespace, $path);
693             }
694
695             $map = require __DIR__ . '/autoload_psr4.php';
696             foreach ($map as $namespace => $path) {
697                 $loader->setPsr4($namespace, $path);
698             }
699
700
701 PSR04;
702 }
703
704 if ($useClassMap) {
705 $file .= <<<'CLASSMAP'
706             $classMap = require __DIR__ . '/autoload_classmap.php';
707             if ($classMap) {
708                 $loader->addClassMap($classMap);
709             }
710
711 CLASSMAP;
712 }
713
714 $file .= "        }\n\n";
715
716 if ($this->classMapAuthoritative) {
717 $file .= <<<'CLASSMAPAUTHORITATIVE'
718         $loader->setClassMapAuthoritative(true);
719
720 CLASSMAPAUTHORITATIVE;
721 }
722
723 if ($this->apcu) {
724 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
725 $file .= <<<APCU
726         \$loader->setApcuPrefix('$apcuPrefix');
727
728 APCU;
729 }
730
731 if ($useGlobalIncludePath) {
732 $file .= <<<'INCLUDEPATH'
733         $loader->setUseIncludePath(true);
734
735 INCLUDEPATH;
736 }
737
738 if ($targetDirLoader) {
739 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
740         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
741
742
743 REGISTER_TARGET_DIR_AUTOLOAD;
744 }
745
746 $file .= <<<REGISTER_LOADER
747         \$loader->register($prependAutoloader);
748
749
750 REGISTER_LOADER;
751
752 if ($useIncludeFiles) {
753 $file .= <<<INCLUDE_FILES
754         if (\$useStaticLoader) {
755             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
756         } else {
757             \$includeFiles = require __DIR__ . '/autoload_files.php';
758         }
759         foreach (\$includeFiles as \$fileIdentifier => \$file) {
760             composerRequire$suffix(\$fileIdentifier, \$file);
761         }
762
763
764 INCLUDE_FILES;
765 }
766
767 $file .= <<<METHOD_FOOTER
768         return \$loader;
769     }
770
771 METHOD_FOOTER;
772
773 $file .= $targetDirLoader;
774
775 if ($useIncludeFiles) {
776 return $file . <<<FOOTER
777 }
778
779 function composerRequire$suffix(\$fileIdentifier, \$file)
780 {
781     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
782         require \$file;
783
784         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
785     }
786 }
787
788 FOOTER;
789 }
790
791 return $file . <<<FOOTER
792 }
793
794 FOOTER;
795 }
796
797 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
798 {
799 $staticPhpVersion = 50600;
800
801 $file = <<<HEADER
802 <?php
803
804 // autoload_static.php @generated by Composer
805
806 namespace Composer\Autoload;
807
808 class ComposerStaticInit$suffix
809 {
810
811 HEADER;
812
813 $loader = new ClassLoader();
814
815 $map = require $targetDir . '/autoload_namespaces.php';
816 foreach ($map as $namespace => $path) {
817 $loader->set($namespace, $path);
818 }
819
820 $map = require $targetDir . '/autoload_psr4.php';
821 foreach ($map as $namespace => $path) {
822 $loader->setPsr4($namespace, $path);
823 }
824
825 $classMap = require $targetDir . '/autoload_classmap.php';
826 if ($classMap) {
827 $loader->addClassMap($classMap);
828 }
829
830 $filesystem = new Filesystem();
831
832 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
833 $vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
834 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
835 $appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
836
837 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
838 $absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\\/') . '/', true), 0, -1);
839 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
840 $absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\\/') . '/', true), 0, -1);
841
842 $initializer = '';
843 $prefix = "\0Composer\Autoload\ClassLoader\0";
844 $prefixLen = strlen($prefix);
845 if (file_exists($targetDir . '/autoload_files.php')) {
846 $maps = array('files' => require $targetDir . '/autoload_files.php');
847 } else {
848 $maps = array();
849 }
850
851 foreach ((array) $loader as $prop => $value) {
852 if ($value && 0 === strpos($prop, $prefix)) {
853 $maps[substr($prop, $prefixLen)] = $value;
854 }
855 }
856
857 foreach ($maps as $prop => $value) {
858 if (count($value) > 32767) {
859
860  
861  $staticPhpVersion = 70000;
862 }
863 $value = strtr(
864 var_export($value, true),
865 array(
866 $absoluteVendorPathCode => $vendorPathCode,
867 $absoluteVendorPharPathCode => $vendorPharPathCode,
868 $absoluteAppBaseDirCode => $appBaseDirCode,
869 $absoluteAppBaseDirPharCode => $appBaseDirPharCode,
870 )
871 );
872 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
873
874 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
875 if ('files' !== $prop) {
876 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
877 }
878 }
879
880 return $file . <<<INITIALIZER
881     public static function getInitializer(ClassLoader \$loader)
882     {
883         return \Closure::bind(function () use (\$loader) {
884 $initializer
885         }, null, ClassLoader::class);
886     }
887 }
888
889 INITIALIZER;
890 }
891
892 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
893 {
894 $autoloads = array();
895
896 foreach ($packageMap as $item) {
897 list($package, $installPath) = $item;
898
899 $autoload = $package->getAutoload();
900 if ($this->devMode && $package === $mainPackage) {
901 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
902 }
903
904
905  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
906 continue;
907 }
908 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
909 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
910 }
911
912 foreach ($autoload[$type] as $namespace => $paths) {
913 foreach ((array) $paths as $path) {
914 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
915
916  if ($package === $mainPackage) {
917 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
918 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
919 } else {
920
921  $path = $package->getTargetDir() . '/' . $path;
922 }
923 }
924
925 if ($type === 'exclude-from-classmap') {
926
927  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
928
929
930  $path = str_replace('\\*\\*', '.+?', $path);
931 $path = str_replace('\\*', '[^/]+?', $path);
932
933
934  $updir = null;
935 $path = preg_replace_callback(
936 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
937 function ($matches) use (&$updir) {
938 if (isset($matches[1])) {
939
940  $updir = str_replace('\\.', '.', $matches[1]);
941 }
942
943 return '';
944 },
945 $path
946 );
947 if (empty($installPath)) {
948 $installPath = strtr(getcwd(), '\\', '/');
949 }
950
951 $resolvedPath = realpath($installPath . '/' . $updir);
952 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
953 continue;
954 }
955
956 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
957
958 if ($type === 'files') {
959 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
960 continue;
961 } elseif ($type === 'classmap') {
962 $autoloads[] = $relativePath;
963 continue;
964 }
965
966 $autoloads[$namespace][] = $relativePath;
967 }
968 }
969 }
970
971 return $autoloads;
972 }
973
974 protected function getFileIdentifier(PackageInterface $package, $path)
975 {
976 return md5($package->getName() . ':' . $path);
977 }
978
979
980
981
982
983
984
985
986 protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage)
987 {
988 $packages = array();
989 $include = array();
990
991 foreach ($packageMap as $item) {
992 $package = $item[0];
993 $name = $package->getName();
994 $packages[$name] = $package;
995 }
996
997 $add = function (PackageInterface $package) use (&$add, $packages, &$include) {
998 foreach ($package->getRequires() as $link) {
999 $target = $link->getTarget();
1000 if (!isset($include[$target])) {
1001 $include[$target] = true;
1002 if (isset($packages[$target])) {
1003 $add($packages[$target]);
1004 }
1005 }
1006 }
1007 };
1008 $add($mainPackage);
1009
1010 return array_filter(
1011 $packageMap,
1012 function ($item) use ($include) {
1013 $package = $item[0];
1014 foreach ($package->getNames() as $name) {
1015 if (isset($include[$name])) {
1016 return true;
1017 }
1018 }
1019
1020 return false;
1021 }
1022 );
1023 }
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033 protected function sortPackageMap(array $packageMap)
1034 {
1035 $packages = array();
1036 $paths = array();
1037
1038 foreach ($packageMap as $item) {
1039 list($package, $path) = $item;
1040 $name = $package->getName();
1041 $packages[$name] = $package;
1042 $paths[$name] = $path;
1043 }
1044
1045 $sortedPackages = PackageSorter::sortPackages($packages);
1046
1047
1048 $sortedPackageMap = array();
1049
1050 foreach ($sortedPackages as $package) {
1051 $name = $package->getName();
1052 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1053 }
1054
1055 return $sortedPackageMap;
1056 }
1057
1058
1059
1060
1061
1062
1063
1064 protected function safeCopy($source, $target)
1065 {
1066 $source = fopen($source, 'r');
1067 $target = fopen($target, 'w+');
1068
1069 stream_copy_to_stream($source, $target);
1070 fclose($source);
1071 fclose($target);
1072 }
1073 }
1074 <?php
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092 namespace Composer\Autoload;
1093
1094 use Symfony\Component\Finder\Finder;
1095 use Composer\IO\IOInterface;
1096 use Composer\Util\Filesystem;
1097
1098
1099
1100
1101
1102
1103
1104 class ClassMapGenerator
1105 {
1106
1107
1108
1109
1110
1111
1112 public static function dump($dirs, $file)
1113 {
1114 $maps = array();
1115
1116 foreach ($dirs as $dir) {
1117 $maps = array_merge($maps, static::createMap($dir));
1118 }
1119
1120 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1135 {
1136 if (is_string($path)) {
1137 if (is_file($path)) {
1138 $path = array(new \SplFileInfo($path));
1139 } elseif (is_dir($path)) {
1140 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1141 } else {
1142 throw new \RuntimeException(
1143 'Could not scan for classes inside "'.$path.
1144 '" which does not appear to be a file nor a folder'
1145 );
1146 }
1147 }
1148
1149 $map = array();
1150 $filesystem = new Filesystem();
1151 $cwd = realpath(getcwd());
1152
1153 foreach ($path as $file) {
1154 $filePath = $file->getPathname();
1155 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1156 continue;
1157 }
1158
1159 if (!$filesystem->isAbsolutePath($filePath)) {
1160 $filePath = $cwd . '/' . $filePath;
1161 $filePath = $filesystem->normalizePath($filePath);
1162 } else {
1163 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1164 }
1165
1166
1167  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1168 continue;
1169 }
1170
1171  if ($blacklist && preg_match($blacklist, strtr($filePath, '\\', '/'))) {
1172 continue;
1173 }
1174
1175 $classes = self::findClasses($filePath);
1176
1177 foreach ($classes as $class) {
1178
1179  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1180 continue;
1181 }
1182
1183 if (!isset($map[$class])) {
1184 $map[$class] = $filePath;
1185 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1186 $io->writeError(
1187 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1188 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1189 );
1190 }
1191 }
1192 }
1193
1194 return $map;
1195 }
1196
1197
1198
1199
1200
1201
1202
1203
1204 private static function findClasses($path)
1205 {
1206 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1207 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1208 $extraTypes .= '|enum';
1209 }
1210
1211
1212  
1213  $contents = @php_strip_whitespace($path);
1214 if (!$contents) {
1215 if (!file_exists($path)) {
1216 $message = 'File at "%s" does not exist, check your classmap definitions';
1217 } elseif (!is_readable($path)) {
1218 $message = 'File at "%s" is not readable, check its permissions';
1219 } elseif ('' === trim(file_get_contents($path))) {
1220
1221  return array();
1222 } else {
1223 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1224 }
1225 $error = error_get_last();
1226 if (isset($error['message'])) {
1227 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1228 }
1229 throw new \RuntimeException(sprintf($message, $path));
1230 }
1231
1232
1233  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1234 return array();
1235 }
1236
1237
1238  $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
1239
1240  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1241
1242  if (substr($contents, 0, 2) !== '<?') {
1243 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1244 if ($replacements === 0) {
1245 return array();
1246 }
1247 }
1248
1249  $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
1250
1251  $pos = strrpos($contents, '?>');
1252 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1253 $contents = substr($contents, 0, $pos);
1254 }
1255
1256  if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
1257 $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
1258 }
1259
1260 preg_match_all('{
1261             (?:
1262                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1263                | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\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*+ [\{;]
1264             )
1265         }ix', $contents, $matches);
1266
1267 $classes = array();
1268 $namespace = '';
1269
1270 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1271 if (!empty($matches['ns'][$i])) {
1272 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1273 } else {
1274 $name = $matches['name'][$i];
1275
1276  if ($name === 'extends' || $name === 'implements') {
1277 continue;
1278 }
1279 if ($name[0] === ':') {
1280
1281  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1282 } elseif ($matches['type'][$i] === 'enum') {
1283
1284  
1285  
1286  
1287  $name = rtrim($name, ':');
1288 }
1289 $classes[] = ltrim($namespace . $name, '\\');
1290 }
1291 }
1292
1293 return $classes;
1294 }
1295 }
1296 <?php
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308 namespace Composer;
1309
1310 use Composer\IO\IOInterface;
1311 use Composer\Util\Filesystem;
1312 use Composer\Util\Silencer;
1313 use Symfony\Component\Finder\Finder;
1314
1315
1316
1317
1318
1319
1320 class Cache
1321 {
1322 private static $cacheCollected = false;
1323 private $io;
1324 private $root;
1325 private $enabled = true;
1326 private $whitelist;
1327 private $filesystem;
1328
1329
1330
1331
1332
1333
1334
1335 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1336 {
1337 $this->io = $io;
1338 $this->root = rtrim($cacheDir, '/\\') . '/';
1339 $this->whitelist = $whitelist;
1340 $this->filesystem = $filesystem ?: new Filesystem();
1341
1342 if (!self::isUsable($cacheDir)) {
1343 $this->enabled = false;
1344
1345 return;
1346 }
1347
1348 if (
1349 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1350 || !is_writable($this->root)
1351 ) {
1352 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1353 $this->enabled = false;
1354 }
1355 }
1356
1357 public static function isUsable($path)
1358 {
1359 return !preg_match('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path);
1360 }
1361
1362 public function isEnabled()
1363 {
1364 return $this->enabled;
1365 }
1366
1367 public function getRoot()
1368 {
1369 return $this->root;
1370 }
1371
1372 public function read($file)
1373 {
1374 if ($this->enabled) {
1375 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1376 if (file_exists($this->root . $file)) {
1377 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1378
1379 return file_get_contents($this->root . $file);
1380 }
1381 }
1382
1383 return false;
1384 }
1385
1386 public function write($file, $contents)
1387 {
1388 if ($this->enabled) {
1389 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1390
1391 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1392
1393 try {
1394 return file_put_contents($this->root . $file, $contents);
1395 } catch (\ErrorException $e) {
1396 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1397 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1398
1399  unlink($this->root . $file);
1400
1401 $message = sprintf(
1402 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1403 $this->root . $file,
1404 $m[1],
1405 $m[2],
1406 @disk_free_space($this->root . dirname($file))
1407 );
1408
1409 $this->io->writeError($message);
1410
1411 return false;
1412 }
1413
1414 throw $e;
1415 }
1416 }
1417
1418 return false;
1419 }
1420
1421
1422
1423
1424 public function copyFrom($file, $source)
1425 {
1426 if ($this->enabled) {
1427 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1428 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1429
1430 if (!file_exists($source)) {
1431 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1432 } elseif ($this->io->isDebug()) {
1433 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1434 }
1435
1436 return copy($source, $this->root . $file);
1437 }
1438
1439 return false;
1440 }
1441
1442
1443
1444
1445 public function copyTo($file, $target)
1446 {
1447 if ($this->enabled) {
1448 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1449 if (file_exists($this->root . $file)) {
1450 try {
1451 touch($this->root . $file, filemtime($this->root . $file), time());
1452 } catch (\ErrorException $e) {
1453
1454  
1455  Silencer::call('touch', $this->root . $file);
1456 }
1457
1458 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1459
1460 return copy($this->root . $file, $target);
1461 }
1462 }
1463
1464 return false;
1465 }
1466
1467 public function gcIsNecessary()
1468 {
1469 return (!self::$cacheCollected && !mt_rand(0, 50));
1470 }
1471
1472 public function remove($file)
1473 {
1474 if ($this->enabled) {
1475 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1476 if (file_exists($this->root . $file)) {
1477 return $this->filesystem->unlink($this->root . $file);
1478 }
1479 }
1480
1481 return false;
1482 }
1483
1484 public function clear()
1485 {
1486 if ($this->enabled) {
1487 $this->filesystem->emptyDirectory($this->root);
1488 return true;
1489 }
1490
1491 return false;
1492 }
1493
1494 public function gc($ttl, $maxSize)
1495 {
1496 if ($this->enabled) {
1497 $expire = new \DateTime();
1498 $expire->modify('-'.$ttl.' seconds');
1499
1500 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1501 foreach ($finder as $file) {
1502 $this->filesystem->unlink($file->getPathname());
1503 }
1504
1505 $totalSize = $this->filesystem->size($this->root);
1506 if ($totalSize > $maxSize) {
1507 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1508 while ($totalSize > $maxSize && $iterator->valid()) {
1509 $filepath = $iterator->current()->getPathname();
1510 $totalSize -= $this->filesystem->size($filepath);
1511 $this->filesystem->unlink($filepath);
1512 $iterator->next();
1513 }
1514 }
1515
1516 self::$cacheCollected = true;
1517
1518 return true;
1519 }
1520
1521 return false;
1522 }
1523
1524 public function sha1($file)
1525 {
1526 if ($this->enabled) {
1527 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1528 if (file_exists($this->root . $file)) {
1529 return sha1_file($this->root . $file);
1530 }
1531 }
1532
1533 return false;
1534 }
1535
1536 public function sha256($file)
1537 {
1538 if ($this->enabled) {
1539 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1540 if (file_exists($this->root . $file)) {
1541 return hash_file('sha256', $this->root . $file);
1542 }
1543 }
1544
1545 return false;
1546 }
1547
1548 protected function getFinder()
1549 {
1550 return Finder::create()->in($this->root)->files();
1551 }
1552 }
1553 <?php
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565 namespace Composer\Command;
1566
1567 use Symfony\Component\Console\Input\InputInterface;
1568 use Symfony\Component\Console\Output\OutputInterface;
1569
1570
1571
1572
1573 class AboutCommand extends BaseCommand
1574 {
1575 protected function configure()
1576 {
1577 $this
1578 ->setName('about')
1579 ->setDescription('Shows the short information about Composer.')
1580 ->setHelp(
1581 <<<EOT
1582 <info>php composer.phar about</info>
1583 EOT
1584 )
1585 ;
1586 }
1587
1588 protected function execute(InputInterface $input, OutputInterface $output)
1589 {
1590 $this->getIO()->write(
1591 <<<EOT
1592 <info>Composer - Dependency Manager for PHP</info>
1593 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1594 See https://getcomposer.org/ for more information.</comment>
1595 EOT
1596 );
1597
1598 return 0;
1599 }
1600 }
1601 <?php
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613 namespace Composer\Command;
1614
1615 use Composer\Factory;
1616 use Composer\IO\IOInterface;
1617 use Composer\Config;
1618 use Composer\Composer;
1619 use Composer\Repository\CompositeRepository;
1620 use Composer\Repository\RepositoryFactory;
1621 use Composer\Script\ScriptEvents;
1622 use Composer\Plugin\CommandEvent;
1623 use Composer\Plugin\PluginEvents;
1624 use Composer\Util\Filesystem;
1625 use Symfony\Component\Console\Input\InputArgument;
1626 use Symfony\Component\Console\Input\InputInterface;
1627 use Symfony\Component\Console\Input\InputOption;
1628 use Symfony\Component\Console\Output\OutputInterface;
1629
1630
1631
1632
1633
1634
1635 class ArchiveCommand extends BaseCommand
1636 {
1637 protected function configure()
1638 {
1639 $this
1640 ->setName('archive')
1641 ->setDescription('Creates an archive of this composer package.')
1642 ->setDefinition(array(
1643 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1644 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1645 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1646 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1647 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1648 .' Note that the format will be appended.'),
1649 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1650 ))
1651 ->setHelp(
1652 <<<EOT
1653 The <info>archive</info> command creates an archive of the specified format
1654 containing the files and directories of the Composer project or the specified
1655 package in the specified version and writes it to the specified directory.
1656
1657 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1658
1659 Read more at https://getcomposer.org/doc/03-cli.md#archive
1660 EOT
1661 )
1662 ;
1663 }
1664
1665 protected function execute(InputInterface $input, OutputInterface $output)
1666 {
1667 $config = Factory::createConfig();
1668 $composer = $this->getComposer(false);
1669 if ($composer) {
1670 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1671 $eventDispatcher = $composer->getEventDispatcher();
1672 $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent);
1673 $eventDispatcher->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1674 }
1675
1676 if (null === $input->getOption('format')) {
1677 $input->setOption('format', $config->get('archive-format'));
1678 }
1679 if (null === $input->getOption('dir')) {
1680 $input->setOption('dir', $config->get('archive-dir'));
1681 }
1682
1683 $returnCode = $this->archive(
1684 $this->getIO(),
1685 $config,
1686 $input->getArgument('package'),
1687 $input->getArgument('version'),
1688 $input->getOption('format'),
1689 $input->getOption('dir'),
1690 $input->getOption('file'),
1691 $input->getOption('ignore-filters'),
1692 $composer
1693 );
1694
1695 if (0 === $returnCode && $composer) {
1696 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1697 }
1698
1699 return $returnCode;
1700 }
1701
1702 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1703 {
1704 if ($composer) {
1705 $archiveManager = $composer->getArchiveManager();
1706 } else {
1707 $factory = new Factory;
1708 $downloadManager = $factory->createDownloadManager($io, $config);
1709 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1710 }
1711
1712 if ($packageName) {
1713 $package = $this->selectPackage($io, $packageName, $version);
1714
1715 if (!$package) {
1716 return 1;
1717 }
1718 } else {
1719 $package = $this->getComposer()->getPackage();
1720 }
1721
1722 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1723 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1724 $fs = new Filesystem;
1725 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1726
1727 $io->writeError('Created: ', false);
1728 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1729
1730 return 0;
1731 }
1732
1733 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1734 {
1735 $io->writeError('<info>Searching for the specified package.</info>');
1736
1737 if ($composer = $this->getComposer(false)) {
1738 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1739 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1740 } else {
1741 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1742 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1743 $repo = new CompositeRepository($defaultRepos);
1744 }
1745
1746 $packages = $repo->findPackages($packageName, $version);
1747
1748 if (count($packages) > 1) {
1749 $package = reset($packages);
1750 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1751 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1752 return $p->getPrettyString();
1753 }, $packages)).'.');
1754 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1755 } elseif ($packages) {
1756 $package = reset($packages);
1757 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1758 } else {
1759 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1760
1761 return false;
1762 }
1763
1764 return $package;
1765 }
1766 }
1767 <?php
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779 namespace Composer\Command;
1780
1781 use Composer\Composer;
1782 use Composer\Config;
1783 use Composer\Console\Application;
1784 use Composer\Factory;
1785 use Composer\IO\IOInterface;
1786 use Composer\IO\NullIO;
1787 use Composer\Plugin\PreCommandRunEvent;
1788 use Composer\Plugin\PluginEvents;
1789 use Symfony\Component\Console\Input\InputInterface;
1790 use Symfony\Component\Console\Output\OutputInterface;
1791 use Symfony\Component\Console\Command\Command;
1792
1793
1794
1795
1796
1797
1798
1799 abstract class BaseCommand extends Command
1800 {
1801
1802
1803
1804 private $composer;
1805
1806
1807
1808
1809 private $io;
1810
1811
1812
1813
1814
1815
1816
1817 public function getComposer($required = true, $disablePlugins = null)
1818 {
1819 if (null === $this->composer) {
1820 $application = $this->getApplication();
1821 if ($application instanceof Application) {
1822
1823 $this->composer = $application->getComposer($required, $disablePlugins);
1824 } elseif ($required) {
1825 throw new \RuntimeException(
1826 'Could not create a Composer\Composer instance, you must inject '.
1827 'one if this command is not used with a Composer\Console\Application instance'
1828 );
1829 }
1830 }
1831
1832 return $this->composer;
1833 }
1834
1835
1836
1837
1838 public function setComposer(Composer $composer)
1839 {
1840 $this->composer = $composer;
1841 }
1842
1843
1844
1845
1846 public function resetComposer()
1847 {
1848 $this->composer = null;
1849 $this->getApplication()->resetComposer();
1850 }
1851
1852
1853
1854
1855
1856
1857
1858
1859 public function isProxyCommand()
1860 {
1861 return false;
1862 }
1863
1864
1865
1866
1867 public function getIO()
1868 {
1869 if (null === $this->io) {
1870 $application = $this->getApplication();
1871 if ($application instanceof Application) {
1872
1873 $this->io = $application->getIO();
1874 } else {
1875 $this->io = new NullIO();
1876 }
1877 }
1878
1879 return $this->io;
1880 }
1881
1882
1883
1884
1885 public function setIO(IOInterface $io)
1886 {
1887 $this->io = $io;
1888 }
1889
1890
1891
1892
1893 protected function initialize(InputInterface $input, OutputInterface $output)
1894 {
1895
1896  $disablePlugins = $input->hasParameterOption('--no-plugins');
1897 $composer = $this->getComposer(false, $disablePlugins);
1898 if (null === $composer) {
1899 $composer = Factory::createGlobal($this->getIO(), $disablePlugins);
1900 }
1901 if ($composer) {
1902 $preCommandRunEvent = new PreCommandRunEvent(PluginEvents::PRE_COMMAND_RUN, $input, $this->getName());
1903 $composer->getEventDispatcher()->dispatch($preCommandRunEvent->getName(), $preCommandRunEvent);
1904 }
1905
1906 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1907 $input->setOption('no-progress', true);
1908 }
1909
1910 parent::initialize($input, $output);
1911 }
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1923 {
1924 $preferSource = false;
1925 $preferDist = false;
1926
1927 switch ($config->get('preferred-install')) {
1928 case 'source':
1929 $preferSource = true;
1930 break;
1931 case 'dist':
1932 $preferDist = true;
1933 break;
1934 case 'auto':
1935 default:
1936
1937  break;
1938 }
1939
1940 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1941 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1942 $preferDist = $input->getOption('prefer-dist');
1943 }
1944
1945 return array($preferSource, $preferDist);
1946 }
1947 }
1948 <?php
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960 namespace Composer\Command;
1961
1962 use Composer\DependencyResolver\Pool;
1963 use Composer\Package\Link;
1964 use Composer\Package\PackageInterface;
1965 use Composer\Repository\ArrayRepository;
1966 use Composer\Repository\CompositeRepository;
1967 use Composer\Repository\PlatformRepository;
1968 use Composer\Repository\RepositoryFactory;
1969 use Composer\Plugin\CommandEvent;
1970 use Composer\Plugin\PluginEvents;
1971 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1972 use Composer\Package\Version\VersionParser;
1973 use Symfony\Component\Console\Helper\Table;
1974 use Symfony\Component\Console\Input\InputArgument;
1975 use Symfony\Component\Console\Input\InputInterface;
1976 use Symfony\Component\Console\Input\InputOption;
1977 use Symfony\Component\Console\Output\OutputInterface;
1978
1979
1980
1981
1982
1983
1984 class BaseDependencyCommand extends BaseCommand
1985 {
1986 const ARGUMENT_PACKAGE = 'package';
1987 const ARGUMENT_CONSTRAINT = 'constraint';
1988 const OPTION_RECURSIVE = 'recursive';
1989 const OPTION_TREE = 'tree';
1990
1991 protected $colors;
1992
1993
1994
1995
1996 protected function configure()
1997 {
1998 $this->setDefinition(array(
1999 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
2000 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
2001 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
2002 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
2003 ));
2004 }
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
2015 {
2016
2017  $composer = $this->getComposer();
2018 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
2019 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
2020
2021
2022  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
2023 $repository = new CompositeRepository(array(
2024 new ArrayRepository(array($composer->getPackage())),
2025 $composer->getRepositoryManager()->getLocalRepository(),
2026 new PlatformRepository(array(), $platformOverrides),
2027 ));
2028 $pool = new Pool();
2029 $pool->addRepository($repository);
2030
2031
2032  list($needle, $textConstraint) = array_pad(
2033 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
2034 2,
2035 $input->getArgument(self::ARGUMENT_CONSTRAINT)
2036 );
2037
2038
2039  $packages = $pool->whatProvides(strtolower($needle));
2040 if (empty($packages)) {
2041 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
2042 }
2043
2044
2045  
2046  if (!$repository->findPackage($needle, $textConstraint)) {
2047 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2048 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2049 $repository->addRepository(new ArrayRepository(array(clone $match)));
2050 }
2051 }
2052
2053
2054  $needles = array($needle);
2055 if ($inverted) {
2056 foreach ($packages as $package) {
2057 $needles = array_merge($needles, array_map(function (Link $link) {
2058 return $link->getTarget();
2059 }, $package->getReplaces()));
2060 }
2061 }
2062
2063
2064  if ('*' !== $textConstraint) {
2065 $versionParser = new VersionParser();
2066 $constraint = $versionParser->parseConstraints($textConstraint);
2067 } else {
2068 $constraint = null;
2069 }
2070
2071
2072  $renderTree = $input->getOption(self::OPTION_TREE);
2073 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2074
2075
2076  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2077 if (empty($results)) {
2078 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2079 $this->getIO()->writeError(sprintf(
2080 '<info>There is no installed package depending on "%s"%s</info>',
2081 $needle,
2082 $extra
2083 ));
2084 } elseif ($renderTree) {
2085 $this->initStyles($output);
2086 $root = $packages[0];
2087 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2088 $this->printTree($results);
2089 } else {
2090 $this->printTable($output, $results);
2091 }
2092
2093 return 0;
2094 }
2095
2096
2097
2098
2099
2100
2101
2102 protected function printTable(OutputInterface $output, $results)
2103 {
2104 $table = array();
2105 $doubles = array();
2106 do {
2107 $queue = array();
2108 $rows = array();
2109 foreach ($results as $result) {
2110
2111
2112
2113
2114 list($package, $link, $children) = $result;
2115 $unique = (string) $link;
2116 if (isset($doubles[$unique])) {
2117 continue;
2118 }
2119 $doubles[$unique] = true;
2120 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2121 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2122 if ($children) {
2123 $queue = array_merge($queue, $children);
2124 }
2125 }
2126 $results = $queue;
2127 $table = array_merge($rows, $table);
2128 } while (!empty($results));
2129
2130
2131  $renderer = new Table($output);
2132 $renderer->setStyle('compact');
2133 $rendererStyle = $renderer->getStyle();
2134 $rendererStyle->setVerticalBorderChar('');
2135 $rendererStyle->setCellRowContentFormat('%s  ');
2136 $renderer->setRows($table)->render();
2137 }
2138
2139
2140
2141
2142
2143
2144 protected function initStyles(OutputInterface $output)
2145 {
2146 $this->colors = array(
2147 'green',
2148 'yellow',
2149 'cyan',
2150 'magenta',
2151 'blue',
2152 );
2153
2154 foreach ($this->colors as $color) {
2155 $style = new OutputFormatterStyle($color);
2156 $output->getFormatter()->setStyle($color, $style);
2157 }
2158 }
2159
2160
2161
2162
2163
2164
2165
2166
2167 protected function printTree($results, $prefix = '', $level = 1)
2168 {
2169 $count = count($results);
2170 $idx = 0;
2171 foreach ($results as $result) {
2172
2173
2174
2175
2176
2177 list($package, $link, $children) = $result;
2178
2179 $color = $this->colors[$level % count($this->colors)];
2180 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2181 $isLast = (++$idx == $count);
2182 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2183 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2184 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2185 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2186 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2187 if ($children) {
2188 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2189 }
2190 }
2191 }
2192
2193 private function writeTreeLine($line)
2194 {
2195 $io = $this->getIO();
2196 if (!$io->isDecorated()) {
2197 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2198 }
2199
2200 $io->write($line);
2201 }
2202 }
2203 <?php
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215 namespace Composer\Command;
2216
2217 use Composer\Package\Link;
2218 use Composer\Package\PackageInterface;
2219 use Composer\Semver\Constraint\Constraint;
2220 use Symfony\Component\Console\Helper\Table;
2221 use Symfony\Component\Console\Input\InputInterface;
2222 use Symfony\Component\Console\Input\InputOption;
2223 use Symfony\Component\Console\Output\OutputInterface;
2224 use Composer\Repository\PlatformRepository;
2225
2226 class CheckPlatformReqsCommand extends BaseCommand
2227 {
2228 protected function configure()
2229 {
2230 $this->setName('check-platform-reqs')
2231 ->setDescription('Check that platform requirements are satisfied.')
2232 ->setDefinition(array(
2233 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables checking of require-dev packages requirements.'),
2234 ))
2235 ->setHelp(
2236 <<<EOT
2237 Checks that your PHP and extensions versions match the platform requirements of the installed packages.
2238
2239 Unlike update/install, this command will ignore config.platform settings and check the real platform packages so you can be certain you have the required platform dependencies.
2240
2241 <info>php composer.phar check-platform-reqs</info>
2242
2243 EOT
2244 );
2245 }
2246
2247 protected function execute(InputInterface $input, OutputInterface $output)
2248 {
2249 $composer = $this->getComposer();
2250
2251 $requires = $composer->getPackage()->getRequires();
2252 if ($input->getOption('no-dev')) {
2253 $dependencies = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'))->getPackages();
2254 } else {
2255 $dependencies = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
2256
2257  if (!$dependencies) {
2258 $dependencies = $composer->getLocker()->getLockedRepository(true)->getPackages();
2259 }
2260 $requires += $composer->getPackage()->getDevRequires();
2261 }
2262 foreach ($requires as $require => $link) {
2263 $requires[$require] = array($link);
2264 }
2265
2266 foreach ($dependencies as $package) {
2267 foreach ($package->getRequires() as $require => $link) {
2268 $requires[$require][] = $link;
2269 }
2270 }
2271
2272 ksort($requires);
2273
2274 $platformRepo = new PlatformRepository(array(), array());
2275 $currentPlatformPackages = $platformRepo->getPackages();
2276 $currentPlatformPackageMap = array();
2277
2278
2279
2280
2281 foreach ($currentPlatformPackages as $currentPlatformPackage) {
2282 $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
2283 }
2284
2285 $results = array();
2286
2287 $exitCode = 0;
2288
2289
2290
2291
2292 foreach ($requires as $require => $links) {
2293 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
2294 if (isset($currentPlatformPackageMap[$require])) {
2295 $pass = true;
2296 $version = $currentPlatformPackageMap[$require]->getVersion();
2297
2298 foreach ($links as $link) {
2299 if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
2300 $results[] = array(
2301 $currentPlatformPackageMap[$require]->getPrettyName(),
2302 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2303 $link,
2304 '<error>failed</error>',
2305 );
2306 $pass = false;
2307
2308 $exitCode = max($exitCode, 1);
2309 }
2310 }
2311
2312 if ($pass) {
2313 $results[] = array(
2314 $currentPlatformPackageMap[$require]->getPrettyName(),
2315 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2316 null,
2317 '<info>success</info>',
2318 );
2319 }
2320 } else {
2321 $results[] = array(
2322 $require,
2323 'n/a',
2324 $links[0],
2325 '<error>missing</error>',
2326 );
2327
2328 $exitCode = max($exitCode, 2);
2329 }
2330 }
2331 }
2332
2333 $this->printTable($output, $results);
2334
2335 return $exitCode;
2336 }
2337
2338 protected function printTable(OutputInterface $output, $results)
2339 {
2340 $table = array();
2341 $rows = array();
2342 foreach ($results as $result) {
2343
2344
2345
2346 list($platformPackage, $version, $link, $status) = $result;
2347 $rows[] = array(
2348 $platformPackage,
2349 $version,
2350 $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '',
2351 $status,
2352 );
2353 }
2354 $table = array_merge($rows, $table);
2355
2356
2357  $renderer = new Table($output);
2358 $renderer->setStyle('compact');
2359 $rendererStyle = $renderer->getStyle();
2360 $rendererStyle->setVerticalBorderChar('');
2361 $rendererStyle->setCellRowContentFormat('%s  ');
2362 $renderer->setRows($table)->render();
2363 }
2364 }
2365 <?php
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377 namespace Composer\Command;
2378
2379 use Composer\Cache;
2380 use Composer\Factory;
2381 use Symfony\Component\Console\Input\InputInterface;
2382 use Symfony\Component\Console\Output\OutputInterface;
2383
2384
2385
2386
2387 class ClearCacheCommand extends BaseCommand
2388 {
2389 protected function configure()
2390 {
2391 $this
2392 ->setName('clear-cache')
2393 ->setAliases(array('clearcache'))
2394 ->setDescription('Clears composer\'s internal package cache.')
2395 ->setHelp(
2396 <<<EOT
2397 The <info>clear-cache</info> deletes all cached packages from composer's
2398 cache directory.
2399
2400 Read more at https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-
2401 EOT
2402 )
2403 ;
2404 }
2405
2406 protected function execute(InputInterface $input, OutputInterface $output)
2407 {
2408 $config = Factory::createConfig();
2409 $io = $this->getIO();
2410
2411 $cachePaths = array(
2412 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2413 'cache-repo-dir' => $config->get('cache-repo-dir'),
2414 'cache-files-dir' => $config->get('cache-files-dir'),
2415 'cache-dir' => $config->get('cache-dir'),
2416 );
2417
2418 foreach ($cachePaths as $key => $cachePath) {
2419 $cachePath = realpath($cachePath);
2420 if (!$cachePath) {
2421 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2422
2423 continue;
2424 }
2425 $cache = new Cache($io, $cachePath);
2426 if (!$cache->isEnabled()) {
2427 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2428
2429 continue;
2430 }
2431
2432 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2433 $cache->clear();
2434 }
2435
2436 $io->writeError('<info>All caches cleared.</info>');
2437
2438 return 0;
2439 }
2440 }
2441 <?php
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453 namespace Composer\Command;
2454
2455 use Composer\Util\Platform;
2456 use Composer\Util\Silencer;
2457 use Symfony\Component\Console\Input\InputInterface;
2458 use Symfony\Component\Console\Input\InputArgument;
2459 use Symfony\Component\Console\Input\InputOption;
2460 use Symfony\Component\Console\Output\OutputInterface;
2461 use Composer\Config;
2462 use Composer\Config\JsonConfigSource;
2463 use Composer\Factory;
2464 use Composer\IO\IOInterface;
2465 use Composer\Json\JsonFile;
2466 use Composer\Semver\VersionParser;
2467 use Composer\Package\BasePackage;
2468
2469
2470
2471
2472
2473 class ConfigCommand extends BaseCommand
2474 {
2475
2476
2477
2478 protected $config;
2479
2480
2481
2482
2483 protected $configFile;
2484
2485
2486
2487
2488 protected $configSource;
2489
2490
2491
2492
2493 protected $authConfigFile;
2494
2495
2496
2497
2498 protected $authConfigSource;
2499
2500
2501
2502
2503 protected function configure()
2504 {
2505 $this
2506 ->setName('config')
2507 ->setDescription('Sets config options.')
2508 ->setDefinition(array(
2509 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2510 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2511 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2512 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2513 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2514 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2515 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2516 new InputArgument('setting-key', null, 'Setting key'),
2517 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2518 ))
2519 ->setHelp(
2520 <<<EOT
2521 This command allows you to edit composer config settings and repositories
2522 in either the local composer.json file or the global config.json file.
2523
2524 Additionally it lets you edit most properties in the local composer.json.
2525
2526 To set a config setting:
2527
2528     <comment>%command.full_name% bin-dir bin/</comment>
2529
2530 To read a config setting:
2531
2532     <comment>%command.full_name% bin-dir</comment>
2533     Outputs: <info>bin</info>
2534
2535 To edit the global config.json file:
2536
2537     <comment>%command.full_name% --global</comment>
2538
2539 To add a repository:
2540
2541     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2542
2543 To remove a repository (repo is a short alias for repositories):
2544
2545     <comment>%command.full_name% --unset repo.foo</comment>
2546
2547 To disable packagist:
2548
2549     <comment>%command.full_name% repo.packagist false</comment>
2550
2551 You can alter repositories in the global config.json file by passing in the
2552 <info>--global</info> option.
2553
2554 To edit the file in an external editor:
2555
2556     <comment>%command.full_name% --editor</comment>
2557
2558 To choose your editor you can set the "EDITOR" env variable.
2559
2560 To get a list of configuration values in the file:
2561
2562     <comment>%command.full_name% --list</comment>
2563
2564 You can always pass more than one option. As an example, if you want to edit the
2565 global config.json file.
2566
2567     <comment>%command.full_name% --editor --global</comment>
2568
2569 Read more at https://getcomposer.org/doc/03-cli.md#config
2570 EOT
2571 )
2572 ;
2573 }
2574
2575
2576
2577
2578 protected function initialize(InputInterface $input, OutputInterface $output)
2579 {
2580 parent::initialize($input, $output);
2581
2582 if ($input->getOption('global') && null !== $input->getOption('file')) {
2583 throw new \RuntimeException('--file and --global can not be combined');
2584 }
2585
2586 $io = $this->getIO();
2587 $this->config = Factory::createConfig($io);
2588
2589
2590  
2591  $configFile = $input->getOption('global')
2592 ? ($this->config->get('home') . '/config.json')
2593 : ($input->getOption('file') ?: Factory::getComposerFile());
2594
2595
2596  if (
2597 ($configFile === 'composer.json' || $configFile === './composer.json')
2598 && !file_exists($configFile)
2599 && realpath(getcwd()) === realpath($this->config->get('home'))
2600 ) {
2601 file_put_contents($configFile, "{\n}\n");
2602 }
2603
2604 $this->configFile = new JsonFile($configFile, null, $io);
2605 $this->configSource = new JsonConfigSource($this->configFile);
2606
2607 $authConfigFile = $input->getOption('global')
2608 ? ($this->config->get('home') . '/auth.json')
2609 : dirname(realpath($configFile)) . '/auth.json';
2610
2611 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2612 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2613
2614
2615  if ($input->getOption('global') && !$this->configFile->exists()) {
2616 touch($this->configFile->getPath());
2617 $this->configFile->write(array('config' => new \ArrayObject));
2618 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2619 }
2620 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2621 touch($this->authConfigFile->getPath());
2622 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2623 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2624 }
2625
2626 if (!$this->configFile->exists()) {
2627 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2628 }
2629 }
2630
2631
2632
2633
2634 protected function execute(InputInterface $input, OutputInterface $output)
2635 {
2636
2637  if ($input->getOption('editor')) {
2638 $editor = escapeshellcmd(getenv('EDITOR'));
2639 if (!$editor) {
2640 if (Platform::isWindows()) {
2641 $editor = 'notepad';
2642 } else {
2643 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2644 if (exec('which '.$candidate)) {
2645 $editor = $candidate;
2646 break;
2647 }
2648 }
2649 }
2650 }
2651
2652 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2653 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2654
2655 return 0;
2656 }
2657
2658 if (!$input->getOption('global')) {
2659 $this->config->merge($this->configFile->read());
2660 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2661 }
2662
2663
2664  if ($input->getOption('list')) {
2665 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2666
2667 return 0;
2668 }
2669
2670 $settingKey = $input->getArgument('setting-key');
2671 if (!$settingKey) {
2672 return 0;
2673 }
2674
2675
2676  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2677 throw new \RuntimeException('You can not combine a setting value with --unset');
2678 }
2679
2680
2681  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2682 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2683 $rawData = $this->configFile->read();
2684 $data = $this->config->all();
2685 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2686 if (!isset($matches[1]) || $matches[1] === '') {
2687 $value = isset($data['repositories']) ? $data['repositories'] : array();
2688 } else {
2689 if (!isset($data['repositories'][$matches[1]])) {
2690 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2691 }
2692
2693 $value = $data['repositories'][$matches[1]];
2694 }
2695 } elseif (strpos($settingKey, '.')) {
2696 $bits = explode('.', $settingKey);
2697 if ($bits[0] === 'extra') {
2698 $data = $rawData;
2699 } else {
2700 $data = $data['config'];
2701 }
2702 $match = false;
2703 foreach ($bits as $bit) {
2704 $key = isset($key) ? $key.'.'.$bit : $bit;
2705 $match = false;
2706 if (isset($data[$key])) {
2707 $match = true;
2708 $data = $data[$key];
2709 unset($key);
2710 }
2711 }
2712
2713 if (!$match) {
2714 throw new \RuntimeException($settingKey.' is not defined.');
2715 }
2716
2717 $value = $data;
2718 } elseif (isset($data['config'][$settingKey])) {
2719 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2720 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2721 $value = $rawData[$settingKey];
2722 } else {
2723 throw new \RuntimeException($settingKey.' is not defined');
2724 }
2725
2726 if (is_array($value)) {
2727 $value = json_encode($value);
2728 }
2729
2730 $this->getIO()->write($value, true, IOInterface::QUIET);
2731
2732 return 0;
2733 }
2734
2735 $values = $input->getArgument('setting-value'); 
2736
2737 $booleanValidator = function ($val) {
2738 return in_array($val, array('true', 'false', '1', '0'), true);
2739 };
2740 $booleanNormalizer = function ($val) {
2741 return $val !== 'false' && (bool) $val;
2742 };
2743
2744
2745  $uniqueConfigValues = array(
2746 'process-timeout' => array('is_numeric', 'intval'),
2747 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2748 'use-github-api' => array($booleanValidator, $booleanNormalizer),
2749 'preferred-install' => array(
2750 function ($val) {
2751 return in_array($val, array('auto', 'source', 'dist'), true);
2752 },
2753 function ($val) {
2754 return $val;
2755 },
2756 ),
2757 'store-auths' => array(
2758 function ($val) {
2759 return in_array($val, array('true', 'false', 'prompt'), true);
2760 },
2761 function ($val) {
2762 if ('prompt' === $val) {
2763 return 'prompt';
2764 }
2765
2766 return $val !== 'false' && (bool) $val;
2767 },
2768 ),
2769 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2770 'vendor-dir' => array('is_string', function ($val) {
2771 return $val;
2772 }),
2773 'bin-dir' => array('is_string', function ($val) {
2774 return $val;
2775 }),
2776 'archive-dir' => array('is_string', function ($val) {
2777 return $val;
2778 }),
2779 'archive-format' => array('is_string', function ($val) {
2780 return $val;
2781 }),
2782 'data-dir' => array('is_string', function ($val) {
2783 return $val;
2784 }),
2785 'cache-dir' => array('is_string', function ($val) {
2786 return $val;
2787 }),
2788 'cache-files-dir' => array('is_string', function ($val) {
2789 return $val;
2790 }),
2791 'cache-repo-dir' => array('is_string', function ($val) {
2792 return $val;
2793 }),
2794 'cache-vcs-dir' => array('is_string', function ($val) {
2795 return $val;
2796 }),
2797 'cache-ttl' => array('is_numeric', 'intval'),
2798 'cache-files-ttl' => array('is_numeric', 'intval'),
2799 'cache-files-maxsize' => array(
2800 function ($val) {
2801 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2802 },
2803 function ($val) {
2804 return $val;
2805 },
2806 ),
2807 'bin-compat' => array(
2808 function ($val) {
2809 return in_array($val, array('auto', 'full'));
2810 },
2811 function ($val) {
2812 return $val;
2813 },
2814 ),
2815 'discard-changes' => array(
2816 function ($val) {
2817 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2818 },
2819 function ($val) {
2820 if ('stash' === $val) {
2821 return 'stash';
2822 }
2823
2824 return $val !== 'false' && (bool) $val;
2825 },
2826 ),
2827 'autoloader-suffix' => array('is_string', function ($val) {
2828 return $val === 'null' ? null : $val;
2829 }),
2830 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2831 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2832 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2833 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2834 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2835 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2836 'secure-http' => array($booleanValidator, $booleanNormalizer),
2837 'cafile' => array(
2838 function ($val) {
2839 return file_exists($val) && is_readable($val);
2840 },
2841 function ($val) {
2842 return $val === 'null' ? null : $val;
2843 },
2844 ),
2845 'capath' => array(
2846 function ($val) {
2847 return is_dir($val) && is_readable($val);
2848 },
2849 function ($val) {
2850 return $val === 'null' ? null : $val;
2851 },
2852 ),
2853 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2854 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2855 );
2856 $multiConfigValues = array(
2857 'github-protocols' => array(
2858 function ($vals) {
2859 if (!is_array($vals)) {
2860 return 'array expected';
2861 }
2862
2863 foreach ($vals as $val) {
2864 if (!in_array($val, array('git', 'https', 'ssh'))) {
2865 return 'valid protocols include: git, https, ssh';
2866 }
2867 }
2868
2869 return true;
2870 },
2871 function ($vals) {
2872 return $vals;
2873 },
2874 ),
2875 'github-domains' => array(
2876 function ($vals) {
2877 if (!is_array($vals)) {
2878 return 'array expected';
2879 }
2880
2881 return true;
2882 },
2883 function ($vals) {
2884 return $vals;
2885 },
2886 ),
2887 'gitlab-domains' => array(
2888 function ($vals) {
2889 if (!is_array($vals)) {
2890 return 'array expected';
2891 }
2892
2893 return true;
2894 },
2895 function ($vals) {
2896 return $vals;
2897 },
2898 ),
2899 );
2900
2901 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2902 if ($settingKey === 'disable-tls' && $this->config->get('disable-tls')) {
2903 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
2904 }
2905
2906 $this->configSource->removeConfigSetting($settingKey);
2907
2908 return 0;
2909 }
2910 if (isset($uniqueConfigValues[$settingKey])) {
2911 $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2912
2913 return 0;
2914 }
2915 if (isset($multiConfigValues[$settingKey])) {
2916 $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2917
2918 return 0;
2919 }
2920
2921
2922  $uniqueProps = array(
2923 'name' => array('is_string', function ($val) {
2924 return $val;
2925 }),
2926 'type' => array('is_string', function ($val) {
2927 return $val;
2928 }),
2929 'description' => array('is_string', function ($val) {
2930 return $val;
2931 }),
2932 'homepage' => array('is_string', function ($val) {
2933 return $val;
2934 }),
2935 'version' => array('is_string', function ($val) {
2936 return $val;
2937 }),
2938 'minimum-stability' => array(
2939 function ($val) {
2940 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2941 },
2942 function ($val) {
2943 return VersionParser::normalizeStability($val);
2944 },
2945 ),
2946 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2947 );
2948 $multiProps = array(
2949 'keywords' => array(
2950 function ($vals) {
2951 if (!is_array($vals)) {
2952 return 'array expected';
2953 }
2954
2955 return true;
2956 },
2957 function ($vals) {
2958 return $vals;
2959 },
2960 ),
2961 'license' => array(
2962 function ($vals) {
2963 if (!is_array($vals)) {
2964 return 'array expected';
2965 }
2966
2967 return true;
2968 },
2969 function ($vals) {
2970 return $vals;
2971 },
2972 ),
2973 );
2974
2975 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2976 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');
2977 }
2978 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2979 $this->configSource->removeProperty($settingKey);
2980
2981 return 0;
2982 }
2983 if (isset($uniqueProps[$settingKey])) {
2984 $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2985
2986 return 0;
2987 }
2988 if (isset($multiProps[$settingKey])) {
2989 $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2990
2991 return 0;
2992 }
2993
2994
2995  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2996 if ($input->getOption('unset')) {
2997 $this->configSource->removeRepository($matches[1]);
2998
2999 return 0;
3000 }
3001
3002 if (2 === count($values)) {
3003 $this->configSource->addRepository($matches[1], array(
3004 'type' => $values[0],
3005 'url' => $values[1],
3006 ));
3007
3008 return 0;
3009 }
3010
3011 if (1 === count($values)) {
3012 $value = strtolower($values[0]);
3013 if (true === $booleanValidator($value)) {
3014 if (false === $booleanNormalizer($value)) {
3015 $this->configSource->addRepository($matches[1], false);
3016
3017 return 0;
3018 }
3019 } else {
3020 $value = JsonFile::parseJson($values[0]);
3021 $this->configSource->addRepository($matches[1], $value);
3022
3023 return 0;
3024 }
3025 }
3026
3027 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
3028 }
3029
3030
3031  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
3032 if ($input->getOption('unset')) {
3033 $this->configSource->removeProperty($settingKey);
3034
3035 return 0;
3036 }
3037
3038 $this->configSource->addProperty($settingKey, $values[0]);
3039
3040 return 0;
3041 }
3042
3043
3044  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
3045 if ($input->getOption('unset')) {
3046 $this->configSource->removeConfigSetting($settingKey);
3047
3048 return 0;
3049 }
3050
3051 $this->configSource->addConfigSetting($settingKey, $values[0]);
3052
3053 return 0;
3054 }
3055 if ($settingKey === 'platform' && $input->getOption('unset')) {
3056 $this->configSource->removeConfigSetting($settingKey);
3057
3058 return 0;
3059 }
3060
3061
3062  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
3063 if ($input->getOption('unset')) {
3064 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3065 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3066
3067 return 0;
3068 }
3069
3070 if ($matches[1] === 'bitbucket-oauth') {
3071 if (2 !== count($values)) {
3072 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
3073 }
3074 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3075 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
3076 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
3077 if (1 !== count($values)) {
3078 throw new \RuntimeException('Too many arguments, expected only one token');
3079 }
3080 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3081 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
3082 } elseif ($matches[1] === 'http-basic') {
3083 if (2 !== count($values)) {
3084 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
3085 }
3086 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3087 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
3088 }
3089
3090 return 0;
3091 }
3092
3093
3094  if (preg_match('/^scripts\.(.+)/', $settingKey, $matches)) {
3095 if ($input->getOption('unset')) {
3096 $this->configSource->removeProperty($settingKey);
3097
3098 return 0;
3099 }
3100
3101 $this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
3102
3103 return 0;
3104 }
3105
3106 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
3107 }
3108
3109 protected function handleSingleValue($key, array $callbacks, array $values, $method)
3110 {
3111 list($validator, $normalizer) = $callbacks;
3112 if (1 !== count($values)) {
3113 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
3114 }
3115
3116 if (true !== $validation = $validator($values[0])) {
3117 throw new \RuntimeException(sprintf(
3118 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3119 $values[0]
3120 ));
3121 }
3122
3123 $normalizedValue = $normalizer($values[0]);
3124
3125 if ($key === 'disable-tls') {
3126 if (!$normalizedValue && $this->config->get('disable-tls')) {
3127 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
3128 } elseif ($normalizedValue && !$this->config->get('disable-tls')) {
3129 $this->getIO()->writeError('<warning>You are now running Composer with SSL/TLS protection disabled.</warning>');
3130 }
3131 }
3132
3133 return call_user_func(array($this->configSource, $method), $key, $normalizedValue);
3134 }
3135
3136 protected function handleMultiValue($key, array $callbacks, array $values, $method)
3137 {
3138 list($validator, $normalizer) = $callbacks;
3139 if (true !== $validation = $validator($values)) {
3140 throw new \RuntimeException(sprintf(
3141 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3142 json_encode($values)
3143 ));
3144 }
3145
3146 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
3147 }
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
3158 {
3159 $origK = $k;
3160 $io = $this->getIO();
3161 foreach ($contents as $key => $value) {
3162 if ($k === null && !in_array($key, array('config', 'repositories'))) {
3163 continue;
3164 }
3165
3166 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
3167
3168 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
3169 $k .= preg_replace('{^config\.}', '', $key . '.');
3170 $this->listConfiguration($value, $rawVal, $output, $k);
3171 $k = $origK;
3172
3173 continue;
3174 }
3175
3176 if (is_array($value)) {
3177 $value = array_map(function ($val) {
3178 return is_array($val) ? json_encode($val) : $val;
3179 }, $value);
3180
3181 $value = '['.implode(', ', $value).']';
3182 }
3183
3184 if (is_bool($value)) {
3185 $value = var_export($value, true);
3186 }
3187
3188 if (is_string($rawVal) && $rawVal != $value) {
3189 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>', true, IOInterface::QUIET);
3190 } else {
3191 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>', true, IOInterface::QUIET);
3192 }
3193 }
3194 }
3195 }
3196 <?php
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208 namespace Composer\Command;
3209
3210 use Composer\Config;
3211 use Composer\Factory;
3212 use Composer\Installer;
3213 use Composer\Installer\ProjectInstaller;
3214 use Composer\Installer\InstallationManager;
3215 use Composer\Installer\SuggestedPackagesReporter;
3216 use Composer\IO\IOInterface;
3217 use Composer\Package\BasePackage;
3218 use Composer\DependencyResolver\Pool;
3219 use Composer\DependencyResolver\Operation\InstallOperation;
3220 use Composer\Package\Version\VersionSelector;
3221 use Composer\Package\AliasPackage;
3222 use Composer\Repository\RepositoryFactory;
3223 use Composer\Repository\CompositeRepository;
3224 use Composer\Repository\PlatformRepository;
3225 use Composer\Repository\InstalledFilesystemRepository;
3226 use Composer\Script\ScriptEvents;
3227 use Composer\Util\Silencer;
3228 use Symfony\Component\Console\Input\InputArgument;
3229 use Symfony\Component\Console\Input\InputInterface;
3230 use Symfony\Component\Console\Input\InputOption;
3231 use Symfony\Component\Console\Output\OutputInterface;
3232 use Symfony\Component\Finder\Finder;
3233 use Composer\Json\JsonFile;
3234 use Composer\Config\JsonConfigSource;
3235 use Composer\Util\Filesystem;
3236 use Composer\Package\Version\VersionParser;
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246 class CreateProjectCommand extends BaseCommand
3247 {
3248
3249
3250
3251 protected $suggestedPackagesReporter;
3252
3253 protected function configure()
3254 {
3255 $this
3256 ->setName('create-project')
3257 ->setDescription('Creates new project from a package into given directory.')
3258 ->setDefinition(array(
3259 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
3260 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
3261 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
3262 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
3263 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
3264 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
3265 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
3266 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
3267 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
3268 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
3269 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
3270 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
3271 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
3272 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.'),
3273 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'),
3274 new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'),
3275 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
3276 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
3277 ))
3278 ->setHelp(
3279 <<<EOT
3280 The <info>create-project</info> command creates a new project from a given
3281 package into a new directory. If executed without params and in a directory
3282 with a composer.json file it installs the packages for the current project.
3283
3284 You can use this command to bootstrap new projects or setup a clean
3285 version-controlled installation for developers of your project.
3286
3287 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3288
3289 You can also specify the version with the package name using = or : as separator.
3290
3291 <info>php composer.phar create-project vendor/project:version target-directory</info>
3292
3293 To install unstable packages, either specify the version you want, or use the
3294 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3295
3296 To setup a developer workable version you should create the project using the source
3297 controlled code by appending the <info>'--prefer-source'</info> flag.
3298
3299 To install a package from another repository than the default one you
3300 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3301
3302 Read more at https://getcomposer.org/doc/03-cli.md#create-project
3303 EOT
3304 )
3305 ;
3306 }
3307
3308 protected function execute(InputInterface $input, OutputInterface $output)
3309 {
3310 $config = Factory::createConfig();
3311 $io = $this->getIO();
3312
3313 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3314
3315 if ($input->getOption('dev')) {
3316 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3317 }
3318 if ($input->getOption('no-custom-installers')) {
3319 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3320 $input->setOption('no-plugins', true);
3321 }
3322
3323 return $this->installProject(
3324 $io,
3325 $config,
3326 $input,
3327 $input->getArgument('package'),
3328 $input->getArgument('directory'),
3329 $input->getArgument('version'),
3330 $input->getOption('stability'),
3331 $preferSource,
3332 $preferDist,
3333 !$input->getOption('no-dev'),
3334 $input->getOption('repository') ?: $input->getOption('repository-url'),
3335 $input->getOption('no-plugins'),
3336 $input->getOption('no-scripts'),
3337 $input->getOption('no-progress'),
3338 $input->getOption('no-install'),
3339 $input->getOption('ignore-platform-reqs'),
3340 !$input->getOption('no-secure-http')
3341 );
3342 }
3343
3344 public function installProject(IOInterface $io, Config $config, InputInterface $input, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repository = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $noInstall = false, $ignorePlatformReqs = false, $secureHttp = true)
3345 {
3346 $oldCwd = getcwd();
3347
3348
3349  $io->loadConfiguration($config);
3350
3351 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3352
3353 if ($packageName !== null) {
3354 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
3355 } else {
3356 $installedFromVcs = false;
3357 }
3358
3359 $composer = Factory::create($io, null, $disablePlugins);
3360 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3361
3362 $fs = new Filesystem();
3363
3364 if ($noScripts === false) {
3365
3366  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3367 }
3368
3369
3370  $config = $composer->getConfig();
3371 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3372
3373
3374  if ($noInstall === false) {
3375 $installer = Installer::create($io, $composer);
3376 $installer->setPreferSource($preferSource)
3377 ->setPreferDist($preferDist)
3378 ->setDevMode($installDevPackages)
3379 ->setRunScripts(!$noScripts)
3380 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3381 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3382 ->setOptimizeAutoloader($config->get('optimize-autoloader'))
3383 ->setClassMapAuthoritative($config->get('classmap-authoritative'))
3384 ->setApcuAutoloader($config->get('apcu-autoloader'));
3385
3386 if ($disablePlugins) {
3387 $installer->disablePlugins();
3388 }
3389
3390 $status = $installer->run();
3391 if (0 !== $status) {
3392 return $status;
3393 }
3394 }
3395
3396 $hasVcs = $installedFromVcs;
3397 if (
3398 !$input->getOption('keep-vcs')
3399 && $installedFromVcs
3400 && (
3401 $input->getOption('remove-vcs')
3402 || !$io->isInteractive()
3403 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3404 )
3405 ) {
3406 $finder = new Finder();
3407 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3408 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3409 $finder->name($vcsName);
3410 }
3411
3412 try {
3413 $dirs = iterator_to_array($finder);
3414 unset($finder);
3415 foreach ($dirs as $dir) {
3416 if (!$fs->removeDirectory($dir)) {
3417 throw new \RuntimeException('Could not remove '.$dir);
3418 }
3419 }
3420 } catch (\Exception $e) {
3421 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3422 }
3423
3424 $hasVcs = false;
3425 }
3426
3427
3428  if (!$hasVcs) {
3429 $package = $composer->getPackage();
3430 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3431 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3432 foreach ($package->{'get'.$meta['method']}() as $link) {
3433 if ($link->getPrettyConstraint() === 'self.version') {
3434 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3435 }
3436 }
3437 }
3438 }
3439
3440 if ($noScripts === false) {
3441
3442  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3443 }
3444
3445 chdir($oldCwd);
3446 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3447 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3448 Silencer::call('rmdir', $vendorComposerDir);
3449 $vendorDir = $config->get('vendor-dir');
3450 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3451 Silencer::call('rmdir', $vendorDir);
3452 }
3453 }
3454
3455 return 0;
3456 }
3457
3458 protected function installRootPackage(IOInterface $io, Config $config, $packageName, $directory = null, $packageVersion = null, $stability = 'stable', $preferSource = false, $preferDist = false, $installDevPackages = false, $repository = null, $disablePlugins = false, $noScripts = false, $noProgress = false, $ignorePlatformReqs = false, $secureHttp = true)
3459 {
3460 if (!$secureHttp) {
3461 $config->merge(array('config' => array('secure-http' => false)));
3462 }
3463
3464 if (null === $repository) {
3465 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3466 } else {
3467 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3468 }
3469
3470 $parser = new VersionParser();
3471 $requirements = $parser->parseNameVersionPairs(array($packageName));
3472 $name = strtolower($requirements[0]['name']);
3473 if (!$packageVersion && isset($requirements[0]['version'])) {
3474 $packageVersion = $requirements[0]['version'];
3475 }
3476
3477 if (null === $stability) {
3478 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3479 $stability = $match[1];
3480 } else {
3481 $stability = VersionParser::parseStability($packageVersion);
3482 }
3483 }
3484
3485 $stability = VersionParser::normalizeStability($stability);
3486
3487 if (!isset(BasePackage::$stabilities[$stability])) {
3488 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3489 }
3490
3491 $pool = new Pool($stability);
3492 $pool->addRepository($sourceRepo);
3493
3494 $phpVersion = null;
3495 $prettyPhpVersion = null;
3496 if (!$ignorePlatformReqs) {
3497 $platformOverrides = $config->get('platform') ?: array();
3498
3499  $platform = new PlatformRepository(array(), $platformOverrides);
3500 $phpPackage = $platform->findPackage('php', '*');
3501 $phpVersion = $phpPackage->getVersion();
3502 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3503 }
3504
3505
3506  $versionSelector = new VersionSelector($pool);
3507 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3508
3509 if (!$package) {
3510 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3511 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3512 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3513 }
3514
3515 throw new \InvalidArgumentException($errorMessage .'.');
3516 }
3517
3518 if (null === $directory) {
3519 $parts = explode("/", $name, 2);
3520 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3521 }
3522
3523
3524  if (function_exists('pcntl_async_signals')) {
3525 @mkdir($directory, 0777, true);
3526 if ($realDir = realpath($directory)) {
3527 pcntl_async_signals(true);
3528 pcntl_signal(SIGINT, function () use ($realDir) {
3529 $fs = new Filesystem();
3530 $fs->removeDirectory($realDir);
3531 exit(130);
3532 });
3533 }
3534 }
3535
3536 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3537
3538 if ($disablePlugins) {
3539 $io->writeError('<info>Plugins have been disabled.</info>');
3540 }
3541
3542 if ($package instanceof AliasPackage) {
3543 $package = $package->getAliasOf();
3544 }
3545
3546 $dm = $this->createDownloadManager($io, $config);
3547 $dm->setPreferSource($preferSource)
3548 ->setPreferDist($preferDist)
3549 ->setOutputProgress(!$noProgress);
3550
3551 $projectInstaller = new ProjectInstaller($directory, $dm);
3552 $im = $this->createInstallationManager();
3553 $im->addInstaller($projectInstaller);
3554 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3555 $im->notifyInstalls($io);
3556
3557
3558  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3559
3560 $installedFromVcs = 'source' === $package->getInstallationSource();
3561
3562 $io->writeError('<info>Created project in ' . $directory . '</info>');
3563 chdir($directory);
3564
3565 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3566 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3567
3568 return $installedFromVcs;
3569 }
3570
3571 protected function createDownloadManager(IOInterface $io, Config $config)
3572 {
3573 $factory = new Factory();
3574
3575 return $factory->createDownloadManager($io, $config);
3576 }
3577
3578 protected function createInstallationManager()
3579 {
3580 return new InstallationManager();
3581 }
3582 }
3583 <?php
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595 namespace Composer\Command;
3596
3597 use Symfony\Component\Console\Input\InputInterface;
3598 use Symfony\Component\Console\Output\OutputInterface;
3599
3600
3601
3602
3603 class DependsCommand extends BaseDependencyCommand
3604 {
3605
3606
3607
3608 protected function configure()
3609 {
3610 parent::configure();
3611
3612 $this
3613 ->setName('depends')
3614 ->setAliases(array('why'))
3615 ->setDescription('Shows which packages cause the given package to be installed.')
3616 ->setHelp(
3617 <<<EOT
3618 Displays detailed information about where a package is referenced.
3619
3620 <info>php composer.phar depends composer/composer</info>
3621
3622 Read more at https://getcomposer.org/doc/03-cli.md#depends-why-
3623 EOT
3624 )
3625 ;
3626 }
3627
3628
3629
3630
3631
3632
3633
3634
3635 protected function execute(InputInterface $input, OutputInterface $output)
3636 {
3637 return parent::doExecute($input, $output, false);
3638 }
3639 }
3640 <?php
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652 namespace Composer\Command;
3653
3654 use Composer\Composer;
3655 use Composer\Factory;
3656 use Composer\Config;
3657 use Composer\Downloader\TransportException;
3658 use Composer\Repository\PlatformRepository;
3659 use Composer\Plugin\CommandEvent;
3660 use Composer\Plugin\PluginEvents;
3661 use Composer\Util\ConfigValidator;
3662 use Composer\Util\IniHelper;
3663 use Composer\Util\ProcessExecutor;
3664 use Composer\Util\RemoteFilesystem;
3665 use Composer\Util\StreamContextFactory;
3666 use Composer\SelfUpdate\Keys;
3667 use Composer\SelfUpdate\Versions;
3668 use Composer\IO\NullIO;
3669 use Symfony\Component\Console\Input\InputInterface;
3670 use Symfony\Component\Console\Output\OutputInterface;
3671
3672
3673
3674
3675 class DiagnoseCommand extends BaseCommand
3676 {
3677
3678 protected $rfs;
3679
3680
3681 protected $process;
3682
3683
3684 protected $exitCode = 0;
3685
3686 protected function configure()
3687 {
3688 $this
3689 ->setName('diagnose')
3690 ->setDescription('Diagnoses the system to identify common errors.')
3691 ->setHelp(
3692 <<<EOT
3693 The <info>diagnose</info> command checks common errors to help debugging problems.
3694
3695 The process exit code will be 1 in case of warnings and 2 for errors.
3696
3697 Read more at https://getcomposer.org/doc/03-cli.md#diagnose
3698 EOT
3699 )
3700 ;
3701 }
3702
3703
3704
3705
3706 protected function execute(InputInterface $input, OutputInterface $output)
3707 {
3708 $composer = $this->getComposer(false);
3709 $io = $this->getIO();
3710
3711 if ($composer) {
3712 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3713 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3714
3715 $io->write('Checking composer.json: ', false);
3716 $this->outputResult($this->checkComposerSchema());
3717 }
3718
3719 if ($composer) {
3720 $config = $composer->getConfig();
3721 } else {
3722 $config = Factory::createConfig();
3723 }
3724
3725 $config->merge(array('config' => array('secure-http' => false)));
3726 $config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO);
3727
3728 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3729 $this->process = new ProcessExecutor($io);
3730
3731 $io->write('Checking platform settings: ', false);
3732 $this->outputResult($this->checkPlatform());
3733
3734 $io->write('Checking git settings: ', false);
3735 $this->outputResult($this->checkGit());
3736
3737 $io->write('Checking http connectivity to packagist: ', false);
3738 $this->outputResult($this->checkHttp('http', $config));
3739
3740 $io->write('Checking https connectivity to packagist: ', false);
3741 $this->outputResult($this->checkHttp('https', $config));
3742
3743 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3744 if (!empty($opts['http']['proxy'])) {
3745 $io->write('Checking HTTP proxy: ', false);
3746 $this->outputResult($this->checkHttpProxy());
3747 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3748 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3749 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3750 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3751 }
3752
3753 if ($oauth = $config->get('github-oauth')) {
3754 foreach ($oauth as $domain => $token) {
3755 $io->write('Checking '.$domain.' oauth access: ', false);
3756 $this->outputResult($this->checkGithubOauth($domain, $token));
3757 }
3758 } else {
3759 $io->write('Checking github.com rate limit: ', false);
3760 try {
3761 $rate = $this->getGithubRateLimit('github.com');
3762 if (!is_array($rate)) {
3763 $this->outputResult($rate);
3764 } elseif (10 > $rate['remaining']) {
3765 $io->write('<warning>WARNING</warning>');
3766 $io->write(sprintf(
3767 '<comment>Github has a rate limit on their API. '
3768 . 'You currently have <options=bold>%u</options=bold> '
3769 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3770 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3771 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3772 $rate['remaining'],
3773 $rate['limit']
3774 ));
3775 } else {
3776 $this->outputResult(true);
3777 }
3778 } catch (\Exception $e) {
3779 if ($e instanceof TransportException && $e->getCode() === 401) {
3780 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3781 } else {
3782 $this->outputResult($e);
3783 }
3784 }
3785 }
3786
3787 $io->write('Checking disk free space: ', false);
3788 $this->outputResult($this->checkDiskSpace($config));
3789
3790 if ('phar:' === substr(__FILE__, 0, 5)) {
3791 $io->write('Checking pubkeys: ', false);
3792 $this->outputResult($this->checkPubKeys($config));
3793
3794 $io->write('Checking composer version: ', false);
3795 $this->outputResult($this->checkVersion($config));
3796 }
3797
3798 $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::VERSION));
3799
3800 $platformOverrides = $config->get('platform') ?: array();
3801 $platformRepo = new PlatformRepository(array(), $platformOverrides);
3802 $phpPkg = $platformRepo->findPackage('php', '*');
3803 $phpVersion = $phpPkg->getPrettyVersion();
3804 if (false !== strpos($phpPkg->getDescription(), 'overridden')) {
3805 $phpVersion .= ' - ' . $phpPkg->getDescription();
3806 }
3807
3808 $io->write(sprintf('PHP version: <comment>%s</comment>', $phpVersion));
3809
3810 if (defined('PHP_BINARY')) {
3811 $io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
3812 }
3813
3814 return $this->exitCode;
3815 }
3816
3817 private function checkComposerSchema()
3818 {
3819 $validator = new ConfigValidator($this->getIO());
3820 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3821
3822 if ($errors || $warnings) {
3823 $messages = array(
3824 'error' => $errors,
3825 'warning' => $warnings,
3826 );
3827
3828 $output = '';
3829 foreach ($messages as $style => $msgs) {
3830 foreach ($msgs as $msg) {
3831 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3832 }
3833 }
3834
3835 return rtrim($output);
3836 }
3837
3838 return true;
3839 }
3840
3841 private function checkGit()
3842 {
3843 $this->process->execute('git config color.ui', $output);
3844 if (strtolower(trim($output)) === 'always') {
3845 return '<comment>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.</comment>';
3846 }
3847
3848 return true;
3849 }
3850
3851 private function checkHttp($proto, Config $config)
3852 {
3853 $result = $this->checkConnectivity();
3854 if ($result !== true) {
3855 return $result;
3856 }
3857
3858 $disableTls = false;
3859 $result = array();
3860 if ($proto === 'https' && $config->get('disable-tls') === true) {
3861 $disableTls = true;
3862 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3863 }
3864 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3865 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3866 }
3867
3868 try {
3869 $this->rfs->getContents('packagist.org', $proto . '://repo.packagist.org/packages.json', false);
3870 } catch (TransportException $e) {
3871 if (false !== strpos($e->getMessage(), 'cafile')) {
3872 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3873 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3874 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3875 } else {
3876 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3877 }
3878 }
3879
3880 if (count($result) > 0) {
3881 return $result;
3882 }
3883
3884 return true;
3885 }
3886
3887 private function checkHttpProxy()
3888 {
3889 $result = $this->checkConnectivity();
3890 if ($result !== true) {
3891 return $result;
3892 }
3893
3894 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3895 try {
3896 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/packages.json', false), true);
3897 $hash = reset($json['provider-includes']);
3898 $hash = $hash['sha256'];
3899 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3900 $provider = $this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/'.$path, false);
3901
3902 if (hash('sha256', $provider) !== $hash) {
3903 return 'It seems that your proxy is modifying http traffic on the fly';
3904 }
3905 } catch (\Exception $e) {
3906 return $e;
3907 }
3908
3909 return true;
3910 }
3911
3912
3913
3914
3915
3916
3917
3918
3919 private function checkHttpProxyFullUriRequestParam()
3920 {
3921 $result = $this->checkConnectivity();
3922 if ($result !== true) {
3923 return $result;
3924 }
3925
3926 $url = 'http://repo.packagist.org/packages.json';
3927 try {
3928 $this->rfs->getContents('packagist.org', $url, false);
3929 } catch (TransportException $e) {
3930 try {
3931 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3932 } catch (TransportException $e) {
3933 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3934 }
3935
3936 return 'It seems there is a problem with your proxy server, try setting the "HTTP_PROXY_REQUEST_FULLURI" and "HTTPS_PROXY_REQUEST_FULLURI" environment variables to "false"';
3937 }
3938
3939 return true;
3940 }
3941
3942
3943
3944
3945
3946
3947
3948
3949 private function checkHttpsProxyFullUriRequestParam()
3950 {
3951 $result = $this->checkConnectivity();
3952 if ($result !== true) {
3953 return $result;
3954 }
3955
3956 if (!extension_loaded('openssl')) {
3957 return 'You need the openssl extension installed for this check';
3958 }
3959
3960 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3961 try {
3962 $this->rfs->getContents('github.com', $url, false);
3963 } catch (TransportException $e) {
3964 try {
3965 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3966 } catch (TransportException $e) {
3967 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3968 }
3969
3970 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3971 }
3972
3973 return true;
3974 }
3975
3976 private function checkGithubOauth($domain, $token)
3977 {
3978 $result = $this->checkConnectivity();
3979 if ($result !== true) {
3980 return $result;
3981 }
3982
3983 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3984 try {
3985 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3986
3987 return $this->rfs->getContents($domain, $url, false, array(
3988 'retry-auth-failure' => false,
3989 )) ? true : 'Unexpected error';
3990 } catch (\Exception $e) {
3991 if ($e instanceof TransportException && $e->getCode() === 401) {
3992 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3993 }
3994
3995 return $e;
3996 }
3997 }
3998
3999
4000
4001
4002
4003
4004
4005 private function getGithubRateLimit($domain, $token = null)
4006 {
4007 $result = $this->checkConnectivity();
4008 if ($result !== true) {
4009 return $result;
4010 }
4011
4012 if ($token) {
4013 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
4014 }
4015
4016 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
4017 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
4018 $data = json_decode($json, true);
4019
4020 return $data['resources']['core'];
4021 }
4022
4023 private function checkDiskSpace($config)
4024 {
4025 $minSpaceFree = 1024 * 1024;
4026 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
4027 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
4028 ) {
4029 return '<error>The disk hosting '.$dir.' is full</error>';
4030 }
4031
4032 return true;
4033 }
4034
4035 private function checkPubKeys($config)
4036 {
4037 $home = $config->get('home');
4038 $errors = array();
4039 $io = $this->getIO();
4040
4041 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
4042 $io->write('');
4043 }
4044
4045 if (file_exists($home.'/keys.tags.pub')) {
4046 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
4047 } else {
4048 $errors[] = '<error>Missing pubkey for tags verification</error>';
4049 }
4050
4051 if (file_exists($home.'/keys.dev.pub')) {
4052 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
4053 } else {
4054 $errors[] = '<error>Missing pubkey for dev verification</error>';
4055 }
4056
4057 if ($errors) {
4058 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
4059 }
4060
4061 return $errors ?: true;
4062 }
4063
4064 private function checkVersion($config)
4065 {
4066 $result = $this->checkConnectivity();
4067 if ($result !== true) {
4068 return $result;
4069 }
4070
4071 $versionsUtil = new Versions($config, $this->rfs);
4072 $latest = $versionsUtil->getLatest();
4073
4074 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
4075 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
4076 }
4077
4078 return true;
4079 }
4080
4081
4082
4083
4084 private function outputResult($result)
4085 {
4086 $io = $this->getIO();
4087 if (true === $result) {
4088 $io->write('<info>OK</info>');
4089
4090 return;
4091 }
4092
4093 $hadError = false;
4094 $hadWarning = false;
4095 if ($result instanceof \Exception) {
4096 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
4097 }
4098
4099 if (!$result) {
4100
4101  $hadError = true;
4102 } else {
4103 if (!is_array($result)) {
4104 $result = array($result);
4105 }
4106 foreach ($result as $message) {
4107 if (false !== strpos($message, '<error>')) {
4108 $hadError = true;
4109 } elseif (false !== strpos($message, '<warning>')) {
4110 $hadWarning = true;
4111 }
4112 }
4113 }
4114
4115 if ($hadError) {
4116 $io->write('<error>FAIL</error>');
4117 $this->exitCode = max($this->exitCode, 2);
4118 } elseif ($hadWarning) {
4119 $io->write('<warning>WARNING</warning>');
4120 $this->exitCode = max($this->exitCode, 1);
4121 }
4122
4123 if ($result) {
4124 foreach ($result as $message) {
4125 $io->write($message);
4126 }
4127 }
4128 }
4129
4130 private function checkPlatform()
4131 {
4132 $output = '';
4133 $out = function ($msg, $style) use (&$output) {
4134 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
4135 };
4136
4137
4138  $errors = array();
4139 $warnings = array();
4140 $displayIniMessage = false;
4141
4142 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
4143 $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.';
4144
4145 if (!function_exists('json_decode')) {
4146 $errors['json'] = true;
4147 }
4148
4149 if (!extension_loaded('Phar')) {
4150 $errors['phar'] = true;
4151 }
4152
4153 if (!extension_loaded('filter')) {
4154 $errors['filter'] = true;
4155 }
4156
4157 if (!extension_loaded('hash')) {
4158 $errors['hash'] = true;
4159 }
4160
4161 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
4162 $errors['iconv_mbstring'] = true;
4163 }
4164
4165 if (!filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
4166 $errors['allow_url_fopen'] = true;
4167 }
4168
4169 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
4170 $errors['ioncube'] = ioncube_loader_version();
4171 }
4172
4173 if (PHP_VERSION_ID < 50302) {
4174 $errors['php'] = PHP_VERSION;
4175 }
4176
4177 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
4178 $warnings['php'] = PHP_VERSION;
4179 }
4180
4181 if (!extension_loaded('openssl')) {
4182 $errors['openssl'] = true;
4183 }
4184
4185 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
4186 $warnings['openssl_version'] = true;
4187 }
4188
4189 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) {
4190 $warnings['apc_cli'] = true;
4191 }
4192
4193 if (!extension_loaded('zlib')) {
4194 $warnings['zlib'] = true;
4195 }
4196
4197 ob_start();
4198 phpinfo(INFO_GENERAL);
4199 $phpinfo = ob_get_clean();
4200 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
4201 $configure = $match[1];
4202
4203 if (false !== strpos($configure, '--enable-sigchild')) {
4204 $warnings['sigchild'] = true;
4205 }
4206
4207 if (false !== strpos($configure, '--with-curlwrappers')) {
4208 $warnings['curlwrappers'] = true;
4209 }
4210 }
4211
4212 if (filter_var(ini_get('xdebug.profiler_enabled'), FILTER_VALIDATE_BOOLEAN)) {
4213 $warnings['xdebug_profile'] = true;
4214 } elseif (extension_loaded('xdebug')) {
4215 $warnings['xdebug_loaded'] = true;
4216 }
4217
4218 if (!empty($errors)) {
4219 foreach ($errors as $error => $current) {
4220 switch ($error) {
4221 case 'json':
4222 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
4223 $text .= "Install it or recompile php without --disable-json";
4224 break;
4225
4226 case 'phar':
4227 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
4228 $text .= "Install it or recompile php without --disable-phar";
4229 break;
4230
4231 case 'filter':
4232 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
4233 $text .= "Install it or recompile php without --disable-filter";
4234 break;
4235
4236 case 'hash':
4237 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
4238 $text .= "Install it or recompile php without --disable-hash";
4239 break;
4240
4241 case 'iconv_mbstring':
4242 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
4243 $text .= "Install either of them or recompile php without --disable-iconv";
4244 break;
4245
4246 case 'unicode':
4247 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
4248 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4249 $text .= "    detect_unicode = Off";
4250 $displayIniMessage = true;
4251 break;
4252
4253 case 'suhosin':
4254 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
4255 $text .= "Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):".PHP_EOL;
4256 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
4257 $displayIniMessage = true;
4258 break;
4259
4260 case 'php':
4261 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
4262 break;
4263
4264 case 'allow_url_fopen':
4265 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
4266 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4267 $text .= "    allow_url_fopen = On";
4268 $displayIniMessage = true;
4269 break;
4270
4271 case 'ioncube':
4272 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
4273 $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;
4274 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
4275 $displayIniMessage = true;
4276 break;
4277
4278 case 'openssl':
4279 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
4280 $text .= "If possible you should enable it or recompile php with --with-openssl";
4281 break;
4282 }
4283 $out($text, 'error');
4284 }
4285
4286 $output .= PHP_EOL;
4287 }
4288
4289 if (!empty($warnings)) {
4290 foreach ($warnings as $warning => $current) {
4291 switch ($warning) {
4292 case 'apc_cli':
4293 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
4294 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4295 $text .= "  apc.enable_cli = Off";
4296 $displayIniMessage = true;
4297 break;
4298
4299 case 'zlib':
4300 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
4301 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
4302 $displayIniMessage = true;
4303 break;
4304
4305 case 'sigchild':
4306 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
4307 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
4308 $text .= "  https://bugs.php.net/bug.php?id=22999";
4309 break;
4310
4311 case 'curlwrappers':
4312 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
4313 $text .= " Recompile it without this flag if possible";
4314 break;
4315
4316 case 'php':
4317 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
4318 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
4319 break;
4320
4321 case 'openssl_version':
4322
4323  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
4324 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
4325
4326 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
4327 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
4328 break;
4329
4330 case 'xdebug_loaded':
4331 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
4332 $text .= " Disabling it when using Composer is recommended.";
4333 break;
4334
4335 case 'xdebug_profile':
4336 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
4337 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
4338 $text .= "  xdebug.profiler_enabled = 0";
4339 $displayIniMessage = true;
4340 break;
4341 }
4342 $out($text, 'comment');
4343 }
4344 }
4345
4346 if ($displayIniMessage) {
4347 $out($iniMessage, 'comment');
4348 }
4349
4350 return !$warnings && !$errors ? true : $output;
4351 }
4352
4353
4354
4355
4356
4357
4358
4359 private function checkConnectivity()
4360 {
4361 if (!ini_get('allow_url_fopen')) {
4362 $result = '<info>Skipped because allow_url_fopen is missing.</info>';
4363 return $result;
4364 }
4365
4366 return true;
4367 }
4368 }
4369 <?php
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381 namespace Composer\Command;
4382
4383 use Composer\Plugin\CommandEvent;
4384 use Composer\Plugin\PluginEvents;
4385 use Symfony\Component\Console\Input\InputInterface;
4386 use Symfony\Component\Console\Input\InputOption;
4387 use Symfony\Component\Console\Output\OutputInterface;
4388
4389
4390
4391
4392 class DumpAutoloadCommand extends BaseCommand
4393 {
4394 protected function configure()
4395 {
4396 $this
4397 ->setName('dump-autoload')
4398 ->setAliases(array('dumpautoload'))
4399 ->setDescription('Dumps the autoloader.')
4400 ->setDefinition(array(
4401 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4402 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4403 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4404 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4405 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4406 ))
4407 ->setHelp(
4408 <<<EOT
4409 <info>php composer.phar dump-autoload</info>
4410
4411 Read more at https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload-
4412 EOT
4413 )
4414 ;
4415 }
4416
4417 protected function execute(InputInterface $input, OutputInterface $output)
4418 {
4419 $composer = $this->getComposer();
4420
4421 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4422 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4423
4424 $installationManager = $composer->getInstallationManager();
4425 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4426 $package = $composer->getPackage();
4427 $config = $composer->getConfig();
4428
4429 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4430 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4431 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4432
4433 if ($authoritative) {
4434 $this->getIO()->writeError('<info>Generating optimized autoload files (authoritative)</info>', false);
4435 } elseif ($optimize) {
4436 $this->getIO()->writeError('<info>Generating optimized autoload files</info>', false);
4437 } else {
4438 $this->getIO()->writeError('<info>Generating autoload files</info>', false);
4439 }
4440
4441 $generator = $composer->getAutoloadGenerator();
4442 $generator->setDevMode(!$input->getOption('no-dev'));
4443 $generator->setClassMapAuthoritative($authoritative);
4444 $generator->setApcu($apcu);
4445 $generator->setRunScripts(!$input->getOption('no-scripts'));
4446 $numberOfClasses = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4447
4448 if ($authoritative) {
4449 $this->getIO()->overwriteError('<info>Generated optimized autoload files (authoritative) containing '. $numberOfClasses .' classes</info>');
4450 } elseif ($optimize) {
4451 $this->getIO()->overwriteError('<info>Generated optimized autoload files containing '. $numberOfClasses .' classes</info>');
4452 } else {
4453 $this->getIO()->overwriteError('<info>Generated autoload files containing '. $numberOfClasses .' classes</info>');
4454 }
4455
4456 return 0;
4457 }
4458 }
4459 <?php
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471 namespace Composer\Command;
4472
4473 use Symfony\Component\Console\Input\InputInterface;
4474 use Symfony\Component\Console\Input\InputOption;
4475 use Symfony\Component\Console\Output\OutputInterface;
4476 use Symfony\Component\Console\Input\InputArgument;
4477
4478
4479
4480
4481 class ExecCommand extends BaseCommand
4482 {
4483 protected function configure()
4484 {
4485 $this
4486 ->setName('exec')
4487 ->setDescription('Executes a vendored binary/script.')
4488 ->setDefinition(array(
4489 new InputOption('list', 'l', InputOption::VALUE_NONE),
4490 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4491 new InputArgument(
4492 'args',
4493 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4494 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4495 ),
4496 ))
4497 ->setHelp(
4498 <<<EOT
4499 Executes a vendored binary/script.
4500                 
4501 Read more at https://getcomposer.org/doc/03-cli.md#exec
4502 EOT
4503 )
4504 ;
4505 }
4506
4507 protected function execute(InputInterface $input, OutputInterface $output)
4508 {
4509 $composer = $this->getComposer();
4510 $binDir = $composer->getConfig()->get('bin-dir');
4511 if ($input->getOption('list') || !$input->getArgument('binary')) {
4512 $bins = glob($binDir . '/*');
4513 $bins = array_merge($bins, array_map(function ($e) {
4514 return "$e (local)";
4515 }, $composer->getPackage()->getBinaries()));
4516
4517 if (!$bins) {
4518 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4519 }
4520
4521 $this->getIO()->write(
4522 <<<EOT
4523 <comment>Available binaries:</comment>
4524 EOT
4525 );
4526
4527 foreach ($bins as $bin) {
4528
4529  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4530 continue;
4531 }
4532
4533 $previousBin = $bin;
4534 $bin = basename($bin);
4535 $this->getIO()->write(
4536 <<<EOT
4537 <info>- $bin</info>
4538 EOT
4539 );
4540 }
4541
4542 return 0;
4543 }
4544
4545 $binary = $input->getArgument('binary');
4546
4547 $dispatcher = $composer->getEventDispatcher();
4548 $dispatcher->addListener('__exec_command', $binary);
4549 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4550 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4551 }
4552
4553 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4554 }
4555 }
4556 <?php
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568 namespace Composer\Command;
4569
4570 use Composer\Factory;
4571 use Composer\Util\Filesystem;
4572 use Symfony\Component\Console\Input\InputInterface;
4573 use Symfony\Component\Console\Input\InputArgument;
4574 use Symfony\Component\Console\Input\StringInput;
4575 use Symfony\Component\Console\Output\OutputInterface;
4576
4577
4578
4579
4580 class GlobalCommand extends BaseCommand
4581 {
4582 protected function configure()
4583 {
4584 $this
4585 ->setName('global')
4586 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4587 ->setDefinition(array(
4588 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4589 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4590 ))
4591 ->setHelp(
4592 <<<EOT
4593 Use this command as a wrapper to run other Composer commands
4594 within the global context of COMPOSER_HOME.
4595
4596 You can use this to install CLI utilities globally, all you need
4597 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4598
4599 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4600 and /home/<user>/.composer on unix systems.
4601
4602 If your system uses freedesktop.org standards, then it will first check
4603 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4604
4605 Note: This path may vary depending on customizations to bin-dir in
4606 composer.json or the environmental variable COMPOSER_BIN_DIR.
4607
4608 Read more at https://getcomposer.org/doc/03-cli.md#global
4609 EOT
4610 )
4611 ;
4612 }
4613
4614 public function run(InputInterface $input, OutputInterface $output)
4615 {
4616
4617  $tokens = preg_split('{\s+}', $input->__toString());
4618 $args = array();
4619 foreach ($tokens as $token) {
4620 if ($token && $token[0] !== '-') {
4621 $args[] = $token;
4622 if (count($args) >= 2) {
4623 break;
4624 }
4625 }
4626 }
4627
4628
4629  if (count($args) < 2) {
4630 return parent::run($input, $output);
4631 }
4632
4633
4634  $config = Factory::createConfig();
4635 $home = $config->get('home');
4636
4637 if (!is_dir($home)) {
4638 $fs = new Filesystem();
4639 $fs->ensureDirectoryExists($home);
4640 if (!is_dir($home)) {
4641 throw new \RuntimeException('Could not create home directory');
4642 }
4643 }
4644
4645 try {
4646 chdir($home);
4647 } catch (\Exception $e) {
4648 throw new \RuntimeException('Could not switch to home directory "'.$home.'"', 0, $e);
4649 }
4650 $this->getIO()->writeError('<info>Changed current directory to '.$home.'</info>');
4651
4652
4653  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4654 $this->getApplication()->resetComposer();
4655
4656 return $this->getApplication()->run($input, $output);
4657 }
4658
4659
4660
4661
4662 public function isProxyCommand()
4663 {
4664 return true;
4665 }
4666 }
4667 <?php
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679 namespace Composer\Command;
4680
4681 use Composer\Package\CompletePackageInterface;
4682 use Composer\Repository\RepositoryInterface;
4683 use Composer\Repository\ArrayRepository;
4684 use Composer\Repository\RepositoryFactory;
4685 use Composer\Util\Platform;
4686 use Composer\Util\ProcessExecutor;
4687 use Symfony\Component\Console\Input\InputArgument;
4688 use Symfony\Component\Console\Input\InputOption;
4689 use Symfony\Component\Console\Input\InputInterface;
4690 use Symfony\Component\Console\Output\OutputInterface;
4691
4692
4693
4694
4695 class HomeCommand extends BaseCommand
4696 {
4697
4698
4699
4700 protected function configure()
4701 {
4702 $this
4703 ->setName('browse')
4704 ->setAliases(array('home'))
4705 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4706 ->setDefinition(array(
4707 new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.'),
4708 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4709 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4710 ))
4711 ->setHelp(
4712 <<<EOT
4713 The home command opens or shows a package's repository URL or
4714 homepage in your default browser.
4715
4716 To open the homepage by default, use -H or --homepage.
4717 To show instead of open the repository or homepage URL, use -s or --show.
4718
4719 Read more at https://getcomposer.org/doc/03-cli.md#browse-home
4720 EOT
4721 );
4722 }
4723
4724
4725
4726
4727 protected function execute(InputInterface $input, OutputInterface $output)
4728 {
4729 $repos = $this->initializeRepos();
4730 $io = $this->getIO();
4731 $return = 0;
4732
4733 $packages = $input->getArgument('packages');
4734 if (!$packages) {
4735 $io->writeError('No package specified, opening homepage for the root package');
4736 $packages = array($this->getComposer()->getPackage()->getName());
4737 }
4738
4739 foreach ($packages as $packageName) {
4740 $handled = false;
4741 $packageExists = false;
4742 foreach ($repos as $repo) {
4743 foreach ($repo->findPackages($packageName) as $package) {
4744 $packageExists = true;
4745 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4746 $handled = true;
4747 break 2;
4748 }
4749 }
4750 }
4751
4752 if (!$packageExists) {
4753 $return = 1;
4754 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4755 }
4756
4757 if (!$handled) {
4758 $return = 1;
4759 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4760 }
4761 }
4762
4763 return $return;
4764 }
4765
4766 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4767 {
4768 $support = $package->getSupport();
4769 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4770 if (!$url || $showHomepage) {
4771 $url = $package->getHomepage();
4772 }
4773
4774 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4775 return false;
4776 }
4777
4778 if ($showOnly) {
4779 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4780 } else {
4781 $this->openBrowser($url);
4782 }
4783
4784 return true;
4785 }
4786
4787
4788
4789
4790
4791
4792 private function openBrowser($url)
4793 {
4794 $url = ProcessExecutor::escape($url);
4795
4796 $process = new ProcessExecutor($this->getIO());
4797 if (Platform::isWindows()) {
4798 return $process->execute('start "web" explorer "' . $url . '"', $output);
4799 }
4800
4801 $linux = $process->execute('which xdg-open', $output);
4802 $osx = $process->execute('which open', $output);
4803
4804 if (0 === $linux) {
4805 $process->execute('xdg-open ' . $url, $output);
4806 } elseif (0 === $osx) {
4807 $process->execute('open ' . $url, $output);
4808 } else {
4809 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4810 }
4811 }
4812
4813
4814
4815
4816
4817
4818
4819
4820 private function initializeRepos()
4821 {
4822 $composer = $this->getComposer(false);
4823
4824 if ($composer) {
4825 return array_merge(
4826 array(new ArrayRepository(array($composer->getPackage()))), 
4827  array($composer->getRepositoryManager()->getLocalRepository()), 
4828  $composer->getRepositoryManager()->getRepositories() 
4829  );
4830 }
4831
4832 return RepositoryFactory::defaultRepos($this->getIO());
4833 }
4834 }
4835 <?php
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847 namespace Composer\Command;
4848
4849 use Composer\DependencyResolver\Pool;
4850 use Composer\Factory;
4851 use Composer\Json\JsonFile;
4852 use Composer\Package\BasePackage;
4853 use Composer\Package\Version\VersionParser;
4854 use Composer\Package\Version\VersionSelector;
4855 use Composer\Repository\CompositeRepository;
4856 use Composer\Repository\PlatformRepository;
4857 use Composer\Repository\RepositoryFactory;
4858 use Composer\Util\ProcessExecutor;
4859 use Symfony\Component\Console\Input\ArrayInput;
4860 use Symfony\Component\Console\Input\InputInterface;
4861 use Symfony\Component\Console\Input\InputOption;
4862 use Symfony\Component\Console\Output\OutputInterface;
4863 use Symfony\Component\Process\ExecutableFinder;
4864 use Symfony\Component\Process\Process;
4865
4866
4867
4868
4869
4870 class InitCommand extends BaseCommand
4871 {
4872
4873 protected $repos;
4874
4875
4876 private $gitConfig;
4877
4878
4879 private $pools;
4880
4881
4882
4883
4884 protected function configure()
4885 {
4886 $this
4887 ->setName('init')
4888 ->setDescription('Creates a basic composer.json file in current directory.')
4889 ->setDefinition(array(
4890 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4891 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4892 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4893
4894  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4895 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4896 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"'),
4897 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"'),
4898 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4899 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4900 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4901 ))
4902 ->setHelp(
4903 <<<EOT
4904 The <info>init</info> command creates a basic composer.json file
4905 in the current directory.
4906
4907 <info>php composer.phar init</info>
4908
4909 Read more at https://getcomposer.org/doc/03-cli.md#init
4910 EOT
4911 )
4912 ;
4913 }
4914
4915
4916
4917
4918 protected function execute(InputInterface $input, OutputInterface $output)
4919 {
4920 $io = $this->getIO();
4921
4922 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4923 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4924
4925 if (isset($options['author'])) {
4926 $options['authors'] = $this->formatAuthors($options['author']);
4927 unset($options['author']);
4928 }
4929
4930 $repositories = $input->getOption('repository');
4931 if ($repositories) {
4932 $config = Factory::createConfig($io);
4933 foreach ($repositories as $repo) {
4934 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4935 }
4936 }
4937
4938 if (isset($options['stability'])) {
4939 $options['minimum-stability'] = $options['stability'];
4940 unset($options['stability']);
4941 }
4942
4943 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4944 if (array() === $options['require']) {
4945 $options['require'] = new \stdClass;
4946 }
4947
4948 if (isset($options['require-dev'])) {
4949 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4950 if (array() === $options['require-dev']) {
4951 $options['require-dev'] = new \stdClass;
4952 }
4953 }
4954
4955 $file = new JsonFile(Factory::getComposerFile());
4956 $json = $file->encode($options);
4957
4958 if ($input->isInteractive()) {
4959 $io->writeError(array('', $json, ''));
4960 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4961 $io->writeError('<error>Command aborted</error>');
4962
4963 return 1;
4964 }
4965 }
4966
4967 $file->write($options);
4968
4969 if ($input->isInteractive() && is_dir('.git')) {
4970 $ignoreFile = realpath('.gitignore');
4971
4972 if (false === $ignoreFile) {
4973 $ignoreFile = realpath('.') . '/.gitignore';
4974 }
4975
4976 if (!$this->hasVendorIgnore($ignoreFile)) {
4977 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4978
4979 if ($io->askConfirmation($question, true)) {
4980 $this->addVendorIgnore($ignoreFile);
4981 }
4982 }
4983 }
4984
4985 $question = 'Would you like to install dependencies now [<comment>yes</comment>]? ';
4986 if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question, true)) {
4987 $this->installDependencies($output);
4988 }
4989
4990 return 0;
4991 }
4992
4993
4994
4995
4996 protected function interact(InputInterface $input, OutputInterface $output)
4997 {
4998 $git = $this->getGitConfig();
4999 $io = $this->getIO();
5000 $formatter = $this->getHelperSet()->get('formatter');
5001
5002
5003  $repositories = $input->getOption('repository');
5004 if ($repositories) {
5005 $config = Factory::createConfig($io);
5006 $repos = array(new PlatformRepository);
5007 $createDefaultPackagistRepo = true;
5008 foreach ($repositories as $repo) {
5009 $repoConfig = RepositoryFactory::configFromString($io, $config, $repo);
5010 if (
5011 (isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
5012 || (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
5013 ) {
5014 $createDefaultPackagistRepo = false;
5015 continue;
5016 }
5017 $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig);
5018 }
5019
5020 if ($createDefaultPackagistRepo) {
5021 $repos[] = RepositoryFactory::createRepo($io, $config, array(
5022 'type' => 'composer',
5023 'url' => 'https://repo.packagist.org',
5024 ));
5025 }
5026
5027 $this->repos = new CompositeRepository($repos);
5028 unset($repos, $config, $repositories);
5029 }
5030
5031 $io->writeError(array(
5032 '',
5033 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
5034 '',
5035 ));
5036
5037
5038  $io->writeError(array(
5039 '',
5040 'This command will guide you through creating your composer.json config.',
5041 '',
5042 ));
5043
5044 $cwd = realpath(".");
5045
5046 if (!$name = $input->getOption('name')) {
5047 $name = basename($cwd);
5048 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
5049 $name = strtolower($name);
5050 if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
5051 $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
5052 } elseif (isset($git['github.user'])) {
5053 $name = $git['github.user'] . '/' . $name;
5054 } elseif (!empty($_SERVER['USERNAME'])) {
5055 $name = $_SERVER['USERNAME'] . '/' . $name;
5056 } elseif (!empty($_SERVER['USER'])) {
5057 $name = $_SERVER['USER'] . '/' . $name;
5058 } elseif (get_current_user()) {
5059 $name = get_current_user() . '/' . $name;
5060 } else {
5061
5062  $name .= '/' . $name;
5063 }
5064 $name = strtolower($name);
5065 } else {
5066 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $name)) {
5067 throw new \InvalidArgumentException(
5068 'The package name '.$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_.-]+'
5069 );
5070 }
5071 }
5072
5073 $name = $io->askAndValidate(
5074 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
5075 function ($value) use ($name) {
5076 if (null === $value) {
5077 return $name;
5078 }
5079
5080 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $value)) {
5081 throw new \InvalidArgumentException(
5082 '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_.-]+'
5083 );
5084 }
5085
5086 return $value;
5087 },
5088 null,
5089 $name
5090 );
5091 $input->setOption('name', $name);
5092
5093 $description = $input->getOption('description') ?: false;
5094 $description = $io->ask(
5095 'Description [<comment>'.$description.'</comment>]: ',
5096 $description
5097 );
5098 $input->setOption('description', $description);
5099
5100 if (null === $author = $input->getOption('author')) {
5101 if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
5102 $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
5103 } elseif (isset($git['user.name'])) {
5104 $author_name = $git['user.name'];
5105 }
5106
5107 if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
5108 $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
5109 } elseif (isset($git['user.email'])) {
5110 $author_email = $git['user.email'];
5111 }
5112
5113 if (isset($author_name) && isset($author_email)) {
5114 $author = sprintf('%s <%s>', $author_name, $author_email);
5115 }
5116 }
5117
5118 $self = $this;
5119 $author = $io->askAndValidate(
5120 'Author [<comment>'.$author.'</comment>, n to skip]: ',
5121 function ($value) use ($self, $author) {
5122 if ($value === 'n' || $value === 'no') {
5123 return;
5124 }
5125 $value = $value ?: $author;
5126 $author = $self->parseAuthorString($value);
5127
5128 return sprintf('%s <%s>', $author['name'], $author['email']);
5129 },
5130 null,
5131 $author
5132 );
5133 $input->setOption('author', $author);
5134
5135 $minimumStability = $input->getOption('stability') ?: null;
5136 $minimumStability = $io->askAndValidate(
5137 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
5138 function ($value) use ($minimumStability) {
5139 if (null === $value) {
5140 return $minimumStability;
5141 }
5142
5143 if (!isset(BasePackage::$stabilities[$value])) {
5144 throw new \InvalidArgumentException(
5145 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
5146 implode(', ', array_keys(BasePackage::$stabilities))
5147 );
5148 }
5149
5150 return $value;
5151 },
5152 null,
5153 $minimumStability
5154 );
5155 $input->setOption('stability', $minimumStability);
5156
5157 $type = $input->getOption('type') ?: false;
5158 $type = $io->ask(
5159 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
5160 $type
5161 );
5162 $input->setOption('type', $type);
5163
5164 if (null === $license = $input->getOption('license')) {
5165 if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
5166 $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
5167 }
5168 }
5169
5170 $license = $io->ask(
5171 'License [<comment>'.$license.'</comment>]: ',
5172 $license
5173 );
5174 $input->setOption('license', $license);
5175
5176 $io->writeError(array('', 'Define your dependencies.', ''));
5177
5178
5179  $repos = $this->getRepos();
5180 $preferredStability = $minimumStability ?: 'stable';
5181 $phpVersion = $repos->findPackage('php', '*')->getPrettyVersion();
5182
5183 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
5184 $require = $input->getOption('require');
5185 $requirements = array();
5186 if ($require || $io->askConfirmation($question, true)) {
5187 $requirements = $this->determineRequirements($input, $output, $require, $phpVersion, $preferredStability);
5188 }
5189 $input->setOption('require', $requirements);
5190
5191 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
5192 $requireDev = $input->getOption('require-dev');
5193 $devRequirements = array();
5194 if ($requireDev || $io->askConfirmation($question, true)) {
5195 $devRequirements = $this->determineRequirements($input, $output, $requireDev, $phpVersion, $preferredStability);
5196 }
5197 $input->setOption('require-dev', $devRequirements);
5198 }
5199
5200
5201
5202
5203
5204
5205 public function parseAuthorString($author)
5206 {
5207 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
5208 if ($this->isValidEmail($match['email'])) {
5209 return array(
5210 'name' => trim($match['name']),
5211 'email' => $match['email'],
5212 );
5213 }
5214 }
5215
5216 throw new \InvalidArgumentException(
5217 'Invalid author string.  Must be in the format: '.
5218 'John Smith <john@example.com>'
5219 );
5220 }
5221
5222 protected function findPackages($name)
5223 {
5224 return $this->getRepos()->search($name);
5225 }
5226
5227 protected function getRepos()
5228 {
5229 if (!$this->repos) {
5230 $this->repos = new CompositeRepository(array_merge(
5231 array(new PlatformRepository),
5232 RepositoryFactory::defaultRepos($this->getIO())
5233 ));
5234 }
5235
5236 return $this->repos;
5237 }
5238
5239 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true)
5240 {
5241 if ($requires) {
5242 $requires = $this->normalizeRequirements($requires);
5243 $result = array();
5244 $io = $this->getIO();
5245
5246 foreach ($requires as $requirement) {
5247 if (!isset($requirement['version'])) {
5248
5249  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
5250 $requirement['version'] = $version;
5251
5252
5253  $requirement['name'] = $name;
5254
5255 $io->writeError(sprintf(
5256 'Using version <info>%s</info> for <info>%s</info>',
5257 $requirement['version'],
5258 $requirement['name']
5259 ));
5260 } else {
5261
5262  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev');
5263
5264
5265  $requirement['name'] = $name;
5266 }
5267
5268 $result[] = $requirement['name'] . ' ' . $requirement['version'];
5269 }
5270
5271 return $result;
5272 }
5273
5274 $versionParser = new VersionParser();
5275 $io = $this->getIO();
5276 while (null !== $package = $io->ask('Search for a package: ')) {
5277 $matches = $this->findPackages($package);
5278
5279 if (count($matches)) {
5280 $exactMatch = null;
5281 $choices = array();
5282 foreach ($matches as $position => $foundPackage) {
5283 $abandoned = '';
5284 if (isset($foundPackage['abandoned'])) {
5285 if (is_string($foundPackage['abandoned'])) {
5286 $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
5287 } else {
5288 $replacement = 'No replacement was suggested';
5289 }
5290 $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
5291 }
5292
5293 $choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
5294 if ($foundPackage['name'] === $package) {
5295 $exactMatch = true;
5296 break;
5297 }
5298 }
5299
5300
5301  if (!$exactMatch) {
5302 $io->writeError(array(
5303 '',
5304 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
5305 '',
5306 ));
5307
5308 $io->writeError($choices);
5309 $io->writeError('');
5310
5311 $validator = function ($selection) use ($matches, $versionParser) {
5312 if ('' === $selection) {
5313 return false;
5314 }
5315
5316 if (is_numeric($selection) && isset($matches[(int) $selection])) {
5317 $package = $matches[(int) $selection];
5318
5319 return $package['name'];
5320 }
5321
5322 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
5323 if (isset($packageMatches['version'])) {
5324
5325
5326
5327  $versionParser->parseConstraints($packageMatches['version']);
5328
5329 return $packageMatches['name'].' '.$packageMatches['version'];
5330 }
5331
5332
5333  return $packageMatches['name'];
5334 }
5335
5336 throw new \Exception('Not a valid selection');
5337 };
5338
5339 $package = $io->askAndValidate(
5340 'Enter package # to add, or the complete package name if it is not listed: ',
5341 $validator,
5342 3,
5343 false
5344 );
5345 }
5346
5347
5348  if (false !== $package && false === strpos($package, ' ')) {
5349 $validator = function ($input) {
5350 $input = trim($input);
5351
5352 return $input ?: false;
5353 };
5354
5355 $constraint = $io->askAndValidate(
5356 'Enter the version constraint to require (or leave blank to use the latest version): ',
5357 $validator,
5358 3,
5359 false
5360 );
5361
5362 if (false === $constraint) {
5363 list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
5364
5365 $io->writeError(sprintf(
5366 'Using version <info>%s</info> for <info>%s</info>',
5367 $constraint,
5368 $package
5369 ));
5370 }
5371
5372 $package .= ' '.$constraint;
5373 }
5374
5375 if (false !== $package) {
5376 $requires[] = $package;
5377 }
5378 }
5379 }
5380
5381 return $requires;
5382 }
5383
5384 protected function formatAuthors($author)
5385 {
5386 return array($this->parseAuthorString($author));
5387 }
5388
5389 protected function formatRequirements(array $requirements)
5390 {
5391 $requires = array();
5392 $requirements = $this->normalizeRequirements($requirements);
5393 foreach ($requirements as $requirement) {
5394 $requires[$requirement['name']] = $requirement['version'];
5395 }
5396
5397 return $requires;
5398 }
5399
5400 protected function getGitConfig()
5401 {
5402 if (null !== $this->gitConfig) {
5403 return $this->gitConfig;
5404 }
5405
5406 $finder = new ExecutableFinder();
5407 $gitBin = $finder->find('git');
5408
5409
5410  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
5411 $cmd = new Process(array($gitBin, 'config', '-l'));
5412 } else {
5413 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
5414 }
5415 $cmd->run();
5416
5417 if ($cmd->isSuccessful()) {
5418 $this->gitConfig = array();
5419 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
5420 foreach ($matches as $match) {
5421 $this->gitConfig[$match[1]] = $match[2];
5422 }
5423
5424 return $this->gitConfig;
5425 }
5426
5427 return $this->gitConfig = array();
5428 }
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
5447 {
5448 if (!file_exists($ignoreFile)) {
5449 return false;
5450 }
5451
5452 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
5453
5454 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
5455 foreach ($lines as $line) {
5456 if (preg_match($pattern, $line)) {
5457 return true;
5458 }
5459 }
5460
5461 return false;
5462 }
5463
5464 protected function normalizeRequirements(array $requirements)
5465 {
5466 $parser = new VersionParser();
5467
5468 return $parser->parseNameVersionPairs($requirements);
5469 }
5470
5471 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
5472 {
5473 $contents = "";
5474 if (file_exists($ignoreFile)) {
5475 $contents = file_get_contents($ignoreFile);
5476
5477 if ("\n" !== substr($contents, 0, -1)) {
5478 $contents .= "\n";
5479 }
5480 }
5481
5482 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5483 }
5484
5485 protected function isValidEmail($email)
5486 {
5487
5488  if (!function_exists('filter_var')) {
5489 return true;
5490 }
5491
5492
5493  if (PHP_VERSION_ID < 50303) {
5494 return true;
5495 }
5496
5497 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5498 }
5499
5500 private function getPool(InputInterface $input, $minimumStability = null)
5501 {
5502 $key = $minimumStability ?: 'default';
5503
5504 if (!isset($this->pools[$key])) {
5505 $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5506 $pool->addRepository($this->getRepos());
5507 }
5508
5509 return $this->pools[$key];
5510 }
5511
5512 private function getMinimumStability(InputInterface $input)
5513 {
5514 if ($input->hasOption('stability')) {
5515 return $input->getOption('stability') ?: 'stable';
5516 }
5517
5518 $file = Factory::getComposerFile();
5519 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5520 if (!empty($composer['minimum-stability'])) {
5521 return $composer['minimum-stability'];
5522 }
5523 }
5524
5525 return 'stable';
5526 }
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542 private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null)
5543 {
5544
5545  $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5546 $ignorePlatformReqs = $input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs');
5547
5548
5549  if ($ignorePlatformReqs) {
5550 $phpVersion = null;
5551 }
5552
5553 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5554
5555 if (!$package) {
5556
5557  
5558  if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
5559 return array($name, $requiredVersion ?: '*');
5560 }
5561
5562
5563  if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
5564 throw new \InvalidArgumentException(sprintf(
5565 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)',
5566 $name,
5567 $requiredVersion,
5568 $phpVersion
5569 ));
5570 }
5571
5572  if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
5573 throw new \InvalidArgumentException(sprintf(
5574 'Could not find package %s in a version matching %s',
5575 $name,
5576 $requiredVersion
5577 ));
5578 }
5579
5580  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5581 throw new \InvalidArgumentException(sprintf(
5582 'Could not find package %s in any version matching your PHP version (%s)',
5583 $name,
5584 $phpVersion
5585 ));
5586 }
5587
5588
5589  $similar = $this->findSimilar($name);
5590 if ($similar) {
5591
5592  if ($requiredVersion === null && in_array($name, $similar, true)) {
5593 throw new \InvalidArgumentException(sprintf(
5594 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
5595 $name,
5596 $this->getMinimumStability($input)
5597 ));
5598 }
5599
5600 throw new \InvalidArgumentException(sprintf(
5601 "Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s",
5602 $name,
5603 implode("\n    ", $similar)
5604 ));
5605 }
5606
5607 throw new \InvalidArgumentException(sprintf(
5608 '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).',
5609 $name,
5610 $this->getMinimumStability($input)
5611 ));
5612 }
5613
5614 return array(
5615 $package->getPrettyName(),
5616 $versionSelector->findRecommendedRequireVersion($package),
5617 );
5618 }
5619
5620 private function findSimilar($package)
5621 {
5622 try {
5623 $results = $this->repos->search($package);
5624 } catch (\Exception $e) {
5625
5626  return array();
5627 }
5628 $similarPackages = array();
5629
5630 foreach ($results as $result) {
5631 $similarPackages[$result['name']] = levenshtein($package, $result['name']);
5632 }
5633 asort($similarPackages);
5634
5635 return array_keys(array_slice($similarPackages, 0, 5));
5636 }
5637
5638 private function installDependencies($output)
5639 {
5640 try {
5641 $installCommand = $this->getApplication()->find('install');
5642 $installCommand->run(new ArrayInput(array()), $output);
5643 } catch (\Exception $e) {
5644 $this->getIO()->writeError('Could not install dependencies. Run `composer install` to see more information.');
5645 }
5646
5647 }
5648
5649 private function hasDependencies($options)
5650 {
5651 $requires = (array) $options['require'];
5652 $devRequires = isset($options['require-dev']) ? (array) $options['require-dev'] : array();
5653
5654 return !empty($requires) || !empty($devRequires);
5655 }
5656 }
5657 <?php
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669 namespace Composer\Command;
5670
5671 use Composer\Installer;
5672 use Composer\Plugin\CommandEvent;
5673 use Composer\Plugin\PluginEvents;
5674 use Symfony\Component\Console\Input\InputInterface;
5675 use Symfony\Component\Console\Input\InputOption;
5676 use Symfony\Component\Console\Input\InputArgument;
5677 use Symfony\Component\Console\Output\OutputInterface;
5678
5679
5680
5681
5682
5683
5684
5685 class InstallCommand extends BaseCommand
5686 {
5687 protected function configure()
5688 {
5689 $this
5690 ->setName('install')
5691 ->setAliases(array('i'))
5692 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5693 ->setDefinition(array(
5694 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5695 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5696 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5697 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5698 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5699 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5700 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5701 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5702 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5703 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5704 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5705 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5706 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5707 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5708 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5709 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5710 ))
5711 ->setHelp(
5712 <<<EOT
5713 The <info>install</info> command reads the composer.lock file from
5714 the current directory, processes it, and downloads and installs all the
5715 libraries and dependencies outlined in that file. If the file does not
5716 exist it will look for composer.json and do the same.
5717
5718 <info>php composer.phar install</info>
5719
5720 Read more at https://getcomposer.org/doc/03-cli.md#install-i
5721 EOT
5722 )
5723 ;
5724 }
5725
5726 protected function execute(InputInterface $input, OutputInterface $output)
5727 {
5728 $io = $this->getIO();
5729 if ($args = $input->getArgument('packages')) {
5730 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5731
5732 return 1;
5733 }
5734
5735 if ($input->getOption('no-custom-installers')) {
5736 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5737 $input->setOption('no-plugins', true);
5738 }
5739
5740 if ($input->getOption('dev')) {
5741 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5742 }
5743
5744 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5745 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5746
5747 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5748 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5749
5750 $install = Installer::create($io, $composer);
5751
5752 $config = $composer->getConfig();
5753 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5754
5755 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5756 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5757 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5758
5759 $install
5760 ->setDryRun($input->getOption('dry-run'))
5761 ->setVerbose($input->getOption('verbose'))
5762 ->setPreferSource($preferSource)
5763 ->setPreferDist($preferDist)
5764 ->setDevMode(!$input->getOption('no-dev'))
5765 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5766 ->setRunScripts(!$input->getOption('no-scripts'))
5767 ->setSkipSuggest($input->getOption('no-suggest'))
5768 ->setOptimizeAutoloader($optimize)
5769 ->setClassMapAuthoritative($authoritative)
5770 ->setApcuAutoloader($apcu)
5771 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5772 ;
5773
5774 if ($input->getOption('no-plugins')) {
5775 $install->disablePlugins();
5776 }
5777
5778 return $install->run();
5779 }
5780 }
5781 <?php
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793 namespace Composer\Command;
5794
5795 use Composer\Json\JsonFile;
5796 use Composer\Plugin\CommandEvent;
5797 use Composer\Plugin\PluginEvents;
5798 use Composer\Package\PackageInterface;
5799 use Composer\Repository\RepositoryInterface;
5800 use Symfony\Component\Console\Helper\Table;
5801 use Symfony\Component\Console\Input\InputInterface;
5802 use Symfony\Component\Console\Input\InputOption;
5803 use Symfony\Component\Console\Output\OutputInterface;
5804
5805
5806
5807
5808 class LicensesCommand extends BaseCommand
5809 {
5810 protected function configure()
5811 {
5812 $this
5813 ->setName('licenses')
5814 ->setDescription('Shows information about licenses of dependencies.')
5815 ->setDefinition(array(
5816 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5817 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5818 ))
5819 ->setHelp(
5820 <<<EOT
5821 The license command displays detailed information about the licenses of
5822 the installed dependencies.
5823
5824 Read more at https://getcomposer.org/doc/03-cli.md#licenses
5825 EOT
5826 )
5827 ;
5828 }
5829
5830 protected function execute(InputInterface $input, OutputInterface $output)
5831 {
5832 $composer = $this->getComposer();
5833
5834 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5835 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5836
5837 $root = $composer->getPackage();
5838 $repo = $composer->getRepositoryManager()->getLocalRepository();
5839
5840 if ($input->getOption('no-dev')) {
5841 $packages = $this->filterRequiredPackages($repo, $root);
5842 } else {
5843 $packages = $this->appendPackages($repo->getPackages(), array());
5844 }
5845
5846 ksort($packages);
5847 $io = $this->getIO();
5848
5849 switch ($format = $input->getOption('format')) {
5850 case 'text':
5851 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5852 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5853 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5854 $io->write('Dependencies:');
5855 $io->write('');
5856
5857 $table = new Table($output);
5858 $table->setStyle('compact');
5859 $tableStyle = $table->getStyle();
5860 $tableStyle->setVerticalBorderChar('');
5861 $tableStyle->setCellRowContentFormat('%s  ');
5862 $table->setHeaders(array('Name', 'Version', 'License'));
5863 foreach ($packages as $package) {
5864 $table->addRow(array(
5865 $package->getPrettyName(),
5866 $package->getFullPrettyVersion(),
5867 implode(', ', $package->getLicense()) ?: 'none',
5868 ));
5869 }
5870 $table->render();
5871 break;
5872
5873 case 'json':
5874 $dependencies = array();
5875 foreach ($packages as $package) {
5876 $dependencies[$package->getPrettyName()] = array(
5877 'version' => $package->getFullPrettyVersion(),
5878 'license' => $package->getLicense(),
5879 );
5880 }
5881
5882 $io->write(JsonFile::encode(array(
5883 'name' => $root->getPrettyName(),
5884 'version' => $root->getFullPrettyVersion(),
5885 'license' => $root->getLicense(),
5886 'dependencies' => $dependencies,
5887 )));
5888 break;
5889
5890 default:
5891 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5892 }
5893
5894 return 0;
5895 }
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5906 {
5907 $requires = array_keys($package->getRequires());
5908
5909 $packageListNames = array_keys($bucket);
5910 $packages = array_filter(
5911 $repo->getPackages(),
5912 function ($package) use ($requires, $packageListNames) {
5913 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5914 }
5915 );
5916
5917 $bucket = $this->appendPackages($packages, $bucket);
5918
5919 foreach ($packages as $package) {
5920 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5921 }
5922
5923 return $bucket;
5924 }
5925
5926
5927
5928
5929
5930
5931
5932
5933 public function appendPackages(array $packages, array $bucket)
5934 {
5935 foreach ($packages as $package) {
5936 $bucket[$package->getName()] = $package;
5937 }
5938
5939 return $bucket;
5940 }
5941 }
5942 <?php
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954 namespace Composer\Command;
5955
5956 use Symfony\Component\Console\Input\InputInterface;
5957 use Symfony\Component\Console\Input\InputArgument;
5958 use Symfony\Component\Console\Input\ArrayInput;
5959 use Symfony\Component\Console\Input\InputOption;
5960 use Symfony\Component\Console\Output\OutputInterface;
5961
5962
5963
5964
5965 class OutdatedCommand extends ShowCommand
5966 {
5967 protected function configure()
5968 {
5969 $this
5970 ->setName('outdated')
5971 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5972 ->setDefinition(array(
5973 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5974 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5975 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5976 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5977 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5978 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5979 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5980 new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.'),
5981 ))
5982 ->setHelp(
5983 <<<EOT
5984 The outdated command is just a proxy for `composer show -l`
5985
5986 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5987
5988 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5989 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5990   compatibility breaks according to semver, so upgrade when you can but it
5991   may involve work.
5992 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5993
5994 Read more at https://getcomposer.org/doc/03-cli.md#outdated
5995 EOT
5996 )
5997 ;
5998 }
5999
6000 protected function execute(InputInterface $input, OutputInterface $output)
6001 {
6002 $args = array(
6003 'command' => 'show',
6004 '--latest' => true,
6005 );
6006 if (!$input->getOption('all')) {
6007 $args['--outdated'] = true;
6008 }
6009 if ($input->getOption('direct')) {
6010 $args['--direct'] = true;
6011 }
6012 if ($input->getArgument('package')) {
6013 $args['package'] = $input->getArgument('package');
6014 }
6015 if ($input->getOption('strict')) {
6016 $args['--strict'] = true;
6017 }
6018 if ($input->getOption('minor-only')) {
6019 $args['--minor-only'] = true;
6020 }
6021 $args['--format'] = $input->getOption('format');
6022 $args['--ignore'] = $input->getOption('ignore');
6023
6024 $input = new ArrayInput($args);
6025
6026 return $this->getApplication()->run($input, $output);
6027 }
6028
6029
6030
6031
6032 public function isProxyCommand()
6033 {
6034 return true;
6035 }
6036 }
6037 <?php
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049 namespace Composer\Command;
6050
6051 use Symfony\Component\Console\Input\InputInterface;
6052 use Symfony\Component\Console\Output\OutputInterface;
6053
6054
6055
6056
6057 class ProhibitsCommand extends BaseDependencyCommand
6058 {
6059
6060
6061
6062 protected function configure()
6063 {
6064 parent::configure();
6065
6066 $this
6067 ->setName('prohibits')
6068 ->setAliases(array('why-not'))
6069 ->setDescription('Shows which packages prevent the given package from being installed.')
6070 ->setHelp(
6071 <<<EOT
6072 Displays detailed information about why a package cannot be installed.
6073
6074 <info>php composer.phar prohibits composer/composer</info>
6075
6076 Read more at https://getcomposer.org/doc/03-cli.md#prohibits-why-not-
6077 EOT
6078 )
6079 ;
6080 }
6081
6082
6083
6084
6085
6086
6087
6088
6089 protected function execute(InputInterface $input, OutputInterface $output)
6090 {
6091 return parent::doExecute($input, $output, true);
6092 }
6093 }
6094 <?php
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106 namespace Composer\Command;
6107
6108 use Composer\Config\JsonConfigSource;
6109 use Composer\Installer;
6110 use Composer\Plugin\CommandEvent;
6111 use Composer\Plugin\PluginEvents;
6112 use Composer\Json\JsonFile;
6113 use Composer\Factory;
6114 use Symfony\Component\Console\Input\InputInterface;
6115 use Symfony\Component\Console\Input\InputOption;
6116 use Symfony\Component\Console\Input\InputArgument;
6117 use Symfony\Component\Console\Output\OutputInterface;
6118 use Composer\Package\BasePackage;
6119
6120
6121
6122
6123
6124 class RemoveCommand extends BaseCommand
6125 {
6126 protected function configure()
6127 {
6128 $this
6129 ->setName('remove')
6130 ->setDescription('Removes a package from the require or require-dev.')
6131 ->setDefinition(array(
6132 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
6133 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
6134 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6135 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6136 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6137 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6138 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
6139 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
6140 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6141 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6142 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6143 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6144 ))
6145 ->setHelp(
6146 <<<EOT
6147 The <info>remove</info> command removes a package from the current
6148 list of installed packages
6149
6150 <info>php composer.phar remove</info>
6151
6152 Read more at https://getcomposer.org/doc/03-cli.md#remove
6153 EOT
6154 )
6155 ;
6156 }
6157
6158 protected function execute(InputInterface $input, OutputInterface $output)
6159 {
6160 $packages = $input->getArgument('packages');
6161 $packages = array_map('strtolower', $packages);
6162
6163 $file = Factory::getComposerFile();
6164
6165 $jsonFile = new JsonFile($file);
6166 $composer = $jsonFile->read();
6167 $composerBackup = file_get_contents($jsonFile->getPath());
6168
6169 $json = new JsonConfigSource($jsonFile);
6170
6171 $type = $input->getOption('dev') ? 'require-dev' : 'require';
6172 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
6173 $io = $this->getIO();
6174
6175 if ($input->getOption('update-with-dependencies')) {
6176 $io->writeError('<warning>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.</warning>');
6177 }
6178
6179
6180  foreach (array('require', 'require-dev') as $linkType) {
6181 if (isset($composer[$linkType])) {
6182 foreach ($composer[$linkType] as $name => $version) {
6183 $composer[$linkType][strtolower($name)] = $name;
6184 }
6185 }
6186 }
6187
6188 foreach ($packages as $package) {
6189 if (isset($composer[$type][$package])) {
6190 $json->removeLink($type, $composer[$type][$package]);
6191 } elseif (isset($composer[$altType][$package])) {
6192 $io->writeError('<warning>' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6193 if ($io->isInteractive()) {
6194 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6195 $json->removeLink($altType, $composer[$altType][$package]);
6196 }
6197 }
6198 } elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) {
6199 foreach ($matches as $matchedPackage) {
6200 $json->removeLink($type, $matchedPackage);
6201 }
6202 } elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) {
6203 foreach ($matches as $matchedPackage) {
6204 $io->writeError('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6205 if ($io->isInteractive()) {
6206 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6207 $json->removeLink($altType, $matchedPackage);
6208 }
6209 }
6210 }
6211 } else {
6212 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
6213 }
6214 }
6215
6216 if ($input->getOption('no-update')) {
6217 return 0;
6218 }
6219
6220
6221  $this->resetComposer();
6222 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6223 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6224
6225 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
6226 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6227
6228 $install = Installer::create($io, $composer);
6229
6230 $updateDevMode = !$input->getOption('update-no-dev');
6231 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6232 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6233 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6234
6235 $install
6236 ->setVerbose($input->getOption('verbose'))
6237 ->setDevMode($updateDevMode)
6238 ->setOptimizeAutoloader($optimize)
6239 ->setClassMapAuthoritative($authoritative)
6240 ->setApcuAutoloader($apcu)
6241 ->setUpdate(true)
6242 ->setUpdateWhitelist($packages)
6243 ->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
6244 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6245 ->setRunScripts(!$input->getOption('no-scripts'))
6246 ;
6247
6248 $status = $install->run();
6249 if ($status !== 0) {
6250 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
6251 file_put_contents($jsonFile->getPath(), $composerBackup);
6252 }
6253
6254 return $status;
6255 }
6256 }
6257 <?php
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269 namespace Composer\Command;
6270
6271 use Symfony\Component\Console\Input\InputInterface;
6272 use Symfony\Component\Console\Input\InputArgument;
6273 use Symfony\Component\Console\Input\InputOption;
6274 use Symfony\Component\Console\Output\OutputInterface;
6275 use Composer\Factory;
6276 use Composer\Installer;
6277 use Composer\Json\JsonFile;
6278 use Composer\Json\JsonManipulator;
6279 use Composer\Package\Version\VersionParser;
6280 use Composer\Plugin\CommandEvent;
6281 use Composer\Plugin\PluginEvents;
6282 use Composer\Repository\CompositeRepository;
6283 use Composer\Repository\PlatformRepository;
6284 use Composer\IO\IOInterface;
6285 use Composer\Util\Silencer;
6286
6287
6288
6289
6290
6291 class RequireCommand extends InitCommand
6292 {
6293 private $newlyCreated;
6294 private $json;
6295 private $file;
6296 private $composerBackup;
6297
6298 protected function configure()
6299 {
6300 $this
6301 ->setName('require')
6302 ->setDescription('Adds required packages to your composer.json and installs them.')
6303 ->setDefinition(array(
6304 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"'),
6305 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
6306 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
6307 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
6308 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6309 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
6310 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6311 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6312 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6313 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
6314 new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
6315 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6316 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
6317 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
6318 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
6319 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6320 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6321 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6322 ))
6323 ->setHelp(
6324 <<<EOT
6325 The require command adds required packages to your composer.json and installs them.
6326
6327 If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of
6328 matches to require.
6329
6330 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
6331
6332 If you do not want to install the new dependencies immediately you can call it with --no-update
6333
6334 Read more at https://getcomposer.org/doc/03-cli.md#require
6335 EOT
6336 )
6337 ;
6338 }
6339
6340 protected function execute(InputInterface $input, OutputInterface $output)
6341 {
6342 if (function_exists('pcntl_async_signals')) {
6343 pcntl_async_signals(true);
6344 pcntl_signal(SIGINT, array($this, 'revertComposerFile'));
6345 pcntl_signal(SIGTERM, array($this, 'revertComposerFile'));
6346 pcntl_signal(SIGHUP, array($this, 'revertComposerFile'));
6347 }
6348
6349 $this->file = Factory::getComposerFile();
6350 $io = $this->getIO();
6351
6352 $this->newlyCreated = !file_exists($this->file);
6353 if ($this->newlyCreated && !file_put_contents($this->file, "{\n}\n")) {
6354 $io->writeError('<error>'.$this->file.' could not be created.</error>');
6355
6356 return 1;
6357 }
6358
6359  
6360  if (!is_readable($this->file) && false === Silencer::call('file_get_contents', $this->file)) {
6361 $io->writeError('<error>'.$this->file.' is not readable.</error>');
6362
6363 return 1;
6364 }
6365
6366 if (filesize($this->file) === 0) {
6367 file_put_contents($this->file, "{\n}\n");
6368 }
6369
6370 $this->json = new JsonFile($this->file);
6371 $this->composerBackup = file_get_contents($this->json->getPath());
6372
6373
6374  
6375  if (!is_writable($this->file) && !Silencer::call('file_put_contents', $this->file, $this->composerBackup)) {
6376 $io->writeError('<error>'.$this->file.' is not writable.</error>');
6377
6378 return 1;
6379 }
6380
6381 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6382 $repos = $composer->getRepositoryManager()->getRepositories();
6383
6384 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6385
6386  $this->repos = new CompositeRepository(array_merge(
6387 array(new PlatformRepository(array(), $platformOverrides)),
6388 $repos
6389 ));
6390
6391 if ($composer->getPackage()->getPreferStable()) {
6392 $preferredStability = 'stable';
6393 } else {
6394 $preferredStability = $composer->getPackage()->getMinimumStability();
6395 }
6396
6397 $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
6398 try {
6399 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'));
6400 } catch (\Exception $e) {
6401 if ($this->newlyCreated) {
6402 throw new \RuntimeException('No composer.json present in the current directory, this may be the cause of the following exception.', 0, $e);
6403 }
6404
6405 throw $e;
6406 }
6407
6408 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
6409 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
6410 $requirements = $this->formatRequirements($requirements);
6411
6412
6413  $versionParser = new VersionParser();
6414 foreach ($requirements as $package => $constraint) {
6415 if (strtolower($package) === $composer->getPackage()->getName()) {
6416 $io->writeError(sprintf('<error>Root package \'%s\' cannot require itself in its composer.json</error>', $package));
6417
6418 return 1;
6419 }
6420 $versionParser->parseConstraints($constraint);
6421 }
6422
6423 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
6424
6425 if (!$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
6426 $composerDefinition = $this->json->read();
6427 foreach ($requirements as $package => $version) {
6428 $composerDefinition[$requireKey][$package] = $version;
6429 unset($composerDefinition[$removeKey][$package]);
6430 }
6431 $this->json->write($composerDefinition);
6432 }
6433
6434 $io->writeError('<info>'.$this->file.' has been '.($this->newlyCreated ? 'created' : 'updated').'</info>');
6435
6436 if ($input->getOption('no-update')) {
6437 return 0;
6438 }
6439
6440 try {
6441 return $this->doUpdate($input, $output, $io, $requirements);
6442 } catch (\Exception $e) {
6443 $this->revertComposerFile(false);
6444 throw $e;
6445 }
6446 }
6447
6448 private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
6449 {
6450
6451  $this->resetComposer();
6452 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6453 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6454
6455 $updateDevMode = !$input->getOption('update-no-dev');
6456 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6457 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6458 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6459
6460 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
6461 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6462
6463 $install = Installer::create($io, $composer);
6464
6465 $install
6466 ->setVerbose($input->getOption('verbose'))
6467 ->setPreferSource($input->getOption('prefer-source'))
6468 ->setPreferDist($input->getOption('prefer-dist'))
6469 ->setDevMode($updateDevMode)
6470 ->setRunScripts(!$input->getOption('no-scripts'))
6471 ->setSkipSuggest($input->getOption('no-suggest'))
6472 ->setOptimizeAutoloader($optimize)
6473 ->setClassMapAuthoritative($authoritative)
6474 ->setApcuAutoloader($apcu)
6475 ->setUpdate(true)
6476 ->setUpdateWhitelist(array_keys($requirements))
6477 ->setWhitelistTransitiveDependencies($input->getOption('update-with-dependencies'))
6478 ->setWhitelistAllDependencies($input->getOption('update-with-all-dependencies'))
6479 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6480 ->setPreferStable($input->getOption('prefer-stable'))
6481 ->setPreferLowest($input->getOption('prefer-lowest'))
6482 ;
6483
6484 $status = $install->run();
6485 if ($status !== 0) {
6486 $this->revertComposerFile(false);
6487 }
6488
6489 return $status;
6490 }
6491
6492 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
6493 {
6494 $contents = file_get_contents($json->getPath());
6495
6496 $manipulator = new JsonManipulator($contents);
6497
6498 foreach ($new as $package => $constraint) {
6499 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
6500 return false;
6501 }
6502 if (!$manipulator->removeSubNode($removeKey, $package)) {
6503 return false;
6504 }
6505 }
6506
6507 file_put_contents($json->getPath(), $manipulator->getContents());
6508
6509 return true;
6510 }
6511
6512 protected function interact(InputInterface $input, OutputInterface $output)
6513 {
6514 return;
6515 }
6516
6517 public function revertComposerFile($hardExit = true)
6518 {
6519 $io = $this->getIO();
6520
6521 if ($this->newlyCreated) {
6522 $io->writeError("\n".'<error>Installation failed, deleting '.$this->file.'.</error>');
6523 unlink($this->json->getPath());
6524 } else {
6525 $io->writeError("\n".'<error>Installation failed, reverting '.$this->file.' to its original content.</error>');
6526 file_put_contents($this->json->getPath(), $this->composerBackup);
6527 }
6528
6529 if ($hardExit) {
6530 exit(1);
6531 }
6532 }
6533 }
6534 <?php
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546 namespace Composer\Command;
6547
6548 use Composer\Script\Event as ScriptEvent;
6549 use Composer\Script\ScriptEvents;
6550 use Composer\Util\ProcessExecutor;
6551 use Symfony\Component\Console\Input\InputInterface;
6552 use Symfony\Component\Console\Input\InputOption;
6553 use Symfony\Component\Console\Input\InputArgument;
6554 use Symfony\Component\Console\Output\OutputInterface;
6555 use Symfony\Component\Console\Helper\Table;
6556
6557
6558
6559
6560 class RunScriptCommand extends BaseCommand
6561 {
6562
6563
6564
6565 protected $scriptEvents = array(
6566 ScriptEvents::PRE_INSTALL_CMD,
6567 ScriptEvents::POST_INSTALL_CMD,
6568 ScriptEvents::PRE_UPDATE_CMD,
6569 ScriptEvents::POST_UPDATE_CMD,
6570 ScriptEvents::PRE_STATUS_CMD,
6571 ScriptEvents::POST_STATUS_CMD,
6572 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
6573 ScriptEvents::POST_CREATE_PROJECT_CMD,
6574 ScriptEvents::PRE_ARCHIVE_CMD,
6575 ScriptEvents::POST_ARCHIVE_CMD,
6576 ScriptEvents::PRE_AUTOLOAD_DUMP,
6577 ScriptEvents::POST_AUTOLOAD_DUMP,
6578 );
6579
6580 protected function configure()
6581 {
6582 $this
6583 ->setName('run-script')
6584 ->setAliases(array('run'))
6585 ->setDescription('Runs the scripts defined in composer.json.')
6586 ->setDefinition(array(
6587 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
6588 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6589 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
6590 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6591 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6592 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
6593 ))
6594 ->setHelp(
6595 <<<EOT
6596 The <info>run-script</info> command runs scripts defined in composer.json:
6597
6598 <info>php composer.phar run-script post-update-cmd</info>
6599
6600 Read more at https://getcomposer.org/doc/03-cli.md#run-script
6601 EOT
6602 )
6603 ;
6604 }
6605
6606 protected function execute(InputInterface $input, OutputInterface $output)
6607 {
6608 if ($input->getOption('list')) {
6609 return $this->listScripts($output);
6610 } elseif (!$input->getArgument('script')) {
6611 throw new \RuntimeException('Missing required argument "script"');
6612 }
6613
6614 $script = $input->getArgument('script');
6615 if (!in_array($script, $this->scriptEvents)) {
6616 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
6617 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
6618 }
6619 }
6620
6621 $composer = $this->getComposer();
6622 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
6623 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
6624 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
6625 if (!$hasListeners) {
6626 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
6627 }
6628
6629 $args = $input->getArgument('args');
6630
6631 if (null !== $timeout = $input->getOption('timeout')) {
6632 if (!ctype_digit($timeout)) {
6633 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
6634 }
6635
6636  ProcessExecutor::setTimeout((int) $timeout);
6637 }
6638
6639 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
6640 }
6641
6642 protected function listScripts(OutputInterface $output)
6643 {
6644 $scripts = $this->getComposer()->getPackage()->getScripts();
6645
6646 if (!count($scripts)) {
6647 return 0;
6648 }
6649
6650 $io = $this->getIO();
6651 $io->writeError('<info>scripts:</info>');
6652 $table = array();
6653 foreach ($scripts as $name => $script) {
6654 $description = '';
6655 try {
6656 $cmd = $this->getApplication()->find($name);
6657 if ($cmd instanceof ScriptAliasCommand) {
6658 $description = $cmd->getDescription();
6659 }
6660 } catch (\Symfony\Component\Console\Exception\CommandNotFoundException $e) {
6661
6662  }
6663 $table[] = array('  '.$name, $description);
6664 }
6665
6666 $renderer = new Table($output);
6667 $renderer->setStyle('compact');
6668 $rendererStyle = $renderer->getStyle();
6669 $rendererStyle->setVerticalBorderChar('');
6670 $rendererStyle->setCellRowContentFormat('%s  ');
6671 $renderer->setRows($table)->render();
6672
6673 return 0;
6674 }
6675 }
6676 <?php
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688 namespace Composer\Command;
6689
6690 use Symfony\Component\Console\Input\InputInterface;
6691 use Symfony\Component\Console\Input\InputOption;
6692 use Symfony\Component\Console\Input\InputArgument;
6693 use Symfony\Component\Console\Output\OutputInterface;
6694
6695
6696
6697
6698 class ScriptAliasCommand extends BaseCommand
6699 {
6700 private $script;
6701 private $description;
6702
6703 public function __construct($script, $description)
6704 {
6705 $this->script = $script;
6706 $this->description = empty($description) ? 'Runs the '.$script.' script as defined in composer.json.' : $description;
6707
6708 parent::__construct();
6709 }
6710
6711 protected function configure()
6712 {
6713 $this
6714 ->setName($this->script)
6715 ->setDescription($this->description)
6716 ->setDefinition(array(
6717 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6718 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6719 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6720 ))
6721 ->setHelp(
6722 <<<EOT
6723 The <info>run-script</info> command runs scripts defined in composer.json:
6724
6725 <info>php composer.phar run-script post-update-cmd</info>
6726
6727 Read more at https://getcomposer.org/doc/03-cli.md#run-script
6728 EOT
6729 )
6730 ;
6731 }
6732
6733 protected function execute(InputInterface $input, OutputInterface $output)
6734 {
6735 $composer = $this->getComposer();
6736
6737 $args = $input->getArguments();
6738
6739 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6740 }
6741 }
6742 <?php
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754 namespace Composer\Command;
6755
6756 use Composer\Factory;
6757 use Symfony\Component\Console\Input\InputInterface;
6758 use Symfony\Component\Console\Input\InputArgument;
6759 use Symfony\Component\Console\Input\InputOption;
6760 use Symfony\Component\Console\Output\OutputInterface;
6761 use Composer\Repository\CompositeRepository;
6762 use Composer\Repository\PlatformRepository;
6763 use Composer\Repository\RepositoryInterface;
6764 use Composer\Plugin\CommandEvent;
6765 use Composer\Plugin\PluginEvents;
6766
6767
6768
6769
6770 class SearchCommand extends BaseCommand
6771 {
6772 protected $matches;
6773 protected $lowMatches = array();
6774 protected $tokens;
6775 protected $output;
6776 protected $onlyName;
6777
6778 protected function configure()
6779 {
6780 $this
6781 ->setName('search')
6782 ->setDescription('Searches for packages.')
6783 ->setDefinition(array(
6784 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6785 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6786 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6787 ))
6788 ->setHelp(
6789 <<<EOT
6790 The search command searches for packages by its name
6791 <info>php composer.phar search symfony composer</info>
6792
6793 Read more at https://getcomposer.org/doc/03-cli.md#search
6794 EOT
6795 )
6796 ;
6797 }
6798
6799 protected function execute(InputInterface $input, OutputInterface $output)
6800 {
6801
6802  $platformRepo = new PlatformRepository;
6803 $io = $this->getIO();
6804 if (!($composer = $this->getComposer(false))) {
6805 $composer = Factory::create($this->getIO(), array(), $input->hasParameterOption('--no-plugins'));
6806 }
6807 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6808 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6809 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6810
6811 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6812 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6813
6814 $onlyName = $input->getOption('only-name');
6815 $type = $input->getOption('type') ?: null;
6816
6817 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6818 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6819
6820 foreach ($results as $result) {
6821 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6822 }
6823
6824 return 0;
6825 }
6826 }
6827 <?php
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839 namespace Composer\Command;
6840
6841 use Composer\Composer;
6842 use Composer\Factory;
6843 use Composer\Config;
6844 use Composer\Util\Filesystem;
6845 use Composer\SelfUpdate\Keys;
6846 use Composer\SelfUpdate\Versions;
6847 use Composer\IO\IOInterface;
6848 use Composer\Downloader\FilesystemException;
6849 use Symfony\Component\Console\Input\InputInterface;
6850 use Symfony\Component\Console\Input\InputOption;
6851 use Symfony\Component\Console\Input\InputArgument;
6852 use Symfony\Component\Console\Output\OutputInterface;
6853 use Symfony\Component\Finder\Finder;
6854
6855
6856
6857
6858
6859
6860 class SelfUpdateCommand extends BaseCommand
6861 {
6862 const HOMEPAGE = 'getcomposer.org';
6863 const OLD_INSTALL_EXT = '-old.phar';
6864
6865 protected function configure()
6866 {
6867 $this
6868 ->setName('self-update')
6869 ->setAliases(array('selfupdate'))
6870 ->setDescription('Updates composer.phar to the latest version.')
6871 ->setDefinition(array(
6872 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6873 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'),
6874 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6875 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6876 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6877 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6878 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6879 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6880 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6881 ))
6882 ->setHelp(
6883 <<<EOT
6884 The <info>self-update</info> command checks getcomposer.org for newer
6885 versions of composer and if found, installs the latest.
6886
6887 <info>php composer.phar self-update</info>
6888
6889 Read more at https://getcomposer.org/doc/03-cli.md#self-update-selfupdate-
6890 EOT
6891 )
6892 ;
6893 }
6894
6895 protected function execute(InputInterface $input, OutputInterface $output)
6896 {
6897 $config = Factory::createConfig();
6898
6899 if ($config->get('disable-tls') === true) {
6900 $baseUrl = 'http://' . self::HOMEPAGE;
6901 } else {
6902 $baseUrl = 'https://' . self::HOMEPAGE;
6903 }
6904
6905 $io = $this->getIO();
6906 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6907
6908 $versionsUtil = new Versions($config, $remoteFilesystem);
6909
6910
6911  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6912 if ($input->getOption($channel)) {
6913 $versionsUtil->setChannel($channel);
6914 }
6915 }
6916
6917 if ($input->getOption('set-channel-only')) {
6918 return 0;
6919 }
6920
6921 $cacheDir = $config->get('cache-dir');
6922 $rollbackDir = $config->get('data-dir');
6923 $home = $config->get('home');
6924 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6925
6926 if ($input->getOption('update-keys')) {
6927 return $this->fetchKeys($io, $config);
6928 }
6929
6930
6931  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6932
6933
6934  if (!is_writable($tmpDir)) {
6935 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6936 }
6937
6938
6939  if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
6940 $composeUser = posix_getpwuid(posix_geteuid());
6941 $homeOwner = posix_getpwuid(fileowner($home));
6942 if (isset($composeUser['name']) && isset($homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
6943 $io->writeError('<warning>You are running composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'"</warning>');
6944 }
6945 }
6946
6947 if ($input->getOption('rollback')) {
6948 return $this->rollback($output, $rollbackDir, $localFilename);
6949 }
6950
6951 $latest = $versionsUtil->getLatest();
6952 $latestVersion = $latest['version'];
6953 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6954
6955 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6956 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6957
6958 return 1;
6959 }
6960
6961 if (Composer::VERSION === $updateVersion) {
6962 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6963
6964
6965  if ($input->getOption('clean-backups')) {
6966 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6967 }
6968
6969 return 0;
6970 }
6971
6972 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6973 $backupFile = sprintf(
6974 '%s/%s-%s%s',
6975 $rollbackDir,
6976 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6977 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6978 self::OLD_INSTALL_EXT
6979 );
6980
6981 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6982
6983 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6984 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6985 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6986 $io->writeError('   ', false);
6987 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6988 $io->writeError('');
6989
6990 if (!file_exists($tempFilename) || !$signature) {
6991 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6992
6993 return 1;
6994 }
6995
6996
6997  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6998 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6999 } else {
7000 if (!extension_loaded('openssl')) {
7001 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
7002 . '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.');
7003 }
7004
7005 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
7006 if (!file_exists($sigFile)) {
7007 file_put_contents(
7008 $home.'/keys.dev.pub',
7009 <<<DEVPUBKEY
7010 -----BEGIN PUBLIC KEY-----
7011 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
7012 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
7013 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
7014 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
7015 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
7016 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
7017 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
7018 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
7019 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
7020 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
7021 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
7022 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
7023 -----END PUBLIC KEY-----
7024 DEVPUBKEY
7025 );
7026
7027 file_put_contents(
7028 $home.'/keys.tags.pub',
7029 <<<TAGSPUBKEY
7030 -----BEGIN PUBLIC KEY-----
7031 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
7032 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
7033 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
7034 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
7035 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
7036 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
7037 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
7038 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
7039 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
7040 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
7041 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
7042 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
7043 -----END PUBLIC KEY-----
7044 TAGSPUBKEY
7045 );
7046 }
7047
7048 $pubkeyid = openssl_pkey_get_public($sigFile);
7049 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
7050 if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) {
7051 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
7052 }
7053 $signature = json_decode($signature, true);
7054 $signature = base64_decode($signature['sha384']);
7055 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
7056 openssl_free_key($pubkeyid);
7057 if (!$verified) {
7058 throw new \RuntimeException('The phar signature did not match the file you downloaded, this means your public keys are outdated or that the phar file is corrupt/has been modified');
7059 }
7060 }
7061
7062
7063  if ($input->getOption('clean-backups')) {
7064 $this->cleanBackups($rollbackDir);
7065 }
7066
7067 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
7068 @unlink($tempFilename);
7069 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
7070 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
7071
7072 return 1;
7073 }
7074
7075 if (file_exists($backupFile)) {
7076 $io->writeError(sprintf(
7077 'Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>',
7078 Composer::VERSION
7079 ));
7080 } else {
7081 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
7082 }
7083
7084 return 0;
7085 }
7086
7087 protected function fetchKeys(IOInterface $io, Config $config)
7088 {
7089 if (!$io->isInteractive()) {
7090 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
7091 }
7092
7093 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
7094
7095 $validator = function ($value) {
7096 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
7097 throw new \UnexpectedValueException('Invalid input');
7098 }
7099
7100 return trim($value)."\n";
7101 };
7102
7103 $devKey = '';
7104 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
7105 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
7106 while ($line = $io->ask('')) {
7107 $devKey .= trim($line)."\n";
7108 if (trim($line) === '-----END PUBLIC KEY-----') {
7109 break;
7110 }
7111 }
7112 }
7113 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
7114 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7115
7116 $tagsKey = '';
7117 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
7118 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
7119 while ($line = $io->ask('')) {
7120 $tagsKey .= trim($line)."\n";
7121 if (trim($line) === '-----END PUBLIC KEY-----') {
7122 break;
7123 }
7124 }
7125 }
7126 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
7127 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7128
7129 $io->write('Public keys stored in '.$config->get('home'));
7130 }
7131
7132 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
7133 {
7134 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
7135 if (!$rollbackVersion) {
7136 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
7137 }
7138
7139 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
7140
7141 if (!is_file($oldFile)) {
7142 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
7143 }
7144 if (!is_readable($oldFile)) {
7145 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
7146 }
7147
7148 $io = $this->getIO();
7149 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
7150 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
7151 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
7152
7153 return 1;
7154 }
7155
7156 return 0;
7157 }
7158
7159
7160
7161
7162
7163
7164
7165
7166 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
7167 {
7168 try {
7169 @chmod($newFilename, fileperms($localFilename));
7170 if (!ini_get('phar.readonly')) {
7171
7172  $phar = new \Phar($newFilename);
7173
7174  unset($phar);
7175 }
7176
7177
7178  if ($backupTarget && file_exists($localFilename)) {
7179 @copy($localFilename, $backupTarget);
7180 }
7181
7182 rename($newFilename, $localFilename);
7183
7184 return null;
7185 } catch (\Exception $e) {
7186 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
7187 throw $e;
7188 }
7189
7190 return $e;
7191 }
7192 }
7193
7194 protected function cleanBackups($rollbackDir, $except = null)
7195 {
7196 $finder = $this->getOldInstallationFinder($rollbackDir);
7197 $io = $this->getIO();
7198 $fs = new Filesystem;
7199
7200 foreach ($finder as $file) {
7201 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
7202 continue;
7203 }
7204 $file = (string) $file;
7205 $io->writeError('<info>Removing: '.$file.'</info>');
7206 $fs->remove($file);
7207 }
7208 }
7209
7210 protected function getLastBackupVersion($rollbackDir)
7211 {
7212 $finder = $this->getOldInstallationFinder($rollbackDir);
7213 $finder->sortByName();
7214 $files = iterator_to_array($finder);
7215
7216 if (count($files)) {
7217 return basename(end($files), self::OLD_INSTALL_EXT);
7218 }
7219
7220 return false;
7221 }
7222
7223 protected function getOldInstallationFinder($rollbackDir)
7224 {
7225 $finder = Finder::create()
7226 ->depth(0)
7227 ->files()
7228 ->name('*' . self::OLD_INSTALL_EXT)
7229 ->in($rollbackDir);
7230
7231 return $finder;
7232 }
7233 }
7234 <?php
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246 namespace Composer\Command;
7247
7248 use Composer\Composer;
7249 use Composer\DependencyResolver\DefaultPolicy;
7250 use Composer\DependencyResolver\Pool;
7251 use Composer\Json\JsonFile;
7252 use Composer\Package\BasePackage;
7253 use Composer\Package\CompletePackageInterface;
7254 use Composer\Package\PackageInterface;
7255 use Composer\Package\Version\VersionParser;
7256 use Composer\Package\Version\VersionSelector;
7257 use Composer\Plugin\CommandEvent;
7258 use Composer\Plugin\PluginEvents;
7259 use Composer\Repository\ArrayRepository;
7260 use Composer\Repository\ComposerRepository;
7261 use Composer\Repository\CompositeRepository;
7262 use Composer\Repository\PlatformRepository;
7263 use Composer\Repository\RepositoryFactory;
7264 use Composer\Repository\RepositoryInterface;
7265 use Composer\Semver\Constraint\ConstraintInterface;
7266 use Composer\Semver\Semver;
7267 use Composer\Spdx\SpdxLicenses;
7268 use Composer\Util\Platform;
7269 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
7270 use Symfony\Component\Console\Input\InputArgument;
7271 use Symfony\Component\Console\Input\InputInterface;
7272 use Symfony\Component\Console\Input\InputOption;
7273 use Symfony\Component\Console\Output\OutputInterface;
7274 use Symfony\Component\Console\Terminal;
7275
7276
7277
7278
7279
7280
7281
7282 class ShowCommand extends BaseCommand
7283 {
7284
7285 protected $versionParser;
7286 protected $colors;
7287
7288
7289 private $pool;
7290
7291 protected function configure()
7292 {
7293 $this
7294 ->setName('show')
7295 ->setAliases(array('info'))
7296 ->setDescription('Shows information about packages.')
7297 ->setDefinition(array(
7298 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
7299 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
7300 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
7301 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
7302 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
7303 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
7304 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
7305 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
7306 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
7307 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
7308 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
7309 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
7310 new InputOption('ignore', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Ignore specified package(s). Use it with the --outdated option if you don\'t want to be informed about new versions of some packages.'),
7311 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
7312 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
7313 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
7314 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
7315 ))
7316 ->setHelp(
7317 <<<EOT
7318 The show command displays detailed information about a package, or
7319 lists all packages available.
7320
7321 Read more at https://getcomposer.org/doc/03-cli.md#show
7322 EOT
7323 )
7324 ;
7325 }
7326
7327 protected function execute(InputInterface $input, OutputInterface $output)
7328 {
7329 $this->versionParser = new VersionParser;
7330 if ($input->getOption('tree')) {
7331 $this->initStyles($output);
7332 }
7333
7334 $composer = $this->getComposer(false);
7335 $io = $this->getIO();
7336
7337 if ($input->getOption('installed')) {
7338 $io->writeError('<warning>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.</warning>');
7339 }
7340
7341 if ($input->getOption('outdated')) {
7342 $input->setOption('latest', true);
7343 } elseif ($input->getOption('ignore')) {
7344 $io->writeError('<warning>You are using the option "ignore" for action other than "outdated", it will be ignored.</warning>');
7345 }
7346
7347 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
7348 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
7349
7350 return 1;
7351 }
7352
7353 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
7354 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
7355
7356 return 1;
7357 }
7358
7359 if ($input->getOption('tree') && $input->getOption('latest')) {
7360 $io->writeError('The --tree (-t) option is not usable in combination with --latest (-l)');
7361
7362 return 1;
7363 }
7364
7365 $format = $input->getOption('format');
7366 if (!in_array($format, array('text', 'json'))) {
7367 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
7368
7369 return 1;
7370 }
7371
7372
7373  $platformOverrides = array();
7374 if ($composer) {
7375 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
7376 }
7377 $platformRepo = new PlatformRepository(array(), $platformOverrides);
7378 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
7379
7380 if ($input->getOption('self')) {
7381 $package = $this->getComposer()->getPackage();
7382 $repos = $installedRepo = new ArrayRepository(array($package));
7383 } elseif ($input->getOption('platform')) {
7384 $repos = $installedRepo = $platformRepo;
7385 } elseif ($input->getOption('available')) {
7386 $installedRepo = $platformRepo;
7387 if ($composer) {
7388 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
7389 } else {
7390 $defaultRepos = RepositoryFactory::defaultRepos($io);
7391 $repos = new CompositeRepository($defaultRepos);
7392 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7393 }
7394 } elseif ($input->getOption('all') && $composer) {
7395 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
7396 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
7397 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
7398 } elseif ($input->getOption('all')) {
7399 $defaultRepos = RepositoryFactory::defaultRepos($io);
7400 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7401 $installedRepo = $platformRepo;
7402 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
7403 } else {
7404 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
7405 $rootPkg = $this->getComposer()->getPackage();
7406 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
7407 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
7408 }
7409 }
7410
7411 if ($composer) {
7412 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
7413 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7414 }
7415
7416 if ($input->getOption('latest') && null === $composer) {
7417 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
7418 $input->setOption('latest', false);
7419 }
7420
7421 $packageFilter = $input->getArgument('package');
7422
7423
7424  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
7425 if (empty($package)) {
7426 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
7427
7428 if (empty($package)) {
7429 $options = $input->getOptions();
7430 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
7431 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
7432 }
7433
7434 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
7435
7436 return 1;
7437 }
7438 } else {
7439 $versions = array($package->getPrettyVersion() => $package->getVersion());
7440 }
7441
7442 $exitCode = 0;
7443 if ($input->getOption('tree')) {
7444 $arrayTree = $this->generatePackageTree($package, $installedRepo, $repos);
7445
7446 if ('json' === $format) {
7447 $io->write(JsonFile::encode(array('installed' => array($arrayTree))));
7448 } else {
7449 $this->displayPackageTree(array($arrayTree));
7450 }
7451 } else {
7452 $latestPackage = null;
7453 if ($input->getOption('latest')) {
7454 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
7455 }
7456 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7457 $exitCode = 1;
7458 }
7459 if ($input->getOption('path')) {
7460 $io->write($package->getName(), false);
7461 $io->write(' ' . strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n"));
7462
7463 return $exitCode;
7464 }
7465 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
7466 $this->printLinks($package, 'requires');
7467 $this->printLinks($package, 'devRequires', 'requires (dev)');
7468 if ($package->getSuggests()) {
7469 $io->write("\n<info>suggests</info>");
7470 foreach ($package->getSuggests() as $suggested => $reason) {
7471 $io->write($suggested . ' <comment>' . $reason . '</comment>');
7472 }
7473 }
7474 $this->printLinks($package, 'provides');
7475 $this->printLinks($package, 'conflicts');
7476 $this->printLinks($package, 'replaces');
7477 }
7478
7479 return $exitCode;
7480 }
7481
7482
7483  if ($input->getOption('tree')) {
7484 $rootRequires = $this->getRootRequires();
7485 $packages = $installedRepo->getPackages();
7486 usort($packages, 'strcmp');
7487 $arrayTree = array();
7488 foreach ($packages as $package) {
7489 if (in_array($package->getName(), $rootRequires, true)) {
7490 $arrayTree[] = $this->generatePackageTree($package, $installedRepo, $repos);
7491 }
7492 }
7493
7494 if ('json' === $format) {
7495 $io->write(JsonFile::encode(array('installed' => $arrayTree)));
7496 } else {
7497 $this->displayPackageTree($arrayTree);
7498 }
7499
7500 return 0;
7501 }
7502
7503 if ($repos instanceof CompositeRepository) {
7504 $repos = $repos->getRepositories();
7505 } elseif (!is_array($repos)) {
7506 $repos = array($repos);
7507 }
7508
7509
7510  $packages = array();
7511 if (null !== $packageFilter) {
7512 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
7513 }
7514
7515 $packageListFilter = array();
7516 if ($input->getOption('direct')) {
7517 $packageListFilter = $this->getRootRequires();
7518 }
7519
7520 if (class_exists('Symfony\Component\Console\Terminal')) {
7521 $terminal = new Terminal();
7522 $width = $terminal->getWidth();
7523 } else {
7524
7525  list($width) = $this->getApplication()->getTerminalDimensions();
7526 }
7527 if (null === $width) {
7528
7529  
7530  $width = PHP_INT_MAX;
7531 }
7532 if (Platform::isWindows()) {
7533 $width--;
7534 } else {
7535 $width = max(80, $width);
7536 }
7537
7538 if ($input->getOption('path') && null === $composer) {
7539 $io->writeError('No composer.json found in the current directory, disabling "path" option');
7540 $input->setOption('path', false);
7541 }
7542
7543 foreach ($repos as $repo) {
7544 if ($repo === $platformRepo) {
7545 $type = 'platform';
7546 } elseif (
7547 $repo === $installedRepo
7548 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
7549 ) {
7550 $type = 'installed';
7551 } else {
7552 $type = 'available';
7553 }
7554 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
7555 foreach ($repo->getProviderNames() as $name) {
7556 if (!$packageFilter || preg_match($packageFilter, $name)) {
7557 $packages[$type][$name] = $name;
7558 }
7559 }
7560 } else {
7561 foreach ($repo->getPackages() as $package) {
7562 if (!isset($packages[$type][$package->getName()])
7563 || !is_object($packages[$type][$package->getName()])
7564 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
7565 ) {
7566 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
7567 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
7568 $packages[$type][$package->getName()] = $package;
7569 }
7570 }
7571 }
7572 }
7573 }
7574 }
7575
7576 $showAllTypes = $input->getOption('all');
7577 $showLatest = $input->getOption('latest');
7578 $showMinorOnly = $input->getOption('minor-only');
7579 $ignoredPackages = array_map('strtolower', $input->getOption('ignore'));
7580 $indent = $showAllTypes ? '  ' : '';
7581 $latestPackages = array();
7582 $exitCode = 0;
7583 $viewData = array();
7584 $viewMetaData = array();
7585 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
7586 if (isset($packages[$type])) {
7587 ksort($packages[$type]);
7588
7589 $nameLength = $versionLength = $latestLength = 0;
7590
7591 if ($showLatest && $showVersion) {
7592 foreach ($packages[$type] as $package) {
7593 if (is_object($package)) {
7594 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
7595 if ($latestPackage === false) {
7596 continue;
7597 }
7598
7599 $latestPackages[$package->getPrettyName()] = $latestPackage;
7600 }
7601 }
7602 }
7603
7604 $writePath = !$input->getOption('name-only') && $input->getOption('path');
7605 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
7606 $writeLatest = $writeVersion && $showLatest;
7607 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
7608
7609 $hasOutdatedPackages = false;
7610
7611 $viewData[$type] = array();
7612 foreach ($packages[$type] as $package) {
7613 $packageViewData = array();
7614 if (is_object($package)) {
7615 $latestPackage = null;
7616 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
7617 $latestPackage = $latestPackages[$package->getPrettyName()];
7618 }
7619
7620
7621  $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned();
7622 $packageIsIgnored = \in_array($package->getPrettyName(), $ignoredPackages, true);
7623 if ($input->getOption('outdated') && ($packageIsUpToDate || $packageIsIgnored)) {
7624 continue;
7625 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
7626 $hasOutdatedPackages = true;
7627 }
7628
7629 $packageViewData['name'] = $package->getPrettyName();
7630 $nameLength = max($nameLength, strlen($package->getPrettyName()));
7631 if ($writeVersion) {
7632 $packageViewData['version'] = $package->getFullPrettyVersion();
7633 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
7634 }
7635 if ($writeLatest && $latestPackage) {
7636 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
7637 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
7638 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
7639 }
7640 if ($writeDescription) {
7641 $packageViewData['description'] = $package->getDescription();
7642 }
7643 if ($writePath) {
7644 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
7645 }
7646
7647 if ($latestPackage && $latestPackage->isAbandoned()) {
7648 $replacement = is_string($latestPackage->getReplacementPackage())
7649 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
7650 : 'No replacement was suggested';
7651 $packageWarning = sprintf(
7652 'Package %s is abandoned, you should avoid using it. %s.',
7653 $package->getPrettyName(),
7654 $replacement
7655 );
7656 $packageViewData['warning'] = $packageWarning;
7657 }
7658 } else {
7659 $packageViewData['name'] = $package;
7660 $nameLength = max($nameLength, strlen($package));
7661 }
7662 $viewData[$type][] = $packageViewData;
7663 }
7664 $viewMetaData[$type] = array(
7665 'nameLength' => $nameLength,
7666 'versionLength' => $versionLength,
7667 'latestLength' => $latestLength,
7668 );
7669 if ($input->getOption('strict') && $hasOutdatedPackages) {
7670 $exitCode = 1;
7671 break;
7672 }
7673 }
7674 }
7675
7676 if ('json' === $format) {
7677 $io->write(JsonFile::encode($viewData));
7678 } else {
7679 foreach ($viewData as $type => $packages) {
7680 $nameLength = $viewMetaData[$type]['nameLength'];
7681 $versionLength = $viewMetaData[$type]['versionLength'];
7682 $latestLength = $viewMetaData[$type]['latestLength'];
7683
7684 $writeVersion = $nameLength + $versionLength + 3 <= $width;
7685 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
7686 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
7687
7688 if ($writeLatest && !$io->isDecorated()) {
7689 $latestLength += 2;
7690 }
7691
7692 if ($showAllTypes) {
7693 if ('available' === $type) {
7694 $io->write('<comment>' . $type . '</comment>:');
7695 } else {
7696 $io->write('<info>' . $type . '</info>:');
7697 }
7698 }
7699
7700 foreach ($packages as $package) {
7701 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
7702 if (isset($package['version']) && $writeVersion) {
7703 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
7704 }
7705 if (isset($package['latest']) && $writeLatest) {
7706 $latestVersion = $package['latest'];
7707 $updateStatus = $package['latest-status'];
7708 $style = $this->updateStatusToVersionStyle($updateStatus);
7709 if (!$io->isDecorated()) {
7710 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
7711 }
7712 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
7713 }
7714 if (isset($package['description']) && $writeDescription) {
7715 $description = strtok($package['description'], "\r\n");
7716 $remaining = $width - $nameLength - $versionLength - 4;
7717 if ($writeLatest) {
7718 $remaining -= $latestLength;
7719 }
7720 if (strlen($description) > $remaining) {
7721 $description = substr($description, 0, $remaining - 3) . '...';
7722 }
7723 $io->write(' ' . $description, false);
7724 }
7725 if (isset($package['path'])) {
7726 $io->write(' ' . $package['path'], false);
7727 }
7728 $io->write('');
7729 if (isset($package['warning'])) {
7730 $io->writeError('<warning>' . $package['warning'] . '</warning>');
7731 }
7732 }
7733
7734 if ($showAllTypes) {
7735 $io->write('');
7736 }
7737 }
7738 }
7739
7740 return $exitCode;
7741 }
7742
7743 protected function getRootRequires()
7744 {
7745 $rootPackage = $this->getComposer()->getPackage();
7746
7747 return array_map(
7748 'strtolower',
7749 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
7750 );
7751 }
7752
7753 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
7754 {
7755 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7756 }
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7769 {
7770 $name = strtolower($name);
7771 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7772
7773 $policy = new DefaultPolicy();
7774 $pool = new Pool('dev');
7775 $pool->addRepository($repos);
7776
7777 $matchedPackage = null;
7778 $versions = array();
7779 $matches = $pool->whatProvides($name, $constraint);
7780 foreach ($matches as $index => $package) {
7781
7782  if ($package->getName() !== $name) {
7783 unset($matches[$index]);
7784 continue;
7785 }
7786
7787
7788  if (null === $version && $installedRepo->hasPackage($package)) {
7789 $matchedPackage = $package;
7790 }
7791
7792 $versions[$package->getPrettyVersion()] = $package->getVersion();
7793 $matches[$index] = $package->getId();
7794 }
7795
7796
7797  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7798 $matchedPackage = $pool->literalToPackage($preferred[0]);
7799 }
7800
7801 return array($matchedPackage, $versions);
7802 }
7803
7804
7805
7806
7807
7808
7809
7810
7811 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7812 {
7813 $io = $this->getIO();
7814 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7815 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7816 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7817 $this->printVersions($package, $versions, $installedRepo);
7818 if ($latestPackage) {
7819 $style = $this->getVersionStyle($latestPackage, $package);
7820 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7821 } else {
7822 $latestPackage = $package;
7823 }
7824 $io->write('<info>type</info>     : ' . $package->getType());
7825 $this->printLicenses($package);
7826 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7827 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7828 if ($installedRepo->hasPackage($package)) {
7829 $io->write('<info>path</info>     : ' . sprintf('%s', realpath($this->getComposer()->getInstallationManager()->getInstallPath($package))));
7830 }
7831 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7832
7833 if ($latestPackage->isAbandoned()) {
7834 $replacement = ($latestPackage->getReplacementPackage() !== null)
7835 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7836 : null;
7837
7838 $io->writeError(
7839 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7840 );
7841 }
7842
7843 if ($package->getSupport()) {
7844 $io->write("\n<info>support</info>");
7845 foreach ($package->getSupport() as $type => $value) {
7846 $io->write('<comment>' . $type . '</comment> : '.$value);
7847 }
7848 }
7849
7850 if ($package->getAutoload()) {
7851 $io->write("\n<info>autoload</info>");
7852 foreach ($package->getAutoload() as $type => $autoloads) {
7853 $io->write('<comment>' . $type . '</comment>');
7854
7855 if ($type === 'psr-0') {
7856 foreach ($autoloads as $name => $path) {
7857 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7858 }
7859 } elseif ($type === 'psr-4') {
7860 foreach ($autoloads as $name => $path) {
7861 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7862 }
7863 } elseif ($type === 'classmap') {
7864 $io->write(implode(', ', $autoloads));
7865 }
7866 }
7867 if ($package->getIncludePaths()) {
7868 $io->write('<comment>include-path</comment>');
7869 $io->write(implode(', ', $package->getIncludePaths()));
7870 }
7871 }
7872 }
7873
7874
7875
7876
7877
7878
7879
7880
7881 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7882 {
7883 uasort($versions, 'version_compare');
7884 $versions = array_keys(array_reverse($versions));
7885
7886
7887  if ($installedRepo->hasPackage($package)) {
7888 $installedVersion = $package->getPrettyVersion();
7889 $key = array_search($installedVersion, $versions);
7890 if (false !== $key) {
7891 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7892 }
7893 }
7894
7895 $versions = implode(', ', $versions);
7896
7897 $this->getIO()->write('<info>versions</info> : ' . $versions);
7898 }
7899
7900
7901
7902
7903
7904
7905
7906
7907 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7908 {
7909 $title = $title ?: $linkType;
7910 $io = $this->getIO();
7911 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7912 $io->write("\n<info>" . $title . "</info>");
7913
7914 foreach ($links as $link) {
7915 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7916 }
7917 }
7918 }
7919
7920
7921
7922
7923
7924
7925 protected function printLicenses(CompletePackageInterface $package)
7926 {
7927 $spdxLicenses = new SpdxLicenses();
7928
7929 $licenses = $package->getLicense();
7930 $io = $this->getIO();
7931
7932 foreach ($licenses as $licenseId) {
7933 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7934
7935 if (!$license) {
7936 $out = $licenseId;
7937 } else {
7938
7939  if ($license[1] === true) {
7940 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7941 } else {
7942 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7943 }
7944 }
7945
7946 $io->write('<info>license</info>  : ' . $out);
7947 }
7948 }
7949
7950
7951
7952
7953
7954
7955 protected function initStyles(OutputInterface $output)
7956 {
7957 $this->colors = array(
7958 'green',
7959 'yellow',
7960 'cyan',
7961 'magenta',
7962 'blue',
7963 );
7964
7965 foreach ($this->colors as $color) {
7966 $style = new OutputFormatterStyle($color);
7967 $output->getFormatter()->setStyle($color, $style);
7968 }
7969 }
7970
7971
7972
7973
7974
7975
7976 protected function displayPackageTree(array $arrayTree)
7977 {
7978 $io = $this->getIO();
7979 foreach ($arrayTree as $package) {
7980 $io->write(sprintf('<info>%s</info>', $package['name']), false);
7981 $io->write(' ' . $package['version'], false);
7982 $io->write(' ' . strtok($package['description'], "\r\n"));
7983
7984 if (isset($package['requires'])) {
7985 $requires = $package['requires'];
7986 $treeBar = '├';
7987 $j = 0;
7988 $total = count($requires);
7989 foreach ($requires as $require) {
7990 $requireName = $require['name'];
7991 $j++;
7992 if ($j === $total) {
7993 $treeBar = '└';
7994 }
7995 $level = 1;
7996 $color = $this->colors[$level];
7997 $info = sprintf(
7998 '%s──<%s>%s</%s> %s',
7999 $treeBar,
8000 $color,
8001 $requireName,
8002 $color,
8003 $require['version']
8004 );
8005 $this->writeTreeLine($info);
8006
8007 $treeBar = str_replace('└', ' ', $treeBar);
8008 $packagesInTree = array($package['name'], $requireName);
8009
8010 $this->displayTree($require, $packagesInTree, $treeBar, $level + 1);
8011 }
8012 }
8013 }
8014 }
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024 protected function generatePackageTree(
8025 PackageInterface $package,
8026 RepositoryInterface $installedRepo,
8027 RepositoryInterface $distantRepos
8028 ) {
8029 $requires = $package->getRequires();
8030 ksort($requires);
8031 $children = array();
8032 foreach ($requires as $requireName => $require) {
8033 $packagesInTree = array($package->getName(), $requireName);
8034
8035 $treeChildDesc = array(
8036 'name' => $requireName,
8037 'version' => $require->getPrettyConstraint(),
8038 );
8039
8040 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree);
8041
8042 if ($deepChildren) {
8043 $treeChildDesc['requires'] = $deepChildren;
8044 }
8045
8046 $children[] = $treeChildDesc;
8047 }
8048 $tree = array(
8049 'name' => $package->getPrettyName(),
8050 'version' => $package->getPrettyVersion(),
8051 'description' => $package->getDescription(),
8052 );
8053
8054 if ($children) {
8055 $tree['requires'] = $children;
8056 }
8057
8058 return $tree;
8059 }
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069 protected function displayTree(
8070 $package,
8071 array $packagesInTree,
8072 $previousTreeBar = '├',
8073 $level = 1
8074 ) {
8075 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
8076 if (isset($package['requires'])) {
8077 $requires = $package['requires'];
8078 $treeBar = $previousTreeBar . '  ├';
8079 $i = 0;
8080 $total = count($requires);
8081 foreach ($requires as $require) {
8082 $currentTree = $packagesInTree;
8083 $i++;
8084 if ($i === $total) {
8085 $treeBar = $previousTreeBar . '  └';
8086 }
8087 $colorIdent = $level % count($this->colors);
8088 $color = $this->colors[$colorIdent];
8089
8090 $circularWarn = in_array(
8091 $require['name'],
8092 $currentTree,
8093 true
8094 ) ? '(circular dependency aborted here)' : '';
8095 $info = rtrim(sprintf(
8096 '%s──<%s>%s</%s> %s %s',
8097 $treeBar,
8098 $color,
8099 $require['name'],
8100 $color,
8101 $require['version'],
8102 $circularWarn
8103 ));
8104 $this->writeTreeLine($info);
8105
8106 $treeBar = str_replace('└', ' ', $treeBar);
8107
8108 $currentTree[] = $require['name'];
8109 $this->displayTree($require, $currentTree, $treeBar, $level + 1);
8110 }
8111 }
8112 }
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124 protected function addTree(
8125 $name,
8126 $package,
8127 RepositoryInterface $installedRepo,
8128 RepositoryInterface $distantRepos,
8129 array $packagesInTree
8130 ) {
8131 $children = array();
8132 list($package, $versions) = $this->getPackage(
8133 $installedRepo,
8134 $distantRepos,
8135 $name,
8136 $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint()
8137 );
8138 if (is_object($package)) {
8139 $requires = $package->getRequires();
8140 ksort($requires);
8141 foreach ($requires as $requireName => $require) {
8142 $currentTree = $packagesInTree;
8143
8144 $treeChildDesc = array(
8145 'name' => $requireName,
8146 'version' => $require->getPrettyConstraint(),
8147 );
8148
8149 if (!in_array($requireName, $currentTree, true)) {
8150 $currentTree[] = $requireName;
8151 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $currentTree);
8152 if ($deepChildren) {
8153 $treeChildDesc['requires'] = $deepChildren;
8154 }
8155 }
8156
8157 $children[] = $treeChildDesc;
8158 }
8159 }
8160
8161 return $children;
8162 }
8163
8164 private function updateStatusToVersionStyle($updateStatus)
8165 {
8166
8167  
8168  
8169  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
8170 }
8171
8172 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
8173 {
8174 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
8175 return 'up-to-date';
8176 }
8177
8178 $constraint = $package->getVersion();
8179 if (0 !== strpos($constraint, 'dev-')) {
8180 $constraint = '^'.$constraint;
8181 }
8182 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
8183
8184  return 'semver-safe-update';
8185 }
8186
8187
8188  return 'update-possible';
8189 }
8190
8191 private function writeTreeLine($line)
8192 {
8193 $io = $this->getIO();
8194 if (!$io->isDecorated()) {
8195 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
8196 }
8197
8198 $io->write($line);
8199 }
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
8212 {
8213
8214  $name = $package->getName();
8215 $versionSelector = new VersionSelector($this->getPool($composer));
8216 $stability = $composer->getPackage()->getMinimumStability();
8217 $flags = $composer->getPackage()->getStabilityFlags();
8218 if (isset($flags[$name])) {
8219 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
8220 }
8221
8222 $bestStability = $stability;
8223 if ($composer->getPackage()->getPreferStable()) {
8224 $bestStability = $package->getStability();
8225 }
8226
8227 $targetVersion = null;
8228 if (0 === strpos($package->getVersion(), 'dev-')) {
8229 $targetVersion = $package->getVersion();
8230 }
8231
8232 if ($targetVersion === null && $minorOnly) {
8233 $targetVersion = '^' . $package->getVersion();
8234 }
8235
8236 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
8237 }
8238
8239 private function getPool(Composer $composer)
8240 {
8241 if (!$this->pool) {
8242 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
8243 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
8244 }
8245
8246 return $this->pool;
8247 }
8248 }
8249 <?php
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261 namespace Composer\Command;
8262
8263 use Symfony\Component\Console\Input\InputInterface;
8264 use Symfony\Component\Console\Input\InputOption;
8265 use Symfony\Component\Console\Output\OutputInterface;
8266 use Composer\Downloader\ChangeReportInterface;
8267 use Composer\Downloader\DvcsDownloaderInterface;
8268 use Composer\Downloader\VcsCapableDownloaderInterface;
8269 use Composer\Package\Dumper\ArrayDumper;
8270 use Composer\Package\Version\VersionGuesser;
8271 use Composer\Package\Version\VersionParser;
8272 use Composer\Plugin\CommandEvent;
8273 use Composer\Plugin\PluginEvents;
8274 use Composer\Script\ScriptEvents;
8275 use Composer\Util\ProcessExecutor;
8276
8277
8278
8279
8280
8281 class StatusCommand extends BaseCommand
8282 {
8283 const EXIT_CODE_ERRORS = 1;
8284 const EXIT_CODE_UNPUSHED_CHANGES = 2;
8285 const EXIT_CODE_VERSION_CHANGES = 4;
8286
8287
8288
8289
8290 protected function configure()
8291 {
8292 $this
8293 ->setName('status')
8294 ->setDescription('Shows a list of locally modified packages, for packages installed from source.')
8295 ->setDefinition(array(
8296 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
8297 ))
8298 ->setHelp(
8299 <<<EOT
8300 The status command displays a list of dependencies that have
8301 been modified locally.
8302
8303 Read more at https://getcomposer.org/doc/03-cli.md#status
8304 EOT
8305 )
8306 ;
8307 }
8308
8309
8310
8311
8312
8313
8314 protected function execute(InputInterface $input, OutputInterface $output)
8315 {
8316
8317  $composer = $this->getComposer();
8318
8319 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
8320 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8321
8322 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
8323
8324 $dm = $composer->getDownloadManager();
8325 $im = $composer->getInstallationManager();
8326
8327
8328  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
8329
8330 $errors = array();
8331 $io = $this->getIO();
8332 $unpushedChanges = array();
8333 $vcsVersionChanges = array();
8334
8335 $parser = new VersionParser;
8336 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
8337 $dumper = new ArrayDumper;
8338
8339
8340  foreach ($installedRepo->getCanonicalPackages() as $package) {
8341 $downloader = $dm->getDownloaderForInstalledPackage($package);
8342 $targetDir = $im->getInstallPath($package);
8343
8344 if ($downloader instanceof ChangeReportInterface) {
8345 if (is_link($targetDir)) {
8346 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
8347 }
8348
8349 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
8350 $errors[$targetDir] = $changes;
8351 }
8352 }
8353
8354 if ($downloader instanceof VcsCapableDownloaderInterface) {
8355 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
8356 switch ($package->getInstallationSource()) {
8357 case 'source':
8358 $previousRef = $package->getSourceReference();
8359 break;
8360 case 'dist':
8361 $previousRef = $package->getDistReference();
8362 break;
8363 default:
8364 $previousRef = null;
8365 }
8366
8367 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
8368
8369 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
8370 $vcsVersionChanges[$targetDir] = array(
8371 'previous' => array(
8372 'version' => $package->getPrettyVersion(),
8373 'ref' => $previousRef,
8374 ),
8375 'current' => array(
8376 'version' => $currentVersion['pretty_version'],
8377 'ref' => $currentVersion['commit'],
8378 ),
8379 );
8380 }
8381 }
8382 }
8383
8384 if ($downloader instanceof DvcsDownloaderInterface) {
8385 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
8386 $unpushedChanges[$targetDir] = $unpushed;
8387 }
8388 }
8389 }
8390
8391
8392  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
8393 $io->writeError('<info>No local changes</info>');
8394
8395 return 0;
8396 }
8397
8398 if ($errors) {
8399 $io->writeError('<error>You have changes in the following dependencies:</error>');
8400
8401 foreach ($errors as $path => $changes) {
8402 if ($input->getOption('verbose')) {
8403 $indentedChanges = implode("\n", array_map(function ($line) {
8404 return '    ' . ltrim($line);
8405 }, explode("\n", $changes)));
8406 $io->write('<info>'.$path.'</info>:');
8407 $io->write($indentedChanges);
8408 } else {
8409 $io->write($path);
8410 }
8411 }
8412 }
8413
8414 if ($unpushedChanges) {
8415 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
8416
8417 foreach ($unpushedChanges as $path => $changes) {
8418 if ($input->getOption('verbose')) {
8419 $indentedChanges = implode("\n", array_map(function ($line) {
8420 return '    ' . ltrim($line);
8421 }, explode("\n", $changes)));
8422 $io->write('<info>'.$path.'</info>:');
8423 $io->write($indentedChanges);
8424 } else {
8425 $io->write($path);
8426 }
8427 }
8428 }
8429
8430 if ($vcsVersionChanges) {
8431 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
8432
8433 foreach ($vcsVersionChanges as $path => $changes) {
8434 if ($input->getOption('verbose')) {
8435
8436  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
8437 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
8438
8439 if ($io->isVeryVerbose()) {
8440
8441  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
8442 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
8443 }
8444
8445 $io->write('<info>'.$path.'</info>:');
8446 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
8447 } else {
8448 $io->write($path);
8449 }
8450 }
8451 }
8452
8453 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
8454 $io->writeError('Use --verbose (-v) to see a list of files');
8455 }
8456
8457
8458  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
8459
8460 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
8461 }
8462 }
8463 <?php
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475 namespace Composer\Command;
8476
8477 use Composer\Repository\PlatformRepository;
8478 use Symfony\Component\Console\Input\InputArgument;
8479 use Symfony\Component\Console\Input\InputInterface;
8480 use Symfony\Component\Console\Input\InputOption;
8481 use Symfony\Component\Console\Output\OutputInterface;
8482
8483 class SuggestsCommand extends BaseCommand
8484 {
8485 protected function configure()
8486 {
8487 $this
8488 ->setName('suggests')
8489 ->setDescription('Shows package suggestions.')
8490 ->setDefinition(array(
8491 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
8492 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
8493 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
8494 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
8495 ))
8496 ->setHelp(
8497 <<<EOT
8498
8499 The <info>%command.name%</info> command shows a sorted list of suggested packages.
8500
8501 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
8502
8503 Read more at https://getcomposer.org/doc/03-cli.md#suggests
8504 EOT
8505 )
8506 ;
8507 }
8508
8509 protected function execute(InputInterface $input, OutputInterface $output)
8510 {
8511 $lock = $this->getComposer()->getLocker()->getLockData();
8512
8513 if (empty($lock)) {
8514 throw new \RuntimeException('Lockfile seems to be empty?');
8515 }
8516
8517 $packages = $lock['packages'];
8518
8519 if (!$input->getOption('no-dev')) {
8520 $packages += $lock['packages-dev'];
8521 }
8522
8523 $filter = $input->getArgument('packages');
8524
8525
8526  $installed = array();
8527 foreach ($packages as $package) {
8528 $installed[] = $package['name'];
8529
8530 if (!empty($package['provide'])) {
8531 $installed = array_merge($installed, array_keys($package['provide']));
8532 }
8533
8534 if (!empty($package['replace'])) {
8535 $installed = array_merge($installed, array_keys($package['replace']));
8536 }
8537 }
8538
8539
8540  $installed = array_flip($installed);
8541 ksort($installed);
8542
8543
8544  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
8545
8546
8547  $suggesters = array();
8548 $suggested = array();
8549 foreach ($packages as $package) {
8550 $packageName = $package['name'];
8551 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
8552 continue;
8553 }
8554 foreach ($package['suggest'] as $suggestion => $reason) {
8555 if (false === strpos('/', $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
8556 continue;
8557 }
8558 if (!isset($installed[$suggestion])) {
8559 $suggesters[$packageName][$suggestion] = $reason;
8560 $suggested[$suggestion][$packageName] = $reason;
8561 }
8562 }
8563 }
8564 ksort($suggesters);
8565 ksort($suggested);
8566
8567
8568  $mode = 0;
8569 $io = $this->getIO();
8570 if ($input->getOption('by-package') || $io->isVerbose()) {
8571 $mode |= 1;
8572 }
8573 if ($input->getOption('by-suggestion')) {
8574 $mode |= 2;
8575 }
8576
8577
8578  if ($mode === 0) {
8579 foreach (array_keys($suggested) as $suggestion) {
8580 $io->write(sprintf('<info>%s</info>', $suggestion));
8581 }
8582
8583 return 0;
8584 }
8585
8586
8587  if ($mode & 1) {
8588 foreach ($suggesters as $suggester => $suggestions) {
8589 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
8590
8591 foreach ($suggestions as $suggestion => $reason) {
8592 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
8593 }
8594 $io->write('');
8595 }
8596 }
8597
8598
8599  if ($mode & 2) {
8600
8601  if ($mode & 1) {
8602 $io->write(str_repeat('-', 78));
8603 }
8604 foreach ($suggested as $suggestion => $suggesters) {
8605 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
8606
8607 foreach ($suggesters as $suggester => $reason) {
8608 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
8609 }
8610 $io->write('');
8611 }
8612 }
8613
8614 return 0;
8615 }
8616 }
8617 <?php
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629 namespace Composer\Command;
8630
8631 use Composer\Composer;
8632 use Composer\Installer;
8633 use Composer\IO\IOInterface;
8634 use Composer\Plugin\CommandEvent;
8635 use Composer\Plugin\PluginEvents;
8636 use Symfony\Component\Console\Helper\Table;
8637 use Symfony\Component\Console\Input\InputInterface;
8638 use Symfony\Component\Console\Input\InputOption;
8639 use Symfony\Component\Console\Input\InputArgument;
8640 use Symfony\Component\Console\Output\OutputInterface;
8641 use Symfony\Component\Console\Question\Question;
8642
8643
8644
8645
8646
8647 class UpdateCommand extends BaseCommand
8648 {
8649 protected function configure()
8650 {
8651 $this
8652 ->setName('update')
8653 ->setAliases(array('u', 'upgrade'))
8654 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
8655 ->setDefinition(array(
8656 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
8657 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
8658 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
8659 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
8660 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
8661 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
8662 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
8663 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
8664 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
8665 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
8666 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
8667 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
8668 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, except those defined in root package.'),
8669 new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist, including those defined in root package.'),
8670 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
8671 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
8672 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
8673 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
8674 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
8675 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
8676 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
8677 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
8678 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
8679 ))
8680 ->setHelp(
8681 <<<EOT
8682 The <info>update</info> command reads the composer.json file from the
8683 current directory, processes it, and updates, removes or installs all the
8684 dependencies.
8685
8686 <info>php composer.phar update</info>
8687
8688 To limit the update operation to a few packages, you can list the package(s)
8689 you want to update as such:
8690
8691 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
8692
8693 You may also use an asterisk (*) pattern to limit the update operation to package(s)
8694 from a specific vendor:
8695
8696 <info>php composer.phar update vendor/package1 foo/* [...]</info>
8697
8698 To select packages names interactively with auto-completion use <info>-i</info>.
8699
8700 Read more at https://getcomposer.org/doc/03-cli.md#update-u
8701 EOT
8702 )
8703 ;
8704 }
8705
8706 protected function execute(InputInterface $input, OutputInterface $output)
8707 {
8708 $io = $this->getIO();
8709 if ($input->getOption('no-custom-installers')) {
8710 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
8711 $input->setOption('no-plugins', true);
8712 }
8713
8714 if ($input->getOption('dev')) {
8715 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
8716 }
8717
8718 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
8719
8720 $packages = $input->getArgument('packages');
8721
8722 if ($input->getOption('interactive')) {
8723 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
8724 }
8725
8726 if ($input->getOption('root-reqs')) {
8727 $require = array_keys($composer->getPackage()->getRequires());
8728 if (!$input->getOption('no-dev')) {
8729 $requireDev = array_keys($composer->getPackage()->getDevRequires());
8730 $require = array_merge($require, $requireDev);
8731 }
8732
8733 if (!empty($packages)) {
8734 $packages = array_intersect($packages, $require);
8735 } else {
8736 $packages = $require;
8737 }
8738 }
8739
8740 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
8741
8742 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
8743 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8744
8745 $install = Installer::create($io, $composer);
8746
8747 $config = $composer->getConfig();
8748 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
8749
8750 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
8751 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
8752 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
8753
8754 $install
8755 ->setDryRun($input->getOption('dry-run'))
8756 ->setVerbose($input->getOption('verbose'))
8757 ->setPreferSource($preferSource)
8758 ->setPreferDist($preferDist)
8759 ->setDevMode(!$input->getOption('no-dev'))
8760 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
8761 ->setRunScripts(!$input->getOption('no-scripts'))
8762 ->setSkipSuggest($input->getOption('no-suggest'))
8763 ->setOptimizeAutoloader($optimize)
8764 ->setClassMapAuthoritative($authoritative)
8765 ->setApcuAutoloader($apcu)
8766 ->setUpdate(true)
8767 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
8768 ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies'))
8769 ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
8770 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
8771 ->setPreferStable($input->getOption('prefer-stable'))
8772 ->setPreferLowest($input->getOption('prefer-lowest'))
8773 ;
8774
8775 if ($input->getOption('no-plugins')) {
8776 $install->disablePlugins();
8777 }
8778
8779 return $install->run();
8780 }
8781
8782 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
8783 {
8784 if (!$input->isInteractive()) {
8785 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
8786 }
8787
8788 $requires = array_merge(
8789 $composer->getPackage()->getRequires(),
8790 $composer->getPackage()->getDevRequires()
8791 );
8792 $autocompleterValues = array();
8793 foreach ($requires as $require) {
8794 $target = $require->getTarget();
8795 $autocompleterValues[strtolower($target)] = $target;
8796 }
8797
8798 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
8799 foreach ($installedPackages as $package) {
8800 $autocompleterValues[$package->getName()] = $package->getPrettyName();
8801 }
8802
8803 $helper = $this->getHelper('question');
8804 $question = new Question('<comment>Enter package name: </comment>', null);
8805
8806 $io->writeError('<info>Press enter without value to end submission</info>');
8807
8808 do {
8809 $autocompleterValues = array_diff($autocompleterValues, $packages);
8810 $question->setAutocompleterValues($autocompleterValues);
8811 $addedPackage = $helper->ask($input, $output, $question);
8812
8813 if (!is_string($addedPackage) || empty($addedPackage)) {
8814 break;
8815 }
8816
8817 $addedPackage = strtolower($addedPackage);
8818 if (!in_array($addedPackage, $packages)) {
8819 $packages[] = $addedPackage;
8820 }
8821 } while (true);
8822
8823 $packages = array_filter($packages);
8824 if (!$packages) {
8825 throw new \InvalidArgumentException('You must enter minimum one package.');
8826 }
8827
8828 $table = new Table($output);
8829 $table->setHeaders(array('Selected packages'));
8830 foreach ($packages as $package) {
8831 $table->addRow(array($package));
8832 }
8833 $table->render();
8834
8835 if ($io->askConfirmation(sprintf(
8836 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
8837 1 === count($packages) ? '' : 's'
8838 ), true)) {
8839 return $packages;
8840 }
8841
8842 throw new \RuntimeException('Installation aborted.');
8843 }
8844 }
8845 <?php
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857 namespace Composer\Command;
8858
8859 use Composer\Factory;
8860 use Composer\Package\Loader\ValidatingArrayLoader;
8861 use Composer\Plugin\CommandEvent;
8862 use Composer\Plugin\PluginEvents;
8863 use Composer\Util\ConfigValidator;
8864 use Symfony\Component\Console\Input\InputArgument;
8865 use Symfony\Component\Console\Input\InputInterface;
8866 use Symfony\Component\Console\Input\InputOption;
8867 use Symfony\Component\Console\Output\OutputInterface;
8868
8869
8870
8871
8872
8873
8874
8875 class ValidateCommand extends BaseCommand
8876 {
8877
8878
8879
8880 protected function configure()
8881 {
8882 $this
8883 ->setName('validate')
8884 ->setDescription('Validates a composer.json and composer.lock.')
8885 ->setDefinition(array(
8886 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not validate requires for overly strict/loose constraints'),
8887 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
8888 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8889 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8890 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8891 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
8892 ))
8893 ->setHelp(
8894 <<<EOT
8895 The validate command validates a given composer.json and composer.lock
8896
8897 Exit codes in case of errors are:
8898 1 validation warning(s), only when --strict is given
8899 2 validation error(s)
8900 3 file unreadable or missing
8901
8902 Read more at https://getcomposer.org/doc/03-cli.md#validate
8903 EOT
8904 );
8905 }
8906
8907
8908
8909
8910
8911
8912
8913 protected function execute(InputInterface $input, OutputInterface $output)
8914 {
8915 $file = $input->getArgument('file') ?: Factory::getComposerFile();
8916 $io = $this->getIO();
8917
8918 if (!file_exists($file)) {
8919 $io->writeError('<error>' . $file . ' not found.</error>');
8920
8921 return 3;
8922 }
8923 if (!is_readable($file)) {
8924 $io->writeError('<error>' . $file . ' is not readable.</error>');
8925
8926 return 3;
8927 }
8928
8929 $validator = new ConfigValidator($io);
8930 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8931 $checkPublish = !$input->getOption('no-check-publish');
8932 $checkLock = !$input->getOption('no-check-lock');
8933 $isStrict = $input->getOption('strict');
8934 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8935
8936 $lockErrors = array();
8937 $composer = Factory::create($io, $file, $input->hasParameterOption('--no-plugins'));
8938 $locker = $composer->getLocker();
8939 if ($locker->isLocked() && !$locker->isFresh()) {
8940 $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 <package name>`.';
8941 }
8942
8943 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true, $isStrict);
8944
8945
8946  $exitCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
8947
8948 if ($input->getOption('with-dependencies')) {
8949 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8950 foreach ($localRepo->getPackages() as $package) {
8951 $path = $composer->getInstallationManager()->getInstallPath($package);
8952 $file = $path . '/composer.json';
8953 if (is_dir($path) && file_exists($file)) {
8954 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8955 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8956
8957 $depCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
8958 $exitCode = max($depCode, $exitCode);
8959 }
8960 }
8961 }
8962
8963 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8964 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8965 $exitCode = max($eventCode, $exitCode);
8966
8967 return $exitCode;
8968 }
8969
8970 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false, $isStrict = false)
8971 {
8972 if (!$errors && !$publishErrors && !$warnings) {
8973 $io->write('<info>' . $name . ' is valid</info>');
8974 } elseif (!$errors && !$publishErrors) {
8975 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8976 if ($printSchemaUrl) {
8977 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8978 }
8979 } elseif (!$errors) {
8980 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8981 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8982 if ($printSchemaUrl) {
8983 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8984 }
8985 } else {
8986 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8987 }
8988
8989
8990  
8991  if ($checkPublish) {
8992 $errors = array_merge($errors, $publishErrors);
8993 } elseif (!$isStrict) {
8994 $warnings = array_merge($warnings, $publishErrors);
8995 }
8996
8997
8998  
8999  if ($checkLock) {
9000 $errors = array_merge($errors, $lockErrors);
9001 } elseif (!$isStrict) {
9002 $warnings = array_merge($warnings, $lockErrors);
9003 }
9004
9005 $messages = array(
9006 'error' => $errors,
9007 'warning' => $warnings,
9008 );
9009
9010 foreach ($messages as $style => $msgs) {
9011 foreach ($msgs as $msg) {
9012 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
9013 }
9014 }
9015 }
9016 }
9017 <?php
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029 namespace Composer;
9030
9031 use Composer\Package\RootPackageInterface;
9032 use Composer\Package\Locker;
9033 use Composer\Repository\RepositoryManager;
9034 use Composer\Installer\InstallationManager;
9035 use Composer\Plugin\PluginManager;
9036 use Composer\Downloader\DownloadManager;
9037 use Composer\EventDispatcher\EventDispatcher;
9038 use Composer\Autoload\AutoloadGenerator;
9039 use Composer\Package\Archiver\ArchiveManager;
9040
9041
9042
9043
9044
9045
9046 class Composer
9047 {
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
9067
9068
9069 const VERSION = '1.9.2';
9070 const BRANCH_ALIAS_VERSION = '';
9071 const RELEASE_DATE = '2020-01-14 16:30:31';
9072 const SOURCE_VERSION = '';
9073
9074 public static function getVersion()
9075 {
9076
9077  if (self::VERSION === '@package_version'.'@') {
9078 return self::SOURCE_VERSION;
9079 }
9080
9081
9082  if (self::BRANCH_ALIAS_VERSION !== '' && preg_match('{^[a-f0-9]{40}$}', self::VERSION)) {
9083 return self::BRANCH_ALIAS_VERSION.'+'.self::VERSION;
9084 }
9085
9086 return self::VERSION;
9087 }
9088
9089
9090
9091
9092 private $package;
9093
9094
9095
9096
9097 private $locker;
9098
9099
9100
9101
9102 private $repositoryManager;
9103
9104
9105
9106
9107 private $downloadManager;
9108
9109
9110
9111
9112 private $installationManager;
9113
9114
9115
9116
9117 private $pluginManager;
9118
9119
9120
9121
9122 private $config;
9123
9124
9125
9126
9127 private $eventDispatcher;
9128
9129
9130
9131
9132 private $autoloadGenerator;
9133
9134
9135
9136
9137 private $archiveManager;
9138
9139
9140
9141
9142
9143 public function setPackage(RootPackageInterface $package)
9144 {
9145 $this->package = $package;
9146 }
9147
9148
9149
9150
9151 public function getPackage()
9152 {
9153 return $this->package;
9154 }
9155
9156
9157
9158
9159 public function setConfig(Config $config)
9160 {
9161 $this->config = $config;
9162 }
9163
9164
9165
9166
9167 public function getConfig()
9168 {
9169 return $this->config;
9170 }
9171
9172
9173
9174
9175 public function setLocker(Locker $locker)
9176 {
9177 $this->locker = $locker;
9178 }
9179
9180
9181
9182
9183 public function getLocker()
9184 {
9185 return $this->locker;
9186 }
9187
9188
9189
9190
9191 public function setRepositoryManager(RepositoryManager $manager)
9192 {
9193 $this->repositoryManager = $manager;
9194 }
9195
9196
9197
9198
9199 public function getRepositoryManager()
9200 {
9201 return $this->repositoryManager;
9202 }
9203
9204
9205
9206
9207 public function setDownloadManager(DownloadManager $manager)
9208 {
9209 $this->downloadManager = $manager;
9210 }
9211
9212
9213
9214
9215 public function getDownloadManager()
9216 {
9217 return $this->downloadManager;
9218 }
9219
9220
9221
9222
9223 public function setArchiveManager(ArchiveManager $manager)
9224 {
9225 $this->archiveManager = $manager;
9226 }
9227
9228
9229
9230
9231 public function getArchiveManager()
9232 {
9233 return $this->archiveManager;
9234 }
9235
9236
9237
9238
9239 public function setInstallationManager(InstallationManager $manager)
9240 {
9241 $this->installationManager = $manager;
9242 }
9243
9244
9245
9246
9247 public function getInstallationManager()
9248 {
9249 return $this->installationManager;
9250 }
9251
9252
9253
9254
9255 public function setPluginManager(PluginManager $manager)
9256 {
9257 $this->pluginManager = $manager;
9258 }
9259
9260
9261
9262
9263 public function getPluginManager()
9264 {
9265 return $this->pluginManager;
9266 }
9267
9268
9269
9270
9271 public function setEventDispatcher(EventDispatcher $eventDispatcher)
9272 {
9273 $this->eventDispatcher = $eventDispatcher;
9274 }
9275
9276
9277
9278
9279 public function getEventDispatcher()
9280 {
9281 return $this->eventDispatcher;
9282 }
9283
9284
9285
9286
9287 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
9288 {
9289 $this->autoloadGenerator = $autoloadGenerator;
9290 }
9291
9292
9293
9294
9295 public function getAutoloadGenerator()
9296 {
9297 return $this->autoloadGenerator;
9298 }
9299 }
9300 <?php
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312 namespace Composer;
9313
9314 use Composer\Config\ConfigSourceInterface;
9315 use Composer\Downloader\TransportException;
9316 use Composer\IO\IOInterface;
9317 use Composer\Util\Platform;
9318 use Composer\Util\ProcessExecutor;
9319
9320
9321
9322
9323 class Config
9324 {
9325 const RELATIVE_PATHS = 1;
9326
9327 public static $defaultConfig = array(
9328 'process-timeout' => 300,
9329 'use-include-path' => false,
9330 'preferred-install' => 'auto',
9331 'notify-on-install' => true,
9332 'github-protocols' => array('https', 'ssh', 'git'),
9333 'vendor-dir' => 'vendor',
9334 'bin-dir' => '{$vendor-dir}/bin',
9335 'cache-dir' => '{$home}/cache',
9336 'data-dir' => '{$home}',
9337 'cache-files-dir' => '{$cache-dir}/files',
9338 'cache-repo-dir' => '{$cache-dir}/repo',
9339 'cache-vcs-dir' => '{$cache-dir}/vcs',
9340 'cache-ttl' => 15552000, 
9341  'cache-files-ttl' => null, 
9342  'cache-files-maxsize' => '300MiB',
9343 'bin-compat' => 'auto',
9344 'discard-changes' => false,
9345 'autoloader-suffix' => null,
9346 'sort-packages' => false,
9347 'optimize-autoloader' => false,
9348 'classmap-authoritative' => false,
9349 'apcu-autoloader' => false,
9350 'prepend-autoloader' => true,
9351 'github-domains' => array('github.com'),
9352 'bitbucket-expose-hostname' => true,
9353 'disable-tls' => false,
9354 'secure-http' => true,
9355 'cafile' => null,
9356 'capath' => null,
9357 'github-expose-hostname' => true,
9358 'gitlab-domains' => array('gitlab.com'),
9359 'store-auths' => 'prompt',
9360 'platform' => array(),
9361 'archive-format' => 'tar',
9362 'archive-dir' => '.',
9363 'htaccess-protect' => true,
9364 'use-github-api' => true,
9365
9366  
9367  
9368  
9369  
9370  
9371  );
9372
9373 public static $defaultRepositories = array(
9374 'packagist.org' => array(
9375 'type' => 'composer',
9376 'url' => 'https?://repo.packagist.org',
9377 'allow_ssl_downgrade' => true,
9378 ),
9379 );
9380
9381 private $config;
9382 private $baseDir;
9383 private $repositories;
9384
9385 private $configSource;
9386
9387 private $authConfigSource;
9388 private $useEnvironment;
9389 private $warnedHosts = array();
9390
9391
9392
9393
9394
9395 public function __construct($useEnvironment = true, $baseDir = null)
9396 {
9397
9398  $this->config = static::$defaultConfig;
9399 $this->repositories = static::$defaultRepositories;
9400 $this->useEnvironment = (bool) $useEnvironment;
9401 $this->baseDir = $baseDir;
9402 }
9403
9404 public function setConfigSource(ConfigSourceInterface $source)
9405 {
9406 $this->configSource = $source;
9407 }
9408
9409 public function getConfigSource()
9410 {
9411 return $this->configSource;
9412 }
9413
9414 public function setAuthConfigSource(ConfigSourceInterface $source)
9415 {
9416 $this->authConfigSource = $source;
9417 }
9418
9419 public function getAuthConfigSource()
9420 {
9421 return $this->authConfigSource;
9422 }
9423
9424
9425
9426
9427
9428
9429 public function merge($config)
9430 {
9431
9432  if (!empty($config['config']) && is_array($config['config'])) {
9433 foreach ($config['config'] as $key => $val) {
9434 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
9435 $this->config[$key] = array_merge($this->config[$key], $val);
9436 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
9437 if (is_array($val) || is_array($this->config[$key])) {
9438 if (is_string($val)) {
9439 $val = array('*' => $val);
9440 }
9441 if (is_string($this->config[$key])) {
9442 $this->config[$key] = array('*' => $this->config[$key]);
9443 }
9444 $this->config[$key] = array_merge($this->config[$key], $val);
9445
9446  if (isset($this->config[$key]['*'])) {
9447 $wildcard = $this->config[$key]['*'];
9448 unset($this->config[$key]['*']);
9449 $this->config[$key]['*'] = $wildcard;
9450 }
9451 } else {
9452 $this->config[$key] = $val;
9453 }
9454 } else {
9455 $this->config[$key] = $val;
9456 }
9457 }
9458 }
9459
9460 if (!empty($config['repositories']) && is_array($config['repositories'])) {
9461 $this->repositories = array_reverse($this->repositories, true);
9462 $newRepos = array_reverse($config['repositories'], true);
9463 foreach ($newRepos as $name => $repository) {
9464
9465  if (false === $repository) {
9466 $this->disableRepoByName($name);
9467 continue;
9468 }
9469
9470
9471  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
9472 $this->disableRepoByName(key($repository));
9473 continue;
9474 }
9475
9476
9477  if (is_int($name)) {
9478 $this->repositories[] = $repository;
9479 } else {
9480 if ($name === 'packagist') { 
9481  $this->repositories[$name . '.org'] = $repository;
9482 } else {
9483 $this->repositories[$name] = $repository;
9484 }
9485 }
9486 }
9487 $this->repositories = array_reverse($this->repositories, true);
9488 }
9489 }
9490
9491
9492
9493
9494 public function getRepositories()
9495 {
9496 return $this->repositories;
9497 }
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507 public function get($key, $flags = 0)
9508 {
9509 switch ($key) {
9510 case 'vendor-dir':
9511 case 'bin-dir':
9512 case 'process-timeout':
9513 case 'data-dir':
9514 case 'cache-dir':
9515 case 'cache-files-dir':
9516 case 'cache-repo-dir':
9517 case 'cache-vcs-dir':
9518 case 'cafile':
9519 case 'capath':
9520
9521  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
9522
9523 $val = $this->getComposerEnv($env);
9524 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
9525 $val = Platform::expandPath($val);
9526
9527 if (substr($key, -4) !== '-dir') {
9528 return $val;
9529 }
9530
9531 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
9532
9533 case 'htaccess-protect':
9534 $value = $this->getComposerEnv('COMPOSER_HTACCESS_PROTECT');
9535 if (false === $value) {
9536 $value = $this->config[$key];
9537 }
9538 return $value !== 'false' && (bool) $value;
9539
9540 case 'cache-ttl':
9541 return (int) $this->config[$key];
9542
9543 case 'cache-files-maxsize':
9544 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
9545 throw new \RuntimeException(
9546 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
9547 );
9548 }
9549 $size = $matches[1];
9550 if (isset($matches[2])) {
9551 switch (strtolower($matches[2])) {
9552 case 'g':
9553 $size *= 1024;
9554
9555  
9556  case 'm':
9557 $size *= 1024;
9558
9559  
9560  case 'k':
9561 $size *= 1024;
9562 break;
9563 }
9564 }
9565
9566 return $size;
9567
9568 case 'cache-files-ttl':
9569 if (isset($this->config[$key])) {
9570 return (int) $this->config[$key];
9571 }
9572
9573 return (int) $this->config['cache-ttl'];
9574
9575 case 'home':
9576 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
9577
9578 return rtrim($this->process($val, $flags), '/\\');
9579
9580 case 'bin-compat':
9581 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
9582
9583 if (!in_array($value, array('auto', 'full'))) {
9584 throw new \RuntimeException(
9585 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
9586 );
9587 }
9588
9589 return $value;
9590
9591 case 'discard-changes':
9592 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
9593 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
9594 throw new \RuntimeException(
9595 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
9596 );
9597 }
9598 if ('stash' === $env) {
9599 return 'stash';
9600 }
9601
9602
9603  return $env !== 'false' && (bool) $env;
9604 }
9605
9606 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
9607 throw new \RuntimeException(
9608 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
9609 );
9610 }
9611
9612 return $this->config[$key];
9613
9614 case 'github-protocols':
9615 $protos = $this->config['github-protocols'];
9616 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
9617 unset($protos[$index]);
9618 }
9619 if (reset($protos) === 'http') {
9620 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
9621 }
9622
9623 return $protos;
9624
9625 case 'disable-tls':
9626 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9627 case 'secure-http':
9628 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9629 case 'use-github-api':
9630 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9631 default:
9632 if (!isset($this->config[$key])) {
9633 return null;
9634 }
9635
9636 return $this->process($this->config[$key], $flags);
9637 }
9638 }
9639
9640 public function all($flags = 0)
9641 {
9642 $all = array(
9643 'repositories' => $this->getRepositories(),
9644 );
9645 foreach (array_keys($this->config) as $key) {
9646 $all['config'][$key] = $this->get($key, $flags);
9647 }
9648
9649 return $all;
9650 }
9651
9652 public function raw()
9653 {
9654 return array(
9655 'repositories' => $this->getRepositories(),
9656 'config' => $this->config,
9657 );
9658 }
9659
9660
9661
9662
9663
9664
9665
9666 public function has($key)
9667 {
9668 return array_key_exists($key, $this->config);
9669 }
9670
9671
9672
9673
9674
9675
9676
9677
9678 private function process($value, $flags)
9679 {
9680 $config = $this;
9681
9682 if (!is_string($value)) {
9683 return $value;
9684 }
9685
9686 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
9687 return $config->get($match[1], $flags);
9688 }, $value);
9689 }
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699 private function realpath($path)
9700 {
9701 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
9702 return $path;
9703 }
9704
9705 return $this->baseDir . '/' . $path;
9706 }
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717 private function getComposerEnv($var)
9718 {
9719 if ($this->useEnvironment) {
9720 return getenv($var);
9721 }
9722
9723 return false;
9724 }
9725
9726 private function disableRepoByName($name)
9727 {
9728 if (isset($this->repositories[$name])) {
9729 unset($this->repositories[$name]);
9730 } elseif ($name === 'packagist') { 
9731  unset($this->repositories['packagist.org']);
9732 }
9733 }
9734
9735
9736
9737
9738
9739
9740
9741 public function prohibitUrlByConfig($url, IOInterface $io = null)
9742 {
9743
9744  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
9745 return;
9746 }
9747
9748
9749  $scheme = parse_url($url, PHP_URL_SCHEME);
9750 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
9751 if ($this->get('secure-http')) {
9752 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
9753 } elseif ($io) {
9754 $host = parse_url($url, PHP_URL_HOST);
9755 if (!isset($this->warnedHosts[$host])) {
9756 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
9757 }
9758 $this->warnedHosts[$host] = true;
9759 }
9760 }
9761 }
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
9773 public static function disableProcessTimeout()
9774 {
9775
9776  ProcessExecutor::setTimeout(0);
9777 }
9778 }
9779 <?php
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791 namespace Composer\Config;
9792
9793
9794
9795
9796
9797
9798
9799 interface ConfigSourceInterface
9800 {
9801
9802
9803
9804
9805
9806
9807 public function addRepository($name, $config);
9808
9809
9810
9811
9812
9813
9814 public function removeRepository($name);
9815
9816
9817
9818
9819
9820
9821
9822 public function addConfigSetting($name, $value);
9823
9824
9825
9826
9827
9828
9829 public function removeConfigSetting($name);
9830
9831
9832
9833
9834
9835
9836
9837 public function addProperty($name, $value);
9838
9839
9840
9841
9842
9843
9844 public function removeProperty($name);
9845
9846
9847
9848
9849
9850
9851
9852
9853 public function addLink($type, $name, $value);
9854
9855
9856
9857
9858
9859
9860
9861 public function removeLink($type, $name);
9862
9863
9864
9865
9866
9867
9868 public function getName();
9869 }
9870 <?php
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882 namespace Composer\Config;
9883
9884 use Composer\Json\JsonFile;
9885 use Composer\Json\JsonManipulator;
9886 use Composer\Util\Silencer;
9887
9888
9889
9890
9891
9892
9893
9894 class JsonConfigSource implements ConfigSourceInterface
9895 {
9896
9897
9898
9899 private $file;
9900
9901
9902
9903
9904 private $authConfig;
9905
9906
9907
9908
9909
9910
9911
9912 public function __construct(JsonFile $file, $authConfig = false)
9913 {
9914 $this->file = $file;
9915 $this->authConfig = $authConfig;
9916 }
9917
9918
9919
9920
9921 public function getName()
9922 {
9923 return $this->file->getPath();
9924 }
9925
9926
9927
9928
9929 public function addRepository($name, $config)
9930 {
9931 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
9932
9933  
9934  if (isset($config['repositories'])) {
9935 foreach ($config['repositories'] as $index => $val) {
9936 if ($index === $repo) {
9937 continue;
9938 }
9939 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
9940 unset($config['repositories'][$index]);
9941 $config['repositories']['packagist.org'] = false;
9942 break;
9943 }
9944 }
9945 }
9946
9947 $config['repositories'][$repo] = $repoConfig;
9948 });
9949 }
9950
9951
9952
9953
9954 public function removeRepository($name)
9955 {
9956 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9957 unset($config['repositories'][$repo]);
9958 });
9959 }
9960
9961
9962
9963
9964 public function addConfigSetting($name, $value)
9965 {
9966 $authConfig = $this->authConfig;
9967 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9968 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9969 list($key, $host) = explode('.', $key, 2);
9970 if ($authConfig) {
9971 $config[$key][$host] = $val;
9972 } else {
9973 $config['config'][$key][$host] = $val;
9974 }
9975 } else {
9976 $config['config'][$key] = $val;
9977 }
9978 });
9979 }
9980
9981
9982
9983
9984 public function removeConfigSetting($name)
9985 {
9986 $authConfig = $this->authConfig;
9987 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9988 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9989 list($key, $host) = explode('.', $key, 2);
9990 if ($authConfig) {
9991 unset($config[$key][$host]);
9992 } else {
9993 unset($config['config'][$key][$host]);
9994 }
9995 } else {
9996 unset($config['config'][$key]);
9997 }
9998 });
9999 }
10000
10001
10002
10003
10004 public function addProperty($name, $value)
10005 {
10006 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
10007 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10008 $bits = explode('.', $key);
10009 $last = array_pop($bits);
10010 $arr = &$config[reset($bits)];
10011 foreach ($bits as $bit) {
10012 if (!isset($arr[$bit])) {
10013 $arr[$bit] = array();
10014 }
10015 $arr = &$arr[$bit];
10016 }
10017 $arr[$last] = $val;
10018 } else {
10019 $config[$key] = $val;
10020 }
10021 });
10022 }
10023
10024
10025
10026
10027 public function removeProperty($name)
10028 {
10029 $authConfig = $this->authConfig;
10030 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
10031 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10032 $bits = explode('.', $key);
10033 $last = array_pop($bits);
10034 $arr = &$config[reset($bits)];
10035 foreach ($bits as $bit) {
10036 if (!isset($arr[$bit])) {
10037 return;
10038 }
10039 $arr = &$arr[$bit];
10040 }
10041 unset($arr[$last]);
10042 } else {
10043 unset($config[$key]);
10044 }
10045 });
10046 }
10047
10048
10049
10050
10051 public function addLink($type, $name, $value)
10052 {
10053 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
10054 $config[$type][$name] = $value;
10055 });
10056 }
10057
10058
10059
10060
10061 public function removeLink($type, $name)
10062 {
10063 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
10064 unset($config[$type][$name]);
10065
10066 if (0 === count($config[$type])) {
10067 unset($config[$type]);
10068 }
10069 });
10070 }
10071
10072 protected function manipulateJson($method, $args, $fallback)
10073 {
10074 $args = func_get_args();
10075
10076  array_shift($args);
10077 $fallback = array_pop($args);
10078
10079 if ($this->file->exists()) {
10080 if (!is_writable($this->file->getPath())) {
10081 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
10082 }
10083
10084 if (!is_readable($this->file->getPath())) {
10085 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
10086 }
10087
10088 $contents = file_get_contents($this->file->getPath());
10089 } elseif ($this->authConfig) {
10090 $contents = "{\n}\n";
10091 } else {
10092 $contents = "{\n    \"config\": {\n    }\n}\n";
10093 }
10094
10095 $manipulator = new JsonManipulator($contents);
10096
10097 $newFile = !$this->file->exists();
10098
10099
10100  if ($this->authConfig && $method === 'addConfigSetting') {
10101 $method = 'addSubNode';
10102 list($mainNode, $name) = explode('.', $args[0], 2);
10103 $args = array($mainNode, $name, $args[1]);
10104 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
10105 $method = 'removeSubNode';
10106 list($mainNode, $name) = explode('.', $args[0], 2);
10107 $args = array($mainNode, $name);
10108 }
10109
10110
10111  if (call_user_func_array(array($manipulator, $method), $args)) {
10112 file_put_contents($this->file->getPath(), $manipulator->getContents());
10113 } else {
10114
10115  $config = $this->file->read();
10116 $this->arrayUnshiftRef($args, $config);
10117 call_user_func_array($fallback, $args);
10118 $this->file->write($config);
10119 }
10120
10121 if ($newFile) {
10122 Silencer::call('chmod', $this->file->getPath(), 0600);
10123 }
10124 }
10125
10126
10127
10128
10129
10130
10131
10132
10133 private function arrayUnshiftRef(&$array, &$value)
10134 {
10135 $return = array_unshift($array, '');
10136 $array[0] = &$value;
10137
10138 return $return;
10139 }
10140 }
10141 <?php
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153 namespace Composer\Console;
10154
10155 use Composer\IO\NullIO;
10156 use Composer\Util\Platform;
10157 use Composer\Util\Silencer;
10158 use Symfony\Component\Console\Application as BaseApplication;
10159 use Symfony\Component\Console\Exception\CommandNotFoundException;
10160 use Symfony\Component\Console\Helper\HelperSet;
10161 use Symfony\Component\Console\Helper\QuestionHelper;
10162 use Symfony\Component\Console\Input\InputInterface;
10163 use Symfony\Component\Console\Input\InputOption;
10164 use Symfony\Component\Console\Output\OutputInterface;
10165 use Composer\Command;
10166 use Composer\Composer;
10167 use Composer\Factory;
10168 use Composer\IO\IOInterface;
10169 use Composer\IO\ConsoleIO;
10170 use Composer\Json\JsonValidationException;
10171 use Composer\Util\ErrorHandler;
10172 use Composer\EventDispatcher\ScriptExecutionException;
10173 use Composer\Exception\NoSslException;
10174
10175
10176
10177
10178
10179
10180
10181
10182 class Application extends BaseApplication
10183 {
10184
10185
10186
10187 protected $composer;
10188
10189
10190
10191
10192 protected $io;
10193
10194 private static $logo = '   ______
10195   / ____/___  ____ ___  ____  ____  ________  _____
10196  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
10197 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
10198 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
10199                     /_/
10200 ';
10201
10202 private $hasPluginCommands = false;
10203 private $disablePluginsByDefault = false;
10204
10205 public function __construct()
10206 {
10207 static $shutdownRegistered = false;
10208
10209 if (function_exists('ini_set') && extension_loaded('xdebug')) {
10210 ini_set('xdebug.show_exception_trace', false);
10211 ini_set('xdebug.scream', false);
10212 }
10213
10214 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
10215 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
10216 }
10217
10218 if (!$shutdownRegistered) {
10219 $shutdownRegistered = true;
10220
10221 register_shutdown_function(function () {
10222 $lastError = error_get_last();
10223
10224 if ($lastError && $lastError['message'] &&
10225 (strpos($lastError['message'], 'Allowed memory') !== false  ||
10226 strpos($lastError['message'], 'exceeded memory') !== false )) {
10227 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
10228 }
10229 });
10230 }
10231
10232 $this->io = new NullIO();
10233
10234 parent::__construct('Composer', Composer::getVersion());
10235 }
10236
10237
10238
10239
10240 public function run(InputInterface $input = null, OutputInterface $output = null)
10241 {
10242 if (null === $output) {
10243 $output = Factory::createOutput();
10244 }
10245
10246 return parent::run($input, $output);
10247 }
10248
10249
10250
10251
10252 public function doRun(InputInterface $input, OutputInterface $output)
10253 {
10254 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
10255
10256 if (getenv('COMPOSER_NO_INTERACTION')) {
10257 $input->setInteractive(false);
10258 }
10259
10260 $io = $this->io = new ConsoleIO($input, $output, new HelperSet(array(
10261 new QuestionHelper(),
10262 )));
10263 ErrorHandler::register($io);
10264
10265 if ($input->hasParameterOption('--no-cache')) {
10266 $io->writeError('Disabling cache usage', true, IOInterface::DEBUG);
10267 putenv('COMPOSER_CACHE_DIR='.(Platform::isWindows() ? 'nul' : '/dev/null'));
10268 }
10269
10270
10271  if ($newWorkDir = $this->getNewWorkingDir($input)) {
10272 $oldWorkingDir = getcwd();
10273 chdir($newWorkDir);
10274 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
10275 }
10276
10277
10278  $commandName = '';
10279 if ($name = $this->getCommandName($input)) {
10280 try {
10281 $commandName = $this->find($name)->getName();
10282 } catch (CommandNotFoundException $e) {
10283
10284  $commandName = false;
10285 } catch (\InvalidArgumentException $e) {
10286 }
10287 }
10288
10289
10290  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
10291 $dir = dirname(getcwd());
10292 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
10293
10294
10295  while (dirname($dir) !== $dir && $dir !== $home) {
10296 if (file_exists($dir.'/'.Factory::getComposerFile())) {
10297 if ($io->askConfirmation('<info>No composer.json in current directory, do you want to use the one at '.$dir.'?</info> [<comment>Y,n</comment>]? ', true)) {
10298 $oldWorkingDir = getcwd();
10299 chdir($dir);
10300 }
10301 break;
10302 }
10303 $dir = dirname($dir);
10304 }
10305 }
10306
10307 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
10308 try {
10309 foreach ($this->getPluginCommands() as $command) {
10310 if ($this->has($command->getName())) {
10311 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
10312 } else {
10313 $this->add($command);
10314 }
10315 }
10316 } catch (NoSslException $e) {
10317
10318  }
10319
10320 $this->hasPluginCommands = true;
10321 }
10322
10323
10324  $isProxyCommand = false;
10325 if ($name = $this->getCommandName($input)) {
10326 try {
10327 $command = $this->find($name);
10328 $commandName = $command->getName();
10329 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
10330 } catch (\InvalidArgumentException $e) {
10331 }
10332 }
10333
10334 if (!$isProxyCommand) {
10335 $io->writeError(sprintf(
10336 'Running %s (%s) with %s on %s',
10337 Composer::getVersion(),
10338 Composer::RELEASE_DATE,
10339 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
10340 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
10341 ), true, IOInterface::DEBUG);
10342
10343 if (PHP_VERSION_ID < 50302) {
10344 $io->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>');
10345 }
10346
10347 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
10348 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
10349 }
10350
10351 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
10352 $io->writeError(sprintf('<warning>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.</warning>', $_SERVER['PHP_SELF']));
10353 }
10354
10355 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER') && !file_exists('/.dockerenv')) {
10356 if (function_exists('posix_getuid') && posix_getuid() === 0) {
10357 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
10358 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
10359 }
10360 if ($uid = (int) getenv('SUDO_UID')) {
10361
10362  
10363  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
10364 }
10365 }
10366
10367  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
10368 }
10369
10370
10371  Silencer::call(function () use ($io) {
10372 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
10373 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
10374 $io->writeError(sprintf('<error>PHP temp directory (%s) does not exist or is not writable to Composer. Set sys_temp_dir in your php.ini</error>', sys_get_temp_dir()));
10375 }
10376 });
10377
10378
10379  $file = Factory::getComposerFile();
10380 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
10381 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
10382 foreach ($composer['scripts'] as $script => $dummy) {
10383 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
10384 if ($this->has($script)) {
10385 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
10386 } else {
10387 $description = null;
10388
10389 if (isset($composer['scripts-descriptions'][$script])) {
10390 $description = $composer['scripts-descriptions'][$script];
10391 }
10392
10393 $this->add(new Command\ScriptAliasCommand($script, $description));
10394 }
10395 }
10396 }
10397 }
10398 }
10399 }
10400
10401 try {
10402 if ($input->hasParameterOption('--profile')) {
10403 $startTime = microtime(true);
10404 $this->io->enableDebugging($startTime);
10405 }
10406
10407 $result = parent::doRun($input, $output);
10408
10409 if (isset($oldWorkingDir)) {
10410 chdir($oldWorkingDir);
10411 }
10412
10413 if (isset($startTime)) {
10414 $io->writeError('<info>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');
10415 }
10416
10417 restore_error_handler();
10418
10419 return $result;
10420 } catch (ScriptExecutionException $e) {
10421 return $e->getCode();
10422 } catch (\Exception $e) {
10423 $this->hintCommonErrors($e);
10424 restore_error_handler();
10425 throw $e;
10426 }
10427 }
10428
10429
10430
10431
10432
10433
10434 private function getNewWorkingDir(InputInterface $input)
10435 {
10436 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
10437 if (false !== $workingDir && !is_dir($workingDir)) {
10438 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
10439 }
10440
10441 return $workingDir;
10442 }
10443
10444
10445
10446
10447 private function hintCommonErrors($exception)
10448 {
10449 $io = $this->getIO();
10450
10451 Silencer::suppress();
10452 try {
10453 $composer = $this->getComposer(false, true);
10454 if ($composer) {
10455 $config = $composer->getConfig();
10456
10457 $minSpaceFree = 1024 * 1024;
10458 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
10459 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
10460 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
10461 ) {
10462 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
10463 }
10464 }
10465 } catch (\Exception $e) {
10466 }
10467 Silencer::restore();
10468
10469 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
10470 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
10471 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#-the-system-cannot-find-the-path-specified-windows- for details</error>', true, IOInterface::QUIET);
10472 }
10473
10474 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
10475 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
10476 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
10477 }
10478 }
10479
10480
10481
10482
10483
10484
10485
10486 public function getComposer($required = true, $disablePlugins = null)
10487 {
10488 if (null === $disablePlugins) {
10489 $disablePlugins = $this->disablePluginsByDefault;
10490 }
10491
10492 if (null === $this->composer) {
10493 try {
10494 $this->composer = Factory::create($this->io, null, $disablePlugins);
10495 } catch (\InvalidArgumentException $e) {
10496 if ($required) {
10497 $this->io->writeError($e->getMessage());
10498 exit(1);
10499 }
10500 } catch (JsonValidationException $e) {
10501 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
10502 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
10503 throw new JsonValidationException($message);
10504 }
10505 }
10506
10507 return $this->composer;
10508 }
10509
10510
10511
10512
10513 public function resetComposer()
10514 {
10515 $this->composer = null;
10516 if ($this->getIO() && method_exists($this->getIO(), 'resetAuthentications')) {
10517 $this->getIO()->resetAuthentications();
10518 }
10519 }
10520
10521
10522
10523
10524 public function getIO()
10525 {
10526 return $this->io;
10527 }
10528
10529 public function getHelp()
10530 {
10531 return self::$logo . parent::getHelp();
10532 }
10533
10534
10535
10536
10537 protected function getDefaultCommands()
10538 {
10539 $commands = array_merge(parent::getDefaultCommands(), array(
10540 new Command\AboutCommand(),
10541 new Command\ConfigCommand(),
10542 new Command\DependsCommand(),
10543 new Command\ProhibitsCommand(),
10544 new Command\InitCommand(),
10545 new Command\InstallCommand(),
10546 new Command\CreateProjectCommand(),
10547 new Command\UpdateCommand(),
10548 new Command\SearchCommand(),
10549 new Command\ValidateCommand(),
10550 new Command\ShowCommand(),
10551 new Command\SuggestsCommand(),
10552 new Command\RequireCommand(),
10553 new Command\DumpAutoloadCommand(),
10554 new Command\StatusCommand(),
10555 new Command\ArchiveCommand(),
10556 new Command\DiagnoseCommand(),
10557 new Command\RunScriptCommand(),
10558 new Command\LicensesCommand(),
10559 new Command\GlobalCommand(),
10560 new Command\ClearCacheCommand(),
10561 new Command\RemoveCommand(),
10562 new Command\HomeCommand(),
10563 new Command\ExecCommand(),
10564 new Command\OutdatedCommand(),
10565 new Command\CheckPlatformReqsCommand(),
10566 ));
10567
10568 if ('phar:' === substr(__FILE__, 0, 5)) {
10569 $commands[] = new Command\SelfUpdateCommand();
10570 }
10571
10572 return $commands;
10573 }
10574
10575
10576
10577
10578 public function getLongVersion()
10579 {
10580 if (Composer::BRANCH_ALIAS_VERSION && Composer::BRANCH_ALIAS_VERSION !== '@package_branch_alias_version'.'@') {
10581 return sprintf(
10582 '<info>%s</info> version <comment>%s (%s)</comment> %s',
10583 $this->getName(),
10584 Composer::BRANCH_ALIAS_VERSION,
10585 $this->getVersion(),
10586 Composer::RELEASE_DATE
10587 );
10588 }
10589
10590 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
10591 }
10592
10593
10594
10595
10596 protected function getDefaultInputDefinition()
10597 {
10598 $definition = parent::getDefaultInputDefinition();
10599 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
10600 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
10601 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
10602 $definition->addOption(new InputOption('--no-cache', null, InputOption::VALUE_NONE, 'Prevent use of the cache'));
10603
10604 return $definition;
10605 }
10606
10607 private function getPluginCommands()
10608 {
10609 $commands = array();
10610
10611 $composer = $this->getComposer(false, false);
10612 if (null === $composer) {
10613 $composer = Factory::createGlobal($this->io, false);
10614 }
10615
10616 if (null !== $composer) {
10617 $pm = $composer->getPluginManager();
10618 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
10619 $newCommands = $capability->getCommands();
10620 if (!is_array($newCommands)) {
10621 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
10622 }
10623 foreach ($newCommands as $command) {
10624 if (!$command instanceof Command\BaseCommand) {
10625 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
10626 }
10627 }
10628 $commands = array_merge($commands, $newCommands);
10629 }
10630 }
10631
10632 return $commands;
10633 }
10634 }
10635 <?php
10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647 namespace Composer\Console;
10648
10649 use Symfony\Component\Console\Formatter\OutputFormatter;
10650
10651
10652
10653
10654 class HtmlOutputFormatter extends OutputFormatter
10655 {
10656 private static $availableForegroundColors = array(
10657 30 => 'black',
10658 31 => 'red',
10659 32 => 'green',
10660 33 => 'yellow',
10661 34 => 'blue',
10662 35 => 'magenta',
10663 36 => 'cyan',
10664 37 => 'white',
10665 );
10666 private static $availableBackgroundColors = array(
10667 40 => 'black',
10668 41 => 'red',
10669 42 => 'green',
10670 43 => 'yellow',
10671 44 => 'blue',
10672 45 => 'magenta',
10673 46 => 'cyan',
10674 47 => 'white',
10675 );
10676 private static $availableOptions = array(
10677 1 => 'bold',
10678 4 => 'underscore',
10679
10680  
10681  
10682  );
10683
10684
10685
10686
10687 public function __construct(array $styles = array())
10688 {
10689 parent::__construct(true, $styles);
10690 }
10691
10692 public function format($message)
10693 {
10694 $formatted = parent::format($message);
10695
10696 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
10697
10698 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
10699 }
10700
10701 private function formatHtml($matches)
10702 {
10703 $out = '<span style="';
10704 foreach (explode(';', $matches[1]) as $code) {
10705 if (isset(self::$availableForegroundColors[$code])) {
10706 $out .= 'color:'.self::$availableForegroundColors[$code].';';
10707 } elseif (isset(self::$availableBackgroundColors[$code])) {
10708 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
10709 } elseif (isset(self::$availableOptions[$code])) {
10710 switch (self::$availableOptions[$code]) {
10711 case 'bold':
10712 $out .= 'font-weight:bold;';
10713 break;
10714
10715 case 'underscore':
10716 $out .= 'text-decoration:underline;';
10717 break;
10718 }
10719 }
10720 }
10721
10722 return $out.'">'.$matches[2].'</span>';
10723 }
10724 }
10725 <?php
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737 namespace Composer\DependencyResolver;
10738
10739
10740
10741
10742
10743
10744 class Decisions implements \Iterator, \Countable
10745 {
10746 const DECISION_LITERAL = 0;
10747 const DECISION_REASON = 1;
10748
10749 protected $pool;
10750 protected $decisionMap;
10751 protected $decisionQueue = array();
10752
10753 public function __construct($pool)
10754 {
10755 $this->pool = $pool;
10756 $this->decisionMap = array();
10757 }
10758
10759 public function decide($literal, $level, $why)
10760 {
10761 $this->addDecision($literal, $level);
10762 $this->decisionQueue[] = array(
10763 self::DECISION_LITERAL => $literal,
10764 self::DECISION_REASON => $why,
10765 );
10766 }
10767
10768 public function satisfy($literal)
10769 {
10770 $packageId = abs($literal);
10771
10772 return (
10773 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
10774 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
10775 );
10776 }
10777
10778 public function conflict($literal)
10779 {
10780 $packageId = abs($literal);
10781
10782 return (
10783 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
10784 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
10785 );
10786 }
10787
10788 public function decided($literalOrPackageId)
10789 {
10790 return !empty($this->decisionMap[abs($literalOrPackageId)]);
10791 }
10792
10793 public function undecided($literalOrPackageId)
10794 {
10795 return empty($this->decisionMap[abs($literalOrPackageId)]);
10796 }
10797
10798 public function decidedInstall($literalOrPackageId)
10799 {
10800 $packageId = abs($literalOrPackageId);
10801
10802 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
10803 }
10804
10805 public function decisionLevel($literalOrPackageId)
10806 {
10807 $packageId = abs($literalOrPackageId);
10808 if (isset($this->decisionMap[$packageId])) {
10809 return abs($this->decisionMap[$packageId]);
10810 }
10811
10812 return 0;
10813 }
10814
10815 public function decisionRule($literalOrPackageId)
10816 {
10817 $packageId = abs($literalOrPackageId);
10818
10819 foreach ($this->decisionQueue as $i => $decision) {
10820 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
10821 return $decision[self::DECISION_REASON];
10822 }
10823 }
10824
10825 return null;
10826 }
10827
10828 public function atOffset($queueOffset)
10829 {
10830 return $this->decisionQueue[$queueOffset];
10831 }
10832
10833 public function validOffset($queueOffset)
10834 {
10835 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
10836 }
10837
10838 public function lastReason()
10839 {
10840 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
10841 }
10842
10843 public function lastLiteral()
10844 {
10845 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
10846 }
10847
10848 public function reset()
10849 {
10850 while ($decision = array_pop($this->decisionQueue)) {
10851 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10852 }
10853 }
10854
10855 public function resetToOffset($offset)
10856 {
10857 while (count($this->decisionQueue) > $offset + 1) {
10858 $decision = array_pop($this->decisionQueue);
10859 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10860 }
10861 }
10862
10863 public function revertLast()
10864 {
10865 $this->decisionMap[abs($this->lastLiteral())] = 0;
10866 array_pop($this->decisionQueue);
10867 }
10868
10869 public function count()
10870 {
10871 return count($this->decisionQueue);
10872 }
10873
10874 public function rewind()
10875 {
10876 end($this->decisionQueue);
10877 }
10878
10879 public function current()
10880 {
10881 return current($this->decisionQueue);
10882 }
10883
10884 public function key()
10885 {
10886 return key($this->decisionQueue);
10887 }
10888
10889 public function next()
10890 {
10891 return prev($this->decisionQueue);
10892 }
10893
10894 public function valid()
10895 {
10896 return false !== current($this->decisionQueue);
10897 }
10898
10899 public function isEmpty()
10900 {
10901 return count($this->decisionQueue) === 0;
10902 }
10903
10904 protected function addDecision($literal, $level)
10905 {
10906 $packageId = abs($literal);
10907
10908 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
10909 if ($previousDecision != 0) {
10910 $literalString = $this->pool->literalToString($literal);
10911 $package = $this->pool->literalToPackage($literal);
10912 throw new SolverBugException(
10913 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
10914 );
10915 }
10916
10917 if ($literal > 0) {
10918 $this->decisionMap[$packageId] = $level;
10919 } else {
10920 $this->decisionMap[$packageId] = -$level;
10921 }
10922 }
10923
10924 public function __toString()
10925 {
10926 $decisionMap = $this->decisionMap;
10927 ksort($decisionMap);
10928 $str = '[';
10929 foreach ($decisionMap as $packageId => $level) {
10930 $str .= $packageId.':'.$level.',';
10931 }
10932 $str .= ']';
10933 return $str;
10934 }
10935 }
10936 <?php
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947
10948 namespace Composer\DependencyResolver;
10949
10950 use Composer\Package\PackageInterface;
10951 use Composer\Package\AliasPackage;
10952 use Composer\Package\BasePackage;
10953 use Composer\Semver\Constraint\Constraint;
10954
10955
10956
10957
10958
10959 class DefaultPolicy implements PolicyInterface
10960 {
10961 private $preferStable;
10962 private $preferLowest;
10963
10964 public function __construct($preferStable = false, $preferLowest = false)
10965 {
10966 $this->preferStable = $preferStable;
10967 $this->preferLowest = $preferLowest;
10968 }
10969
10970 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
10971 {
10972 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
10973 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
10974 }
10975
10976 $constraint = new Constraint($operator, $b->getVersion());
10977 $version = new Constraint('==', $a->getVersion());
10978
10979 return $constraint->matchSpecific($version, true);
10980 }
10981
10982 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
10983 {
10984 $packages = array();
10985
10986 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
10987 if ($candidate !== $package) {
10988 $packages[] = $candidate;
10989 }
10990 }
10991
10992 return $packages;
10993 }
10994
10995 public function getPriority(Pool $pool, PackageInterface $package)
10996 {
10997 return $pool->getPriority($package->getRepository());
10998 }
10999
11000 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
11001 {
11002 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
11003
11004 foreach ($packages as &$literals) {
11005 $policy = $this;
11006 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11007 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
11008 });
11009 }
11010
11011 foreach ($packages as &$literals) {
11012 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
11013
11014 $literals = $this->pruneToBestVersion($pool, $literals);
11015
11016 $literals = $this->pruneRemoteAliases($pool, $literals);
11017 }
11018
11019 $selected = call_user_func_array('array_merge', $packages);
11020
11021
11022  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11023 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
11024 });
11025
11026 return $selected;
11027 }
11028
11029 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
11030 {
11031 $packages = array();
11032 foreach ($literals as $literal) {
11033 $packageName = $pool->literalToPackage($literal)->getName();
11034
11035 if (!isset($packages[$packageName])) {
11036 $packages[$packageName] = array();
11037 }
11038
11039 if (isset($installedMap[abs($literal)])) {
11040 array_unshift($packages[$packageName], $literal);
11041 } else {
11042 $packages[$packageName][] = $literal;
11043 }
11044 }
11045
11046 return $packages;
11047 }
11048
11049
11050
11051
11052 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
11053 {
11054 if ($a->getRepository() === $b->getRepository()) {
11055
11056  if ($a->getName() === $b->getName()) {
11057 $aAliased = $a instanceof AliasPackage;
11058 $bAliased = $b instanceof AliasPackage;
11059 if ($aAliased && !$bAliased) {
11060 return -1; 
11061  }
11062 if (!$aAliased && $bAliased) {
11063 return 1; 
11064  }
11065 }
11066
11067 if (!$ignoreReplace) {
11068
11069  if ($this->replaces($a, $b)) {
11070 return 1; 
11071  }
11072 if ($this->replaces($b, $a)) {
11073 return -1; 
11074  }
11075
11076
11077  
11078  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
11079 $requiredVendor = substr($requiredPackage, 0, $pos);
11080
11081 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
11082 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
11083
11084 if ($bIsSameVendor !== $aIsSameVendor) {
11085 return $aIsSameVendor ? -1 : 1;
11086 }
11087 }
11088 }
11089
11090
11091  if ($a->id === $b->id) {
11092 return 0;
11093 }
11094
11095 return ($a->id < $b->id) ? -1 : 1;
11096 }
11097
11098 if (isset($installedMap[$a->id])) {
11099 return -1;
11100 }
11101
11102 if (isset($installedMap[$b->id])) {
11103 return 1;
11104 }
11105
11106 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
11107 }
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119 protected function replaces(PackageInterface $source, PackageInterface $target)
11120 {
11121 foreach ($source->getReplaces() as $link) {
11122 if ($link->getTarget() === $target->getName()
11123
11124
11125  ) {
11126 return true;
11127 }
11128 }
11129
11130 return false;
11131 }
11132
11133 protected function pruneToBestVersion(Pool $pool, $literals)
11134 {
11135 $operator = $this->preferLowest ? '<' : '>';
11136 $bestLiterals = array($literals[0]);
11137 $bestPackage = $pool->literalToPackage($literals[0]);
11138 foreach ($literals as $i => $literal) {
11139 if (0 === $i) {
11140 continue;
11141 }
11142
11143 $package = $pool->literalToPackage($literal);
11144
11145 if ($this->versionCompare($package, $bestPackage, $operator)) {
11146 $bestPackage = $package;
11147 $bestLiterals = array($literal);
11148 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
11149 $bestLiterals[] = $literal;
11150 }
11151 }
11152
11153 return $bestLiterals;
11154 }
11155
11156
11157
11158
11159 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
11160 {
11161 $selected = array();
11162
11163 $priority = null;
11164
11165 foreach ($literals as $literal) {
11166 $package = $pool->literalToPackage($literal);
11167
11168 if (isset($installedMap[$package->id])) {
11169 $selected[] = $literal;
11170 continue;
11171 }
11172
11173 if (null === $priority) {
11174 $priority = $this->getPriority($pool, $package);
11175 }
11176
11177 if ($this->getPriority($pool, $package) != $priority) {
11178 break;
11179 }
11180
11181 $selected[] = $literal;
11182 }
11183
11184 return $selected;
11185 }
11186
11187
11188
11189
11190
11191
11192 protected function pruneRemoteAliases(Pool $pool, array $literals)
11193 {
11194 $hasLocalAlias = false;
11195
11196 foreach ($literals as $literal) {
11197 $package = $pool->literalToPackage($literal);
11198
11199 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
11200 $hasLocalAlias = true;
11201 break;
11202 }
11203 }
11204
11205 if (!$hasLocalAlias) {
11206 return $literals;
11207 }
11208
11209 $selected = array();
11210 foreach ($literals as $literal) {
11211 $package = $pool->literalToPackage($literal);
11212
11213 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
11214 $selected[] = $literal;
11215 }
11216 }
11217
11218 return $selected;
11219 }
11220 }
11221 <?php
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233 namespace Composer\DependencyResolver;
11234
11235 use Composer\Package\PackageInterface;
11236 use Composer\Package\Link;
11237
11238
11239
11240
11241 class GenericRule extends Rule
11242 {
11243 protected $literals;
11244
11245
11246
11247
11248
11249
11250
11251 public function __construct(array $literals, $reason, $reasonData, $job = null)
11252 {
11253 parent::__construct($reason, $reasonData, $job);
11254
11255
11256  sort($literals);
11257
11258 $this->literals = $literals;
11259 }
11260
11261 public function getLiterals()
11262 {
11263 return $this->literals;
11264 }
11265
11266 public function getHash()
11267 {
11268 $data = unpack('ihash', md5(implode(',', $this->literals), true));
11269
11270 return $data['hash'];
11271 }
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281 public function equals(Rule $rule)
11282 {
11283 return $this->literals === $rule->getLiterals();
11284 }
11285
11286 public function isAssertion()
11287 {
11288 return 1 === count($this->literals);
11289 }
11290
11291
11292
11293
11294
11295
11296 public function __toString()
11297 {
11298 $result = $this->isDisabled() ? 'disabled(' : '(';
11299
11300 foreach ($this->literals as $i => $literal) {
11301 if ($i != 0) {
11302 $result .= '|';
11303 }
11304 $result .= $literal;
11305 }
11306
11307 $result .= ')';
11308
11309 return $result;
11310 }
11311 }
11312 <?php
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324 namespace Composer\DependencyResolver\Operation;
11325
11326 use Composer\Package\PackageInterface;
11327
11328
11329
11330
11331
11332
11333 class InstallOperation extends SolverOperation
11334 {
11335 protected $package;
11336
11337
11338
11339
11340
11341
11342
11343 public function __construct(PackageInterface $package, $reason = null)
11344 {
11345 parent::__construct($reason);
11346
11347 $this->package = $package;
11348 }
11349
11350
11351
11352
11353
11354
11355 public function getPackage()
11356 {
11357 return $this->package;
11358 }
11359
11360
11361
11362
11363
11364
11365 public function getJobType()
11366 {
11367 return 'install';
11368 }
11369
11370
11371
11372
11373 public function __toString()
11374 {
11375 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
11376 }
11377 }
11378 <?php
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389
11390 namespace Composer\DependencyResolver\Operation;
11391
11392 use Composer\Package\AliasPackage;
11393 use Composer\Package\PackageInterface;
11394
11395
11396
11397
11398
11399
11400 class MarkAliasInstalledOperation extends SolverOperation
11401 {
11402 protected $package;
11403
11404
11405
11406
11407
11408
11409
11410 public function __construct(AliasPackage $package, $reason = null)
11411 {
11412 parent::__construct($reason);
11413
11414 $this->package = $package;
11415 }
11416
11417
11418
11419
11420
11421
11422 public function getPackage()
11423 {
11424 return $this->package;
11425 }
11426
11427
11428
11429
11430
11431
11432 public function getJobType()
11433 {
11434 return 'markAliasInstalled';
11435 }
11436
11437
11438
11439
11440 public function __toString()
11441 {
11442 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
11443 }
11444 }
11445 <?php
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457 namespace Composer\DependencyResolver\Operation;
11458
11459 use Composer\Package\AliasPackage;
11460 use Composer\Package\PackageInterface;
11461
11462
11463
11464
11465
11466
11467 class MarkAliasUninstalledOperation extends SolverOperation
11468 {
11469 protected $package;
11470
11471
11472
11473
11474
11475
11476
11477 public function __construct(AliasPackage $package, $reason = null)
11478 {
11479 parent::__construct($reason);
11480
11481 $this->package = $package;
11482 }
11483
11484
11485
11486
11487
11488
11489 public function getPackage()
11490 {
11491 return $this->package;
11492 }
11493
11494
11495
11496
11497
11498
11499 public function getJobType()
11500 {
11501 return 'markAliasUninstalled';
11502 }
11503
11504
11505
11506
11507 public function __toString()
11508 {
11509 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
11510 }
11511 }
11512 <?php
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524 namespace Composer\DependencyResolver\Operation;
11525
11526
11527
11528
11529
11530
11531 interface OperationInterface
11532 {
11533
11534
11535
11536
11537
11538 public function getJobType();
11539
11540
11541
11542
11543
11544
11545 public function getReason();
11546
11547
11548
11549
11550
11551
11552 public function __toString();
11553 }
11554 <?php
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566 namespace Composer\DependencyResolver\Operation;
11567
11568 use Composer\Package\PackageInterface;
11569
11570
11571
11572
11573
11574
11575 abstract class SolverOperation implements OperationInterface
11576 {
11577 protected $reason;
11578
11579
11580
11581
11582
11583
11584 public function __construct($reason = null)
11585 {
11586 $this->reason = $reason;
11587 }
11588
11589
11590
11591
11592
11593
11594 public function getReason()
11595 {
11596 return $this->reason;
11597 }
11598
11599 protected function formatVersion(PackageInterface $package)
11600 {
11601 return $package->getFullPrettyVersion();
11602 }
11603 }
11604 <?php
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616 namespace Composer\DependencyResolver\Operation;
11617
11618 use Composer\Package\PackageInterface;
11619
11620
11621
11622
11623
11624
11625 class UninstallOperation extends SolverOperation
11626 {
11627 protected $package;
11628
11629
11630
11631
11632
11633
11634
11635 public function __construct(PackageInterface $package, $reason = null)
11636 {
11637 parent::__construct($reason);
11638
11639 $this->package = $package;
11640 }
11641
11642
11643
11644
11645
11646
11647 public function getPackage()
11648 {
11649 return $this->package;
11650 }
11651
11652
11653
11654
11655
11656
11657 public function getJobType()
11658 {
11659 return 'uninstall';
11660 }
11661
11662
11663
11664
11665 public function __toString()
11666 {
11667 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
11668 }
11669 }
11670 <?php
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682 namespace Composer\DependencyResolver\Operation;
11683
11684 use Composer\Package\PackageInterface;
11685
11686
11687
11688
11689
11690
11691 class UpdateOperation extends SolverOperation
11692 {
11693 protected $initialPackage;
11694 protected $targetPackage;
11695
11696
11697
11698
11699
11700
11701
11702
11703 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
11704 {
11705 parent::__construct($reason);
11706
11707 $this->initialPackage = $initial;
11708 $this->targetPackage = $target;
11709 }
11710
11711
11712
11713
11714
11715
11716 public function getInitialPackage()
11717 {
11718 return $this->initialPackage;
11719 }
11720
11721
11722
11723
11724
11725
11726 public function getTargetPackage()
11727 {
11728 return $this->targetPackage;
11729 }
11730
11731
11732
11733
11734
11735
11736 public function getJobType()
11737 {
11738 return 'update';
11739 }
11740
11741
11742
11743
11744 public function __toString()
11745 {
11746 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
11747 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
11748 }
11749 }
11750 <?php
11751
11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762 namespace Composer\DependencyResolver;
11763
11764 use Composer\Package\PackageInterface;
11765
11766
11767
11768
11769 interface PolicyInterface
11770 {
11771 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
11772
11773 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
11774
11775 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
11776 }
11777 <?php
11778
11779
11780
11781
11782
11783
11784
11785
11786
11787
11788
11789 namespace Composer\DependencyResolver;
11790
11791 use Composer\Package\BasePackage;
11792 use Composer\Package\AliasPackage;
11793 use Composer\Package\Version\VersionParser;
11794 use Composer\Semver\Constraint\ConstraintInterface;
11795 use Composer\Semver\Constraint\Constraint;
11796 use Composer\Semver\Constraint\EmptyConstraint;
11797 use Composer\Repository\RepositoryInterface;
11798 use Composer\Repository\CompositeRepository;
11799 use Composer\Repository\ComposerRepository;
11800 use Composer\Repository\InstalledRepositoryInterface;
11801 use Composer\Repository\PlatformRepository;
11802 use Composer\Package\PackageInterface;
11803
11804
11805
11806
11807
11808
11809
11810 class Pool implements \Countable
11811 {
11812 const MATCH_NAME = -1;
11813 const MATCH_NONE = 0;
11814 const MATCH = 1;
11815 const MATCH_PROVIDE = 2;
11816 const MATCH_REPLACE = 3;
11817 const MATCH_FILTERED = 4;
11818
11819 protected $repositories = array();
11820 protected $providerRepos = array();
11821 protected $packages = array();
11822 protected $packageByName = array();
11823 protected $packageByExactName = array();
11824 protected $acceptableStabilities;
11825 protected $stabilityFlags;
11826 protected $versionParser;
11827 protected $providerCache = array();
11828 protected $filterRequires;
11829 protected $whitelist = null;
11830 protected $id = 1;
11831
11832 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
11833 {
11834 $this->versionParser = new VersionParser;
11835 $this->acceptableStabilities = array();
11836 foreach (BasePackage::$stabilities as $stability => $value) {
11837 if ($value <= BasePackage::$stabilities[$minimumStability]) {
11838 $this->acceptableStabilities[$stability] = $value;
11839 }
11840 }
11841 $this->stabilityFlags = $stabilityFlags;
11842 $this->filterRequires = $filterRequires;
11843 foreach ($filterRequires as $name => $constraint) {
11844 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
11845 unset($this->filterRequires[$name]);
11846 }
11847 }
11848 }
11849
11850 public function setWhitelist($whitelist)
11851 {
11852 $this->whitelist = $whitelist;
11853 $this->providerCache = array();
11854 }
11855
11856
11857
11858
11859
11860
11861
11862 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
11863 {
11864 if ($repo instanceof CompositeRepository) {
11865 $repos = $repo->getRepositories();
11866 } else {
11867 $repos = array($repo);
11868 }
11869
11870 foreach ($repos as $repo) {
11871 $this->repositories[] = $repo;
11872
11873 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
11874
11875 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
11876 $this->providerRepos[] = $repo;
11877 $repo->setRootAliases($rootAliases);
11878 $repo->resetPackageIds();
11879 } else {
11880 foreach ($repo->getPackages() as $package) {
11881 $names = $package->getNames();
11882 $stability = $package->getStability();
11883 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
11884 $package->setId($this->id++);
11885 $this->packages[] = $package;
11886 $this->packageByExactName[$package->getName()][$package->id] = $package;
11887
11888 foreach ($names as $provided) {
11889 $this->packageByName[$provided][] = $package;
11890 }
11891
11892
11893  $name = $package->getName();
11894 if (isset($rootAliases[$name][$package->getVersion()])) {
11895 $alias = $rootAliases[$name][$package->getVersion()];
11896 if ($package instanceof AliasPackage) {
11897 $package = $package->getAliasOf();
11898 }
11899 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
11900 $aliasPackage->setRootPackageAlias(true);
11901 $aliasPackage->setId($this->id++);
11902
11903 $package->getRepository()->addPackage($aliasPackage);
11904 $this->packages[] = $aliasPackage;
11905 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
11906
11907 foreach ($aliasPackage->getNames() as $name) {
11908 $this->packageByName[$name][] = $aliasPackage;
11909 }
11910 }
11911 }
11912 }
11913 }
11914 }
11915 }
11916
11917 public function getPriority(RepositoryInterface $repo)
11918 {
11919 $priority = array_search($repo, $this->repositories, true);
11920
11921 if (false === $priority) {
11922 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
11923 }
11924
11925 return -$priority;
11926 }
11927
11928
11929
11930
11931
11932
11933
11934 public function packageById($id)
11935 {
11936 return $this->packages[$id - 1];
11937 }
11938
11939
11940
11941
11942 public function count()
11943 {
11944 return count($this->packages);
11945 }
11946
11947
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
11959 {
11960 if ($bypassFilters) {
11961 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
11962 }
11963
11964 $key = ((int) $mustMatchName).$constraint;
11965 if (isset($this->providerCache[$name][$key])) {
11966 return $this->providerCache[$name][$key];
11967 }
11968
11969 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
11970 }
11971
11972
11973
11974
11975 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
11976 {
11977 $candidates = array();
11978
11979 foreach ($this->providerRepos as $repo) {
11980 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
11981 $candidates[] = $candidate;
11982 if ($candidate->id < 1) {
11983 $candidate->setId($this->id++);
11984 $this->packages[$this->id - 2] = $candidate;
11985 }
11986 }
11987 }
11988
11989 if ($mustMatchName) {
11990 $candidates = array_filter($candidates, function ($candidate) use ($name) {
11991 return $candidate->getName() == $name;
11992 });
11993 if (isset($this->packageByExactName[$name])) {
11994 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
11995 }
11996 } elseif (isset($this->packageByName[$name])) {
11997 $candidates = array_merge($candidates, $this->packageByName[$name]);
11998 }
11999
12000 $matches = $provideMatches = array();
12001 $nameMatch = false;
12002
12003 foreach ($candidates as $candidate) {
12004 $aliasOfCandidate = null;
12005
12006
12007  
12008  if ($candidate instanceof AliasPackage) {
12009 $aliasOfCandidate = $candidate->getAliasOf();
12010 }
12011
12012 if ($this->whitelist !== null && !$bypassFilters && (
12013 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
12014 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
12015 )) {
12016 continue;
12017 }
12018 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
12019 case self::MATCH_NONE:
12020 break;
12021
12022 case self::MATCH_NAME:
12023 $nameMatch = true;
12024 break;
12025
12026 case self::MATCH:
12027 $nameMatch = true;
12028 $matches[] = $candidate;
12029 break;
12030
12031 case self::MATCH_PROVIDE:
12032 $provideMatches[] = $candidate;
12033 break;
12034
12035 case self::MATCH_REPLACE:
12036 $matches[] = $candidate;
12037 break;
12038
12039 case self::MATCH_FILTERED:
12040 break;
12041
12042 default:
12043 throw new \UnexpectedValueException('Unexpected match type');
12044 }
12045 }
12046
12047
12048  if ($nameMatch) {
12049 return $matches;
12050 }
12051
12052 return array_merge($matches, $provideMatches);
12053 }
12054
12055 public function literalToPackage($literal)
12056 {
12057 $packageId = abs($literal);
12058
12059 return $this->packageById($packageId);
12060 }
12061
12062 public function literalToPrettyString($literal, $installedMap)
12063 {
12064 $package = $this->literalToPackage($literal);
12065
12066 if (isset($installedMap[$package->id])) {
12067 $prefix = ($literal > 0 ? 'keep' : 'remove');
12068 } else {
12069 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
12070 }
12071
12072 return $prefix.' '.$package->getPrettyString();
12073 }
12074
12075 public function isPackageAcceptable($name, $stability)
12076 {
12077 foreach ((array) $name as $n) {
12078
12079  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
12080 return true;
12081 }
12082
12083
12084  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
12085 return true;
12086 }
12087 }
12088
12089 return false;
12090 }
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101 public function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
12102 {
12103 $candidateName = $candidate->getName();
12104 $candidateVersion = $candidate->getVersion();
12105 $isDev = $candidate->getStability() === 'dev';
12106 $isAlias = $candidate instanceof AliasPackage;
12107
12108 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
12109 $requireFilter = $this->filterRequires[$name];
12110 } else {
12111 $requireFilter = new EmptyConstraint;
12112 }
12113
12114 if ($candidateName === $name) {
12115 $pkgConstraint = new Constraint('==', $candidateVersion);
12116
12117 if ($constraint === null || $constraint->matches($pkgConstraint)) {
12118 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
12119 }
12120
12121 return self::MATCH_NAME;
12122 }
12123
12124 $provides = $candidate->getProvides();
12125 $replaces = $candidate->getReplaces();
12126
12127
12128  if (isset($replaces[0]) || isset($provides[0])) {
12129 foreach ($provides as $link) {
12130 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
12131 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
12132 }
12133 }
12134
12135 foreach ($replaces as $link) {
12136 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
12137 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
12138 }
12139 }
12140
12141 return self::MATCH_NONE;
12142 }
12143
12144 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
12145 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
12146 }
12147
12148 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
12149 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
12150 }
12151
12152 return self::MATCH_NONE;
12153 }
12154 }
12155 <?php
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167 namespace Composer\DependencyResolver;
12168
12169 use Composer\Package\CompletePackageInterface;
12170
12171
12172
12173
12174
12175
12176 class Problem
12177 {
12178
12179
12180
12181
12182 protected $reasonSeen;
12183
12184
12185
12186
12187
12188 protected $reasons = array();
12189
12190 protected $section = 0;
12191
12192 protected $pool;
12193
12194 public function __construct(Pool $pool)
12195 {
12196 $this->pool = $pool;
12197 }
12198
12199
12200
12201
12202
12203
12204 public function addRule(Rule $rule)
12205 {
12206 $this->addReason(spl_object_hash($rule), array(
12207 'rule' => $rule,
12208 'job' => $rule->getJob(),
12209 ));
12210 }
12211
12212
12213
12214
12215
12216
12217 public function getReasons()
12218 {
12219 return $this->reasons;
12220 }
12221
12222
12223
12224
12225
12226
12227
12228 public function getPrettyString(array $installedMap = array())
12229 {
12230 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
12231
12232 if (count($reasons) === 1) {
12233 reset($reasons);
12234 $reason = current($reasons);
12235
12236 $job = $reason['job'];
12237
12238 $packageName = $job['packageName'];
12239 $constraint = $job['constraint'];
12240
12241 if (isset($constraint)) {
12242 $packages = $this->pool->whatProvides($packageName, $constraint);
12243 } else {
12244 $packages = array();
12245 }
12246
12247 if ($job && $job['cmd'] === 'install' && empty($packages)) {
12248
12249
12250  if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
12251 $version = phpversion();
12252 $available = $this->pool->whatProvides($packageName);
12253
12254 if (count($available)) {
12255 $firstAvailable = reset($available);
12256 $version = $firstAvailable->getPrettyVersion();
12257 $extra = $firstAvailable->getExtra();
12258 if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
12259 $version .= '; ' . $firstAvailable->getDescription();
12260 }
12261 }
12262
12263 $msg = "\n    - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
12264
12265 if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
12266 return $msg . 'your HHVM version does not satisfy that requirement.';
12267 }
12268
12269 if ($packageName === 'hhvm') {
12270 return $msg . 'you are running this with PHP and not HHVM.';
12271 }
12272
12273 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
12274 }
12275
12276
12277  if (0 === stripos($packageName, 'ext-')) {
12278 if (false !== strpos($packageName, ' ')) {
12279 return "\n    - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
12280 }
12281
12282 $ext = substr($packageName, 4);
12283 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
12284
12285 return "\n    - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
12286 }
12287
12288
12289  if (0 === stripos($packageName, 'lib-')) {
12290 if (strtolower($packageName) === 'lib-icu') {
12291 $error = extension_loaded('intl') ? 'has the wrong version installed, try upgrading the intl extension.' : 'is missing from your system, make sure the intl extension is loaded.';
12292
12293 return "\n    - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
12294 }
12295
12296 return "\n    - The requested linked library ".$packageName.$this->constraintToText($constraint).' has the wrong version installed or is missing from your system, make sure to load the extension providing it.';
12297 }
12298
12299 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
12300 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
12301
12302 return "\n    - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
12303 }
12304
12305 if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
12306 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
12307 }
12308
12309 if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
12310 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
12311 }
12312
12313 return "\n    - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
12314 }
12315 }
12316
12317 $messages = array();
12318
12319 foreach ($reasons as $reason) {
12320 $rule = $reason['rule'];
12321 $job = $reason['job'];
12322
12323 if ($job) {
12324 $messages[] = $this->jobToText($job);
12325 } elseif ($rule) {
12326 if ($rule instanceof Rule) {
12327 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
12328 }
12329 }
12330 }
12331
12332 return "\n    - ".implode("\n    - ", $messages);
12333 }
12334
12335
12336
12337
12338
12339
12340
12341 protected function addReason($id, $reason)
12342 {
12343 if (!isset($this->reasonSeen[$id])) {
12344 $this->reasonSeen[$id] = true;
12345 $this->reasons[$this->section][] = $reason;
12346 }
12347 }
12348
12349 public function nextSection()
12350 {
12351 $this->section++;
12352 }
12353
12354
12355
12356
12357
12358
12359
12360 protected function jobToText($job)
12361 {
12362 $packageName = $job['packageName'];
12363 $constraint = $job['constraint'];
12364 switch ($job['cmd']) {
12365 case 'install':
12366 $packages = $this->pool->whatProvides($packageName, $constraint);
12367 if (!$packages) {
12368 return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
12369 }
12370
12371 return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
12372 case 'update':
12373 return 'Update request for '.$packageName.$this->constraintToText($constraint).'.';
12374 case 'remove':
12375 return 'Removal request for '.$packageName.$this->constraintToText($constraint).'';
12376 }
12377
12378 if (isset($constraint)) {
12379 $packages = $this->pool->whatProvides($packageName, $constraint);
12380 } else {
12381 $packages = array();
12382 }
12383
12384 return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
12385 }
12386
12387 protected function getPackageList($packages)
12388 {
12389 $prepared = array();
12390 foreach ($packages as $package) {
12391 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12392 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12393 }
12394 foreach ($prepared as $name => $package) {
12395 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12396 }
12397
12398 return implode(', ', $prepared);
12399 }
12400
12401
12402
12403
12404
12405
12406
12407 protected function constraintToText($constraint)
12408 {
12409 return $constraint ? ' '.$constraint->getPrettyString() : '';
12410 }
12411 }
12412 <?php
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
12423
12424 namespace Composer\DependencyResolver;
12425
12426 use Composer\Semver\Constraint\ConstraintInterface;
12427
12428
12429
12430
12431 class Request
12432 {
12433 protected $jobs;
12434
12435 public function __construct()
12436 {
12437 $this->jobs = array();
12438 }
12439
12440 public function install($packageName, ConstraintInterface $constraint = null)
12441 {
12442 $this->addJob($packageName, 'install', $constraint);
12443 }
12444
12445 public function update($packageName, ConstraintInterface $constraint = null)
12446 {
12447 $this->addJob($packageName, 'update', $constraint);
12448 }
12449
12450 public function remove($packageName, ConstraintInterface $constraint = null)
12451 {
12452 $this->addJob($packageName, 'remove', $constraint);
12453 }
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463 public function fix($packageName, ConstraintInterface $constraint = null)
12464 {
12465 $this->addJob($packageName, 'install', $constraint, true);
12466 }
12467
12468 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
12469 {
12470 $packageName = strtolower($packageName);
12471
12472 $this->jobs[] = array(
12473 'cmd' => $cmd,
12474 'packageName' => $packageName,
12475 'constraint' => $constraint,
12476 'fixed' => $fixed,
12477 );
12478 }
12479
12480 public function updateAll()
12481 {
12482 $this->jobs[] = array('cmd' => 'update-all');
12483 }
12484
12485 public function getJobs()
12486 {
12487 return $this->jobs;
12488 }
12489 }
12490 <?php
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501
12502 namespace Composer\DependencyResolver;
12503
12504 use Composer\Package\CompletePackage;
12505 use Composer\Package\Link;
12506 use Composer\Package\PackageInterface;
12507
12508
12509
12510
12511
12512 abstract class Rule
12513 {
12514
12515  const RULE_INTERNAL_ALLOW_UPDATE = 1;
12516 const RULE_JOB_INSTALL = 2;
12517 const RULE_JOB_REMOVE = 3;
12518 const RULE_PACKAGE_CONFLICT = 6;
12519 const RULE_PACKAGE_REQUIRES = 7;
12520 const RULE_PACKAGE_OBSOLETES = 8;
12521 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
12522 const RULE_PACKAGE_SAME_NAME = 10;
12523 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
12524 const RULE_LEARNED = 12;
12525 const RULE_PACKAGE_ALIAS = 13;
12526
12527
12528  const BITFIELD_TYPE = 0;
12529 const BITFIELD_REASON = 8;
12530 const BITFIELD_DISABLED = 16;
12531
12532 protected $bitfield;
12533 protected $job;
12534 protected $reasonData;
12535
12536
12537
12538
12539
12540
12541 public function __construct($reason, $reasonData, $job = null)
12542 {
12543 $this->reasonData = $reasonData;
12544
12545 if ($job) {
12546 $this->job = $job;
12547 }
12548
12549 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
12550 ($reason << self::BITFIELD_REASON) |
12551 (255 << self::BITFIELD_TYPE);
12552 }
12553
12554 abstract public function getLiterals();
12555
12556 abstract public function getHash();
12557
12558 public function getJob()
12559 {
12560 return $this->job;
12561 }
12562
12563 abstract public function equals(Rule $rule);
12564
12565 public function getReason()
12566 {
12567 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
12568 }
12569
12570 public function getReasonData()
12571 {
12572 return $this->reasonData;
12573 }
12574
12575 public function getRequiredPackage()
12576 {
12577 if ($this->getReason() === self::RULE_JOB_INSTALL) {
12578 return $this->reasonData;
12579 }
12580
12581 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
12582 return $this->reasonData->getTarget();
12583 }
12584 }
12585
12586 public function setType($type)
12587 {
12588 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
12589 }
12590
12591 public function getType()
12592 {
12593 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
12594 }
12595
12596 public function disable()
12597 {
12598 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
12599 }
12600
12601 public function enable()
12602 {
12603 $this->bitfield &= ~(255 << self::BITFIELD_DISABLED);
12604 }
12605
12606 public function isDisabled()
12607 {
12608 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
12609 }
12610
12611 public function isEnabled()
12612 {
12613 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
12614 }
12615
12616 abstract public function isAssertion();
12617
12618 public function getPrettyString(Pool $pool, array $installedMap = array())
12619 {
12620 $literals = $this->getLiterals();
12621
12622 $ruleText = '';
12623 foreach ($literals as $i => $literal) {
12624 if ($i != 0) {
12625 $ruleText .= '|';
12626 }
12627 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
12628 }
12629
12630 switch ($this->getReason()) {
12631 case self::RULE_INTERNAL_ALLOW_UPDATE:
12632 return $ruleText;
12633
12634 case self::RULE_JOB_INSTALL:
12635 return "Install command rule ($ruleText)";
12636
12637 case self::RULE_JOB_REMOVE:
12638 return "Remove command rule ($ruleText)";
12639
12640 case self::RULE_PACKAGE_CONFLICT:
12641 $package1 = $pool->literalToPackage($literals[0]);
12642 $package2 = $pool->literalToPackage($literals[1]);
12643
12644 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
12645
12646 case self::RULE_PACKAGE_REQUIRES:
12647 $sourceLiteral = array_shift($literals);
12648 $sourcePackage = $pool->literalToPackage($sourceLiteral);
12649
12650 $requires = array();
12651 foreach ($literals as $literal) {
12652 $requires[] = $pool->literalToPackage($literal);
12653 }
12654
12655 $text = $this->reasonData->getPrettyString($sourcePackage);
12656 if ($requires) {
12657 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
12658 } else {
12659 $targetName = $this->reasonData->getTarget();
12660
12661 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
12662
12663  if (defined('HHVM_VERSION')) {
12664 return $text . ' -> your HHVM version does not satisfy that requirement.';
12665 }
12666
12667 $packages = $pool->whatProvides($targetName);
12668 $package = count($packages) ? current($packages) : phpversion();
12669
12670 if ($targetName === 'hhvm') {
12671 if ($package instanceof CompletePackage) {
12672 return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12673 } else {
12674 return $text . ' -> you are running this with PHP and not HHVM.';
12675 }
12676 }
12677
12678
12679 if (!($package instanceof CompletePackage)) {
12680 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
12681 }
12682
12683 $extra = $package->getExtra();
12684
12685 if (!empty($extra['config.platform'])) {
12686 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12687 } else {
12688 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12689 }
12690
12691 return $text;
12692 }
12693
12694 if (0 === strpos($targetName, 'ext-')) {
12695
12696  $ext = substr($targetName, 4);
12697 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
12698
12699 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
12700 }
12701
12702 if (0 === strpos($targetName, 'lib-')) {
12703
12704  $lib = substr($targetName, 4);
12705
12706 return $text . ' -> the requested linked library '.$lib.' has the wrong version installed or is missing from your system, make sure to have the extension providing it.';
12707 }
12708
12709 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
12710 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
12711 }
12712
12713 return $text . ' -> no matching package found.';
12714 }
12715
12716 return $text;
12717
12718 case self::RULE_PACKAGE_OBSOLETES:
12719 return $ruleText;
12720 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
12721 return $ruleText;
12722 case self::RULE_PACKAGE_SAME_NAME:
12723 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
12724 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
12725 return $ruleText;
12726 case self::RULE_LEARNED:
12727 return 'Conclusion: '.$ruleText;
12728 case self::RULE_PACKAGE_ALIAS:
12729 return $ruleText;
12730 default:
12731 return '('.$ruleText.')';
12732 }
12733 }
12734
12735
12736
12737
12738
12739
12740
12741 protected function formatPackagesUnique($pool, array $packages)
12742 {
12743 $prepared = array();
12744 foreach ($packages as $package) {
12745 if (!is_object($package)) {
12746 $package = $pool->literalToPackage($package);
12747 }
12748 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12749 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12750 }
12751 foreach ($prepared as $name => $package) {
12752 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12753 }
12754
12755 return implode(', ', $prepared);
12756 }
12757 }
12758 <?php
12759
12760
12761
12762
12763
12764
12765
12766
12767
12768
12769
12770 namespace Composer\DependencyResolver;
12771
12772 use Composer\Package\PackageInterface;
12773 use Composer\Package\Link;
12774
12775
12776
12777
12778 class Rule2Literals extends Rule
12779 {
12780 protected $literal1;
12781 protected $literal2;
12782
12783
12784
12785
12786
12787
12788
12789
12790 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
12791 {
12792 parent::__construct($reason, $reasonData, $job);
12793
12794 if ($literal1 < $literal2) {
12795 $this->literal1 = $literal1;
12796 $this->literal2 = $literal2;
12797 } else {
12798 $this->literal1 = $literal2;
12799 $this->literal2 = $literal1;
12800 }
12801 }
12802
12803 public function getLiterals()
12804 {
12805 return array($this->literal1, $this->literal2);
12806 }
12807
12808 public function getHash()
12809 {
12810 return $this->literal1.','.$this->literal2;
12811 }
12812
12813
12814
12815
12816
12817
12818
12819
12820
12821 public function equals(Rule $rule)
12822 {
12823
12824  if ($rule instanceof self) {
12825 if ($this->literal1 !== $rule->literal1) {
12826 return false;
12827 }
12828
12829 if ($this->literal2 !== $rule->literal2) {
12830 return false;
12831 }
12832
12833 return true;
12834 }
12835
12836 $literals = $rule->getLiterals();
12837 if (2 != count($literals)) {
12838 return false;
12839 }
12840
12841 if ($this->literal1 !== $literals[0]) {
12842 return false;
12843 }
12844
12845 if ($this->literal2 !== $literals[1]) {
12846 return false;
12847 }
12848
12849 return true;
12850 }
12851
12852 public function isAssertion()
12853 {
12854 return false;
12855 }
12856
12857
12858
12859
12860
12861
12862 public function __toString()
12863 {
12864 $result = $this->isDisabled() ? 'disabled(' : '(';
12865
12866 $result .= $this->literal1 . '|' . $this->literal2 . ')';
12867
12868 return $result;
12869 }
12870 }
12871 <?php
12872
12873
12874
12875
12876
12877
12878
12879
12880
12881
12882
12883 namespace Composer\DependencyResolver;
12884
12885
12886
12887
12888 class RuleSet implements \IteratorAggregate, \Countable
12889 {
12890
12891  const TYPE_PACKAGE = 0;
12892 const TYPE_JOB = 1;
12893 const TYPE_LEARNED = 4;
12894
12895
12896
12897
12898
12899
12900 public $ruleById;
12901
12902 protected static $types = array(
12903 255 => 'UNKNOWN',
12904 self::TYPE_PACKAGE => 'PACKAGE',
12905 self::TYPE_JOB => 'JOB',
12906 self::TYPE_LEARNED => 'LEARNED',
12907 );
12908
12909 protected $rules;
12910 protected $nextRuleId;
12911
12912 protected $rulesByHash;
12913
12914 public function __construct()
12915 {
12916 $this->nextRuleId = 0;
12917
12918 foreach ($this->getTypes() as $type) {
12919 $this->rules[$type] = array();
12920 }
12921
12922 $this->rulesByHash = array();
12923 }
12924
12925 public function add(Rule $rule, $type)
12926 {
12927 if (!isset(self::$types[$type])) {
12928 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
12929 }
12930
12931 $hash = $rule->getHash();
12932
12933
12934  if (isset($this->rulesByHash[$hash])) {
12935 $potentialDuplicates = $this->rulesByHash[$hash];
12936 if (is_array($potentialDuplicates)) {
12937 foreach ($potentialDuplicates as $potentialDuplicate) {
12938 if ($rule->equals($potentialDuplicate)) {
12939 return;
12940 }
12941 }
12942 } else {
12943 if ($rule->equals($potentialDuplicates)) {
12944 return;
12945 }
12946 }
12947 }
12948
12949 if (!isset($this->rules[$type])) {
12950 $this->rules[$type] = array();
12951 }
12952
12953 $this->rules[$type][] = $rule;
12954 $this->ruleById[$this->nextRuleId] = $rule;
12955 $rule->setType($type);
12956
12957 $this->nextRuleId++;
12958
12959 if (!isset($this->rulesByHash[$hash])) {
12960 $this->rulesByHash[$hash] = $rule;
12961 } elseif (is_array($this->rulesByHash[$hash])) {
12962 $this->rulesByHash[$hash][] = $rule;
12963 } else {
12964 $originalRule = $this->rulesByHash[$hash];
12965 $this->rulesByHash[$hash] = array($originalRule, $rule);
12966 }
12967 }
12968
12969 public function count()
12970 {
12971 return $this->nextRuleId;
12972 }
12973
12974 public function ruleById($id)
12975 {
12976 return $this->ruleById[$id];
12977 }
12978
12979 public function getRules()
12980 {
12981 return $this->rules;
12982 }
12983
12984 public function getIterator()
12985 {
12986 return new RuleSetIterator($this->getRules());
12987 }
12988
12989 public function getIteratorFor($types)
12990 {
12991 if (!is_array($types)) {
12992 $types = array($types);
12993 }
12994
12995 $allRules = $this->getRules();
12996 $rules = array();
12997
12998 foreach ($types as $type) {
12999 $rules[$type] = $allRules[$type];
13000 }
13001
13002 return new RuleSetIterator($rules);
13003 }
13004
13005 public function getIteratorWithout($types)
13006 {
13007 if (!is_array($types)) {
13008 $types = array($types);
13009 }
13010
13011 $rules = $this->getRules();
13012
13013 foreach ($types as $type) {
13014 unset($rules[$type]);
13015 }
13016
13017 return new RuleSetIterator($rules);
13018 }
13019
13020 public function getTypes()
13021 {
13022 $types = self::$types;
13023 unset($types[255]);
13024
13025 return array_keys($types);
13026 }
13027
13028 public function getPrettyString(Pool $pool = null)
13029 {
13030 $string = "\n";
13031 foreach ($this->rules as $type => $rules) {
13032 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
13033 foreach ($rules as $rule) {
13034 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
13035 }
13036 $string .= "\n\n";
13037 }
13038
13039 return $string;
13040 }
13041
13042 public function __toString()
13043 {
13044 return $this->getPrettyString(null);
13045 }
13046 }
13047 <?php
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059 namespace Composer\DependencyResolver;
13060
13061 use Composer\Package\PackageInterface;
13062 use Composer\Package\AliasPackage;
13063 use Composer\Repository\PlatformRepository;
13064
13065
13066
13067
13068 class RuleSetGenerator
13069 {
13070 protected $policy;
13071 protected $pool;
13072 protected $rules;
13073 protected $jobs;
13074 protected $installedMap;
13075 protected $whitelistedMap;
13076 protected $addedMap;
13077 protected $conflictAddedMap;
13078 protected $addedPackages;
13079 protected $addedPackagesByNames;
13080
13081 public function __construct(PolicyInterface $policy, Pool $pool)
13082 {
13083 $this->policy = $policy;
13084 $this->pool = $pool;
13085 }
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
13102 {
13103 $literals = array(-$package->id);
13104
13105 foreach ($providers as $provider) {
13106
13107  if ($provider === $package) {
13108 return null;
13109 }
13110 $literals[] = $provider->id;
13111 }
13112
13113 return new GenericRule($literals, $reason, $reasonData);
13114 }
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125
13126
13127
13128 protected function createInstallOneOfRule(array $packages, $reason, $job)
13129 {
13130 $literals = array();
13131 foreach ($packages as $package) {
13132 $literals[] = $package->id;
13133 }
13134
13135 return new GenericRule($literals, $reason, $job['packageName'], $job);
13136 }
13137
13138
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149 protected function createRemoveRule(PackageInterface $package, $reason, $job)
13150 {
13151 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
13152 }
13153
13154
13155
13156
13157
13158
13159
13160
13161
13162
13163
13164
13165
13166
13167
13168 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
13169 {
13170
13171  if ($issuer === $provider) {
13172 return null;
13173 }
13174
13175 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
13176 }
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186
13187 private function addRule($type, Rule $newRule = null)
13188 {
13189 if (!$newRule) {
13190 return;
13191 }
13192
13193 $this->rules->add($newRule, $type);
13194 }
13195
13196 protected function whitelistFromPackage(PackageInterface $package)
13197 {
13198 $workQueue = new \SplQueue;
13199 $workQueue->enqueue($package);
13200
13201 while (!$workQueue->isEmpty()) {
13202 $package = $workQueue->dequeue();
13203 if (isset($this->whitelistedMap[$package->id])) {
13204 continue;
13205 }
13206
13207 $this->whitelistedMap[$package->id] = true;
13208
13209 foreach ($package->getRequires() as $link) {
13210 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
13211
13212 foreach ($possibleRequires as $require) {
13213 $workQueue->enqueue($require);
13214 }
13215 }
13216
13217 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
13218
13219 foreach ($obsoleteProviders as $provider) {
13220 if ($provider === $package) {
13221 continue;
13222 }
13223
13224 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
13225 $workQueue->enqueue($provider);
13226 }
13227 }
13228 }
13229 }
13230
13231 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
13232 {
13233 $workQueue = new \SplQueue;
13234 $workQueue->enqueue($package);
13235
13236 while (!$workQueue->isEmpty()) {
13237
13238 $package = $workQueue->dequeue();
13239 if (isset($this->addedMap[$package->id])) {
13240 continue;
13241 }
13242
13243 $this->addedMap[$package->id] = true;
13244
13245 $this->addedPackages[] = $package;
13246 foreach ($package->getNames() as $name) {
13247 $this->addedPackagesByNames[$name][] = $package;
13248 }
13249
13250 foreach ($package->getRequires() as $link) {
13251 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
13252 continue;
13253 }
13254
13255 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13256
13257 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
13258
13259 foreach ($possibleRequires as $require) {
13260 $workQueue->enqueue($require);
13261 }
13262 }
13263
13264 $packageName = $package->getName();
13265 $obsoleteProviders = $this->pool->whatProvides($packageName, null);
13266
13267 foreach ($obsoleteProviders as $provider) {
13268 if ($provider === $package) {
13269 continue;
13270 }
13271
13272 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
13273 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
13274 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
13275 $reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
13276 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
13277 }
13278 }
13279 }
13280 }
13281
13282 protected function addConflictRules($ignorePlatformReqs = false)
13283 {
13284
13285 foreach ($this->addedPackages as $package) {
13286 foreach ($package->getConflicts() as $link) {
13287 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
13288 continue;
13289 }
13290
13291 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
13292 continue;
13293 }
13294
13295
13296 foreach ($this->addedPackagesByNames[$link->getTarget()] as $possibleConflict) {
13297 $conflictMatch = $this->pool->match($possibleConflict, $link->getTarget(), $link->getConstraint(), true);
13298
13299 if ($conflictMatch === Pool::MATCH || $conflictMatch === Pool::MATCH_REPLACE) {
13300 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $possibleConflict, Rule::RULE_PACKAGE_CONFLICT, $link));
13301 }
13302
13303 }
13304 }
13305
13306
13307  $isInstalled = isset($this->installedMap[$package->id]);
13308
13309 foreach ($package->getReplaces() as $link) {
13310 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
13311 continue;
13312 }
13313
13314
13315 foreach ($this->addedPackagesByNames[$link->getTarget()] as $provider) {
13316 if ($provider === $package) {
13317 continue;
13318 }
13319
13320 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
13321 $reason = $isInstalled ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
13322 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
13323 }
13324 }
13325 }
13326 }
13327 }
13328
13329 protected function obsoleteImpossibleForAlias($package, $provider)
13330 {
13331 $packageIsAlias = $package instanceof AliasPackage;
13332 $providerIsAlias = $provider instanceof AliasPackage;
13333
13334 $impossible = (
13335 ($packageIsAlias && $package->getAliasOf() === $provider) ||
13336 ($providerIsAlias && $provider->getAliasOf() === $package) ||
13337 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
13338 );
13339
13340 return $impossible;
13341 }
13342
13343 protected function whitelistFromJobs()
13344 {
13345 foreach ($this->jobs as $job) {
13346 switch ($job['cmd']) {
13347 case 'install':
13348 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
13349 foreach ($packages as $package) {
13350 $this->whitelistFromPackage($package);
13351 }
13352 break;
13353 }
13354 }
13355 }
13356
13357 protected function addRulesForJobs($ignorePlatformReqs)
13358 {
13359 foreach ($this->jobs as $job) {
13360 switch ($job['cmd']) {
13361 case 'install':
13362 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
13363 break;
13364 }
13365
13366 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
13367 if ($packages) {
13368 foreach ($packages as $package) {
13369 if (!isset($this->installedMap[$package->id])) {
13370 $this->addRulesForPackage($package, $ignorePlatformReqs);
13371 }
13372 }
13373
13374 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
13375 $this->addRule(RuleSet::TYPE_JOB, $rule);
13376 }
13377 break;
13378 case 'remove':
13379
13380  
13381  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
13382 foreach ($packages as $package) {
13383 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
13384 $this->addRule(RuleSet::TYPE_JOB, $rule);
13385 }
13386 break;
13387 }
13388 }
13389 }
13390
13391 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
13392 {
13393 $this->jobs = $jobs;
13394 $this->rules = new RuleSet;
13395 $this->installedMap = $installedMap;
13396
13397 $this->whitelistedMap = array();
13398 foreach ($this->installedMap as $package) {
13399 $this->whitelistFromPackage($package);
13400 }
13401 $this->whitelistFromJobs();
13402
13403 $this->pool->setWhitelist($this->whitelistedMap);
13404
13405 $this->addedMap = array();
13406 $this->conflictAddedMap = array();
13407 $this->addedPackages = array();
13408 $this->addedPackagesByNames = array();
13409 foreach ($this->installedMap as $package) {
13410 $this->addRulesForPackage($package, $ignorePlatformReqs);
13411 }
13412
13413 $this->addRulesForJobs($ignorePlatformReqs);
13414
13415 $this->addConflictRules($ignorePlatformReqs);
13416
13417
13418  $this->addedPackages = $this->addedPackagesByNames = null;
13419
13420 return $this->rules;
13421 }
13422 }
13423 <?php
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434
13435 namespace Composer\DependencyResolver;
13436
13437
13438
13439
13440 class RuleSetIterator implements \Iterator
13441 {
13442 protected $rules;
13443 protected $types;
13444
13445 protected $currentOffset;
13446 protected $currentType;
13447 protected $currentTypeOffset;
13448
13449 public function __construct(array $rules)
13450 {
13451 $this->rules = $rules;
13452 $this->types = array_keys($rules);
13453 sort($this->types);
13454
13455 $this->rewind();
13456 }
13457
13458 public function current()
13459 {
13460 return $this->rules[$this->currentType][$this->currentOffset];
13461 }
13462
13463 public function key()
13464 {
13465 return $this->currentType;
13466 }
13467
13468 public function next()
13469 {
13470 $this->currentOffset++;
13471
13472 if (!isset($this->rules[$this->currentType])) {
13473 return;
13474 }
13475
13476 if ($this->currentOffset >= count($this->rules[$this->currentType])) {
13477 $this->currentOffset = 0;
13478
13479 do {
13480 $this->currentTypeOffset++;
13481
13482 if (!isset($this->types[$this->currentTypeOffset])) {
13483 $this->currentType = -1;
13484 break;
13485 }
13486
13487 $this->currentType = $this->types[$this->currentTypeOffset];
13488 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
13489 }
13490 }
13491
13492 public function rewind()
13493 {
13494 $this->currentOffset = 0;
13495
13496 $this->currentTypeOffset = -1;
13497 $this->currentType = -1;
13498
13499 do {
13500 $this->currentTypeOffset++;
13501
13502 if (!isset($this->types[$this->currentTypeOffset])) {
13503 $this->currentType = -1;
13504 break;
13505 }
13506
13507 $this->currentType = $this->types[$this->currentTypeOffset];
13508 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
13509 }
13510
13511 public function valid()
13512 {
13513 return isset($this->rules[$this->currentType])
13514 && isset($this->rules[$this->currentType][$this->currentOffset]);
13515 }
13516 }
13517 <?php
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529 namespace Composer\DependencyResolver;
13530
13531
13532
13533
13534
13535
13536
13537
13538
13539 class RuleWatchChain extends \SplDoublyLinkedList
13540 {
13541 protected $offset = 0;
13542
13543
13544
13545
13546
13547
13548 public function seek($offset)
13549 {
13550 $this->rewind();
13551 for ($i = 0; $i < $offset; $i++, $this->next());
13552 }
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562 public function remove()
13563 {
13564 $offset = $this->key();
13565 $this->offsetUnset($offset);
13566 $this->seek($offset);
13567 }
13568 }
13569 <?php
13570
13571
13572
13573
13574
13575
13576
13577
13578
13579
13580
13581 namespace Composer\DependencyResolver;
13582
13583
13584
13585
13586
13587
13588
13589
13590
13591
13592
13593 class RuleWatchGraph
13594 {
13595 protected $watchChains = array();
13596
13597
13598
13599
13600
13601
13602
13603
13604
13605
13606
13607
13608
13609 public function insert(RuleWatchNode $node)
13610 {
13611 if ($node->getRule()->isAssertion()) {
13612 return;
13613 }
13614
13615 foreach (array($node->watch1, $node->watch2) as $literal) {
13616 if (!isset($this->watchChains[$literal])) {
13617 $this->watchChains[$literal] = new RuleWatchChain;
13618 }
13619
13620 $this->watchChains[$literal]->unshift($node);
13621 }
13622 }
13623
13624
13625
13626
13627
13628
13629
13630
13631
13632
13633
13634
13635
13636
13637
13638
13639
13640
13641
13642
13643
13644
13645
13646
13647 public function propagateLiteral($decidedLiteral, $level, $decisions)
13648 {
13649
13650  
13651  
13652  $literal = -$decidedLiteral;
13653
13654 if (!isset($this->watchChains[$literal])) {
13655 return null;
13656 }
13657
13658 $chain = $this->watchChains[$literal];
13659
13660 $chain->rewind();
13661 while ($chain->valid()) {
13662 $node = $chain->current();
13663 $otherWatch = $node->getOtherWatch($literal);
13664
13665 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
13666 $ruleLiterals = $node->getRule()->getLiterals();
13667
13668 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
13669 return $literal !== $ruleLiteral &&
13670 $otherWatch !== $ruleLiteral &&
13671 !$decisions->conflict($ruleLiteral);
13672 });
13673
13674 if ($alternativeLiterals) {
13675 reset($alternativeLiterals);
13676 $this->moveWatch($literal, current($alternativeLiterals), $node);
13677 continue;
13678 }
13679
13680 if ($decisions->conflict($otherWatch)) {
13681 return $node->getRule();
13682 }
13683
13684 $decisions->decide($otherWatch, $level, $node->getRule());
13685 }
13686
13687 $chain->next();
13688 }
13689
13690 return null;
13691 }
13692
13693
13694
13695
13696
13697
13698
13699
13700
13701
13702 protected function moveWatch($fromLiteral, $toLiteral, $node)
13703 {
13704 if (!isset($this->watchChains[$toLiteral])) {
13705 $this->watchChains[$toLiteral] = new RuleWatchChain;
13706 }
13707
13708 $node->moveWatch($fromLiteral, $toLiteral);
13709 $this->watchChains[$fromLiteral]->remove();
13710 $this->watchChains[$toLiteral]->unshift($node);
13711 }
13712 }
13713 <?php
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725 namespace Composer\DependencyResolver;
13726
13727
13728
13729
13730
13731
13732
13733
13734 class RuleWatchNode
13735 {
13736 public $watch1;
13737 public $watch2;
13738
13739 protected $rule;
13740
13741
13742
13743
13744
13745
13746 public function __construct($rule)
13747 {
13748 $this->rule = $rule;
13749
13750 $literals = $rule->getLiterals();
13751
13752 $literalCount = count($literals);
13753 $this->watch1 = $literalCount > 0 ? $literals[0] : 0;
13754 $this->watch2 = $literalCount > 1 ? $literals[1] : 0;
13755 }
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765 public function watch2OnHighest(Decisions $decisions)
13766 {
13767 $literals = $this->rule->getLiterals();
13768
13769
13770  if (count($literals) < 3) {
13771 return;
13772 }
13773
13774 $watchLevel = 0;
13775
13776 foreach ($literals as $literal) {
13777 $level = $decisions->decisionLevel($literal);
13778
13779 if ($level > $watchLevel) {
13780 $this->watch2 = $literal;
13781 $watchLevel = $level;
13782 }
13783 }
13784 }
13785
13786
13787
13788
13789
13790
13791 public function getRule()
13792 {
13793 return $this->rule;
13794 }
13795
13796
13797
13798
13799
13800
13801
13802 public function getOtherWatch($literal)
13803 {
13804 if ($this->watch1 == $literal) {
13805 return $this->watch2;
13806 }
13807
13808 return $this->watch1;
13809 }
13810
13811
13812
13813
13814
13815
13816
13817 public function moveWatch($from, $to)
13818 {
13819 if ($this->watch1 == $from) {
13820 $this->watch1 = $to;
13821 } else {
13822 $this->watch2 = $to;
13823 }
13824 }
13825 }
13826 <?php
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838 namespace Composer\DependencyResolver;
13839
13840 use Composer\IO\IOInterface;
13841 use Composer\Repository\RepositoryInterface;
13842 use Composer\Repository\PlatformRepository;
13843
13844
13845
13846
13847 class Solver
13848 {
13849 const BRANCH_LITERALS = 0;
13850 const BRANCH_LEVEL = 1;
13851
13852
13853 protected $policy;
13854
13855 protected $pool;
13856
13857 protected $installed;
13858
13859 protected $rules;
13860
13861 protected $ruleSetGenerator;
13862
13863 protected $jobs;
13864
13865
13866 protected $updateMap = array();
13867
13868 protected $watchGraph;
13869
13870 protected $decisions;
13871
13872 protected $installedMap;
13873
13874
13875 protected $propagateIndex;
13876
13877 protected $branches = array();
13878
13879 protected $problems = array();
13880
13881 protected $learnedPool = array();
13882
13883 protected $learnedWhy = array();
13884
13885
13886 public $testFlagLearnedPositiveLiteral = false;
13887
13888
13889 protected $io;
13890
13891
13892
13893
13894
13895
13896
13897 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
13898 {
13899 $this->io = $io;
13900 $this->policy = $policy;
13901 $this->pool = $pool;
13902 $this->installed = $installed;
13903 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
13904 }
13905
13906
13907
13908
13909 public function getRuleSetSize()
13910 {
13911 return count($this->rules);
13912 }
13913
13914
13915
13916 private function makeAssertionRuleDecisions()
13917 {
13918 $decisionStart = count($this->decisions) - 1;
13919
13920 $rulesCount = count($this->rules);
13921 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
13922 $rule = $this->rules->ruleById[$ruleIndex];
13923
13924 if (!$rule->isAssertion() || $rule->isDisabled()) {
13925 continue;
13926 }
13927
13928 $literals = $rule->getLiterals();
13929 $literal = $literals[0];
13930
13931 if (!$this->decisions->decided($literal)) {
13932 $this->decisions->decide($literal, 1, $rule);
13933 continue;
13934 }
13935
13936 if ($this->decisions->satisfy($literal)) {
13937 continue;
13938 }
13939
13940
13941  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
13942 $rule->disable();
13943 continue;
13944 }
13945
13946 $conflict = $this->decisions->decisionRule($literal);
13947
13948 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
13949 $problem = new Problem($this->pool);
13950
13951 $problem->addRule($rule);
13952 $problem->addRule($conflict);
13953 $this->disableProblem($rule);
13954 $this->problems[] = $problem;
13955 continue;
13956 }
13957
13958
13959  $problem = new Problem($this->pool);
13960 $problem->addRule($rule);
13961 $problem->addRule($conflict);
13962
13963
13964  
13965  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
13966 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
13967 continue;
13968 }
13969
13970 $assertRuleLiterals = $assertRule->getLiterals();
13971 $assertRuleLiteral = $assertRuleLiterals[0];
13972
13973 if (abs($literal) !== abs($assertRuleLiteral)) {
13974 continue;
13975 }
13976
13977 $problem->addRule($assertRule);
13978 $this->disableProblem($assertRule);
13979 }
13980 $this->problems[] = $problem;
13981
13982 $this->decisions->resetToOffset($decisionStart);
13983 $ruleIndex = -1;
13984 }
13985 }
13986
13987 protected function setupInstalledMap()
13988 {
13989 $this->installedMap = array();
13990 foreach ($this->installed->getPackages() as $package) {
13991 $this->installedMap[$package->id] = $package;
13992 }
13993 }
13994
13995
13996
13997
13998 protected function checkForRootRequireProblems($ignorePlatformReqs)
13999 {
14000 foreach ($this->jobs as $job) {
14001 switch ($job['cmd']) {
14002 case 'update':
14003 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14004 foreach ($packages as $package) {
14005 if (isset($this->installedMap[$package->id])) {
14006 $this->updateMap[$package->id] = true;
14007 }
14008 }
14009 break;
14010
14011 case 'update-all':
14012 foreach ($this->installedMap as $package) {
14013 $this->updateMap[$package->id] = true;
14014 }
14015 break;
14016
14017 case 'install':
14018 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
14019 break;
14020 }
14021
14022 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
14023 $problem = new Problem($this->pool);
14024 $problem->addRule(new GenericRule(array(), null, null, $job));
14025 $this->problems[] = $problem;
14026 }
14027 break;
14028 }
14029 }
14030 }
14031
14032
14033
14034
14035
14036
14037 public function solve(Request $request, $ignorePlatformReqs = false)
14038 {
14039 $this->jobs = $request->getJobs();
14040
14041 $this->setupInstalledMap();
14042 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
14043 $this->checkForRootRequireProblems($ignorePlatformReqs);
14044 $this->decisions = new Decisions($this->pool);
14045 $this->watchGraph = new RuleWatchGraph;
14046
14047 foreach ($this->rules as $rule) {
14048 $this->watchGraph->insert(new RuleWatchNode($rule));
14049 }
14050
14051
14052 $this->makeAssertionRuleDecisions();
14053
14054 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
14055 $before = microtime(true);
14056 $this->runSat(true);
14057 $this->io->writeError('', true, IOInterface::DEBUG);
14058 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
14059
14060
14061  foreach ($this->installedMap as $packageId => $void) {
14062 if ($this->decisions->undecided($packageId)) {
14063 $this->decisions->decide(-$packageId, 1, null);
14064 }
14065 }
14066
14067 if ($this->problems) {
14068 throw new SolverProblemsException($this->problems, $this->installedMap);
14069 }
14070
14071 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
14072
14073 return $transaction->getOperations();
14074 }
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084
14085 protected function propagate($level)
14086 {
14087 while ($this->decisions->validOffset($this->propagateIndex)) {
14088 $decision = $this->decisions->atOffset($this->propagateIndex);
14089
14090 $conflict = $this->watchGraph->propagateLiteral(
14091 $decision[Decisions::DECISION_LITERAL],
14092 $level,
14093 $this->decisions
14094 );
14095
14096 $this->propagateIndex++;
14097
14098 if ($conflict) {
14099 return $conflict;
14100 }
14101 }
14102
14103 return null;
14104 }
14105
14106
14107
14108
14109
14110
14111 private function revert($level)
14112 {
14113 while (!$this->decisions->isEmpty()) {
14114 $literal = $this->decisions->lastLiteral();
14115
14116 if ($this->decisions->undecided($literal)) {
14117 break;
14118 }
14119
14120 $decisionLevel = $this->decisions->decisionLevel($literal);
14121
14122 if ($decisionLevel <= $level) {
14123 break;
14124 }
14125
14126 $this->decisions->revertLast();
14127 $this->propagateIndex = count($this->decisions);
14128 }
14129
14130 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
14131 array_pop($this->branches);
14132 }
14133 }
14134
14135
14136
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147
14148
14149
14150
14151
14152
14153
14154 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
14155 {
14156 $level++;
14157
14158 $this->decisions->decide($literal, $level, $rule);
14159
14160 while (true) {
14161 $rule = $this->propagate($level);
14162
14163 if (!$rule) {
14164 break;
14165 }
14166
14167 if ($level == 1) {
14168 return $this->analyzeUnsolvable($rule, $disableRules);
14169 }
14170
14171
14172  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
14173
14174 if ($newLevel <= 0 || $newLevel >= $level) {
14175 throw new SolverBugException(
14176 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
14177 );
14178 } elseif (!$newRule) {
14179 throw new SolverBugException(
14180 "No rule was learned from analyzing $rule at level $level."
14181 );
14182 }
14183
14184 $level = $newLevel;
14185
14186 $this->revert($level);
14187
14188 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
14189
14190 $this->learnedWhy[spl_object_hash($newRule)] = $why;
14191
14192 $ruleNode = new RuleWatchNode($newRule);
14193 $ruleNode->watch2OnHighest($this->decisions);
14194 $this->watchGraph->insert($ruleNode);
14195
14196 $this->decisions->decide($learnLiteral, $level, $newRule);
14197 }
14198
14199 return $level;
14200 }
14201
14202
14203
14204
14205
14206
14207
14208
14209 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
14210 {
14211
14212  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
14213
14214 $selectedLiteral = array_shift($literals);
14215
14216
14217  if (count($literals)) {
14218 $this->branches[] = array($literals, $level);
14219 }
14220
14221 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
14222 }
14223
14224
14225
14226
14227
14228
14229 protected function analyze($level, Rule $rule)
14230 {
14231 $analyzedRule = $rule;
14232 $ruleLevel = 1;
14233 $num = 0;
14234 $l1num = 0;
14235 $seen = array();
14236 $learnedLiterals = array(null);
14237
14238 $decisionId = count($this->decisions);
14239
14240 $this->learnedPool[] = array();
14241
14242 while (true) {
14243 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
14244
14245 foreach ($rule->getLiterals() as $literal) {
14246
14247  if ($this->decisions->satisfy($literal)) {
14248 continue;
14249 }
14250
14251 if (isset($seen[abs($literal)])) {
14252 continue;
14253 }
14254 $seen[abs($literal)] = true;
14255
14256 $l = $this->decisions->decisionLevel($literal);
14257
14258 if (1 === $l) {
14259 $l1num++;
14260 } elseif ($level === $l) {
14261 $num++;
14262 } else {
14263
14264  $learnedLiterals[] = $literal;
14265
14266 if ($l > $ruleLevel) {
14267 $ruleLevel = $l;
14268 }
14269 }
14270 }
14271
14272 $l1retry = true;
14273 while ($l1retry) {
14274 $l1retry = false;
14275
14276 if (!$num && !--$l1num) {
14277
14278  break 2;
14279 }
14280
14281 while (true) {
14282 if ($decisionId <= 0) {
14283 throw new SolverBugException(
14284 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
14285 );
14286 }
14287
14288 $decisionId--;
14289
14290 $decision = $this->decisions->atOffset($decisionId);
14291 $literal = $decision[Decisions::DECISION_LITERAL];
14292
14293 if (isset($seen[abs($literal)])) {
14294 break;
14295 }
14296 }
14297
14298 unset($seen[abs($literal)]);
14299
14300 if ($num && 0 === --$num) {
14301 if ($literal < 0) {
14302 $this->testFlagLearnedPositiveLiteral = true;
14303 }
14304 $learnedLiterals[0] = -$literal;
14305
14306 if (!$l1num) {
14307 break 2;
14308 }
14309
14310 foreach ($learnedLiterals as $i => $learnedLiteral) {
14311 if ($i !== 0) {
14312 unset($seen[abs($learnedLiteral)]);
14313 }
14314 }
14315
14316  $l1num++;
14317 $l1retry = true;
14318 }
14319 }
14320
14321 $decision = $this->decisions->atOffset($decisionId);
14322 $rule = $decision[Decisions::DECISION_REASON];
14323 }
14324
14325 $why = count($this->learnedPool) - 1;
14326
14327 if (!$learnedLiterals[0]) {
14328 throw new SolverBugException(
14329 "Did not find a learnable literal in analyzed rule $analyzedRule."
14330 );
14331 }
14332
14333 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
14334
14335 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
14336 }
14337
14338
14339
14340
14341
14342 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
14343 {
14344 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
14345 $why = spl_object_hash($conflictRule);
14346 $learnedWhy = $this->learnedWhy[$why];
14347 $problemRules = $this->learnedPool[$learnedWhy];
14348
14349 foreach ($problemRules as $problemRule) {
14350 $this->analyzeUnsolvableRule($problem, $problemRule);
14351 }
14352
14353 return;
14354 }
14355
14356 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
14357
14358  return;
14359 }
14360
14361 $problem->nextSection();
14362 $problem->addRule($conflictRule);
14363 }
14364
14365
14366
14367
14368
14369
14370 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
14371 {
14372 $problem = new Problem($this->pool);
14373 $problem->addRule($conflictRule);
14374
14375 $this->analyzeUnsolvableRule($problem, $conflictRule);
14376
14377 $this->problems[] = $problem;
14378
14379 $seen = array();
14380 $literals = $conflictRule->getLiterals();
14381
14382 foreach ($literals as $literal) {
14383
14384  if ($this->decisions->satisfy($literal)) {
14385 continue;
14386 }
14387 $seen[abs($literal)] = true;
14388 }
14389
14390 foreach ($this->decisions as $decision) {
14391 $literal = $decision[Decisions::DECISION_LITERAL];
14392
14393
14394  if (!isset($seen[abs($literal)])) {
14395 continue;
14396 }
14397
14398 $why = $decision[Decisions::DECISION_REASON];
14399
14400 $problem->addRule($why);
14401 $this->analyzeUnsolvableRule($problem, $why);
14402
14403 $literals = $why->getLiterals();
14404
14405 foreach ($literals as $literal) {
14406
14407  if ($this->decisions->satisfy($literal)) {
14408 continue;
14409 }
14410 $seen[abs($literal)] = true;
14411 }
14412 }
14413
14414 if ($disableRules) {
14415 foreach ($this->problems[count($this->problems) - 1] as $reason) {
14416 $this->disableProblem($reason['rule']);
14417 }
14418
14419 $this->resetSolver();
14420
14421 return 1;
14422 }
14423
14424 return 0;
14425 }
14426
14427
14428
14429
14430 private function disableProblem(Rule $why)
14431 {
14432 $job = $why->getJob();
14433
14434 if (!$job) {
14435 $why->disable();
14436
14437 return;
14438 }
14439
14440
14441  foreach ($this->rules as $rule) {
14442
14443 if ($job === $rule->getJob()) {
14444 $rule->disable();
14445 }
14446 }
14447 }
14448
14449 private function resetSolver()
14450 {
14451 $this->decisions->reset();
14452
14453 $this->propagateIndex = 0;
14454 $this->branches = array();
14455
14456 $this->enableDisableLearnedRules();
14457 $this->makeAssertionRuleDecisions();
14458 }
14459
14460
14461
14462
14463
14464
14465
14466
14467 private function enableDisableLearnedRules()
14468 {
14469 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
14470 $why = $this->learnedWhy[spl_object_hash($rule)];
14471 $problemRules = $this->learnedPool[$why];
14472
14473 $foundDisabled = false;
14474 foreach ($problemRules as $problemRule) {
14475 if ($problemRule->isDisabled()) {
14476 $foundDisabled = true;
14477 break;
14478 }
14479 }
14480
14481 if ($foundDisabled && $rule->isEnabled()) {
14482 $rule->disable();
14483 } elseif (!$foundDisabled && $rule->isDisabled()) {
14484 $rule->enable();
14485 }
14486 }
14487 }
14488
14489
14490
14491
14492 private function runSat($disableRules = true)
14493 {
14494 $this->propagateIndex = 0;
14495
14496
14497
14498
14499
14500
14501
14502
14503
14504
14505
14506 $decisionQueue = array();
14507 $decisionSupplementQueue = array();
14508
14509
14510
14511 $disableRules = array();
14512
14513 $level = 1;
14514 $systemLevel = $level + 1;
14515 $installedPos = 0;
14516
14517 while (true) {
14518 if (1 === $level) {
14519 $conflictRule = $this->propagate($level);
14520 if (null !== $conflictRule) {
14521 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
14522 continue;
14523 }
14524
14525 return;
14526 }
14527 }
14528
14529
14530  if ($level < $systemLevel) {
14531 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
14532 foreach ($iterator as $rule) {
14533 if ($rule->isEnabled()) {
14534 $decisionQueue = array();
14535 $noneSatisfied = true;
14536
14537 foreach ($rule->getLiterals() as $literal) {
14538 if ($this->decisions->satisfy($literal)) {
14539 $noneSatisfied = false;
14540 break;
14541 }
14542 if ($literal > 0 && $this->decisions->undecided($literal)) {
14543 $decisionQueue[] = $literal;
14544 }
14545 }
14546
14547 if ($noneSatisfied && count($decisionQueue)) {
14548
14549  
14550  if (count($this->installed) != count($this->updateMap)) {
14551 $prunedQueue = array();
14552 foreach ($decisionQueue as $literal) {
14553 if (isset($this->installedMap[abs($literal)])) {
14554 $prunedQueue[] = $literal;
14555 if (isset($this->updateMap[abs($literal)])) {
14556 $prunedQueue = $decisionQueue;
14557 break;
14558 }
14559 }
14560 }
14561 $decisionQueue = $prunedQueue;
14562 }
14563 }
14564
14565 if ($noneSatisfied && count($decisionQueue)) {
14566 $oLevel = $level;
14567 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
14568
14569 if (0 === $level) {
14570 return;
14571 }
14572 if ($level <= $oLevel) {
14573 break;
14574 }
14575 }
14576 }
14577 }
14578
14579 $systemLevel = $level + 1;
14580
14581
14582  $iterator->next();
14583 if ($iterator->valid()) {
14584 continue;
14585 }
14586 }
14587
14588 if ($level < $systemLevel) {
14589 $systemLevel = $level;
14590 }
14591
14592 $rulesCount = count($this->rules);
14593 $pass = 1;
14594
14595 $this->io->writeError('Looking at all rules.', true, IOInterface::DEBUG);
14596 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
14597 if ($i == $rulesCount) {
14598 if (1 === $pass) {
14599 $this->io->writeError("Something's changed, looking at all rules again (pass #$pass)", false, IOInterface::DEBUG);
14600 } else {
14601 $this->io->overwriteError("Something's changed, looking at all rules again (pass #$pass)", false, null, IOInterface::DEBUG);
14602 }
14603
14604 $i = 0;
14605 $pass++;
14606 }
14607
14608 $rule = $this->rules->ruleById[$i];
14609 $literals = $rule->getLiterals();
14610
14611 if ($rule->isDisabled()) {
14612 continue;
14613 }
14614
14615 $decisionQueue = array();
14616
14617
14618  
14619  
14620  
14621  
14622  
14623  foreach ($literals as $literal) {
14624 if ($literal <= 0) {
14625 if (!$this->decisions->decidedInstall($literal)) {
14626 continue 2; 
14627  }
14628 } else {
14629 if ($this->decisions->decidedInstall($literal)) {
14630 continue 2; 
14631  }
14632 if ($this->decisions->undecided($literal)) {
14633 $decisionQueue[] = $literal;
14634 }
14635 }
14636 }
14637
14638
14639  if (count($decisionQueue) < 2) {
14640 continue;
14641 }
14642
14643 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
14644
14645 if (0 === $level) {
14646 return;
14647 }
14648
14649
14650  $rulesCount = count($this->rules);
14651 $n = -1;
14652 }
14653
14654 if ($level < $systemLevel) {
14655 continue;
14656 }
14657
14658
14659  if (count($this->branches)) {
14660 $lastLiteral = null;
14661 $lastLevel = null;
14662 $lastBranchIndex = 0;
14663 $lastBranchOffset = 0;
14664
14665 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
14666 list($literals, $l) = $this->branches[$i];
14667
14668 foreach ($literals as $offset => $literal) {
14669 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
14670 $lastLiteral = $literal;
14671 $lastBranchIndex = $i;
14672 $lastBranchOffset = $offset;
14673 $lastLevel = $l;
14674 }
14675 }
14676 }
14677
14678 if ($lastLiteral) {
14679 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
14680
14681 $level = $lastLevel;
14682 $this->revert($level);
14683
14684 $why = $this->decisions->lastReason();
14685
14686 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
14687
14688 if ($level == 0) {
14689 return;
14690 }
14691
14692 continue;
14693 }
14694 }
14695
14696 break;
14697 }
14698 }
14699 }
14700 <?php
14701
14702
14703
14704
14705
14706
14707
14708
14709
14710
14711
14712 namespace Composer\DependencyResolver;
14713
14714
14715
14716
14717 class SolverBugException extends \RuntimeException
14718 {
14719 public function __construct($message)
14720 {
14721 parent::__construct(
14722 $message."\nThis exception was most likely caused by a bug in Composer.\n".
14723 "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"
14724 );
14725 }
14726 }
14727 <?php
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738
14739 namespace Composer\DependencyResolver;
14740
14741 use Composer\Util\IniHelper;
14742
14743
14744
14745
14746 class SolverProblemsException extends \RuntimeException
14747 {
14748 protected $problems;
14749 protected $installedMap;
14750
14751 public function __construct(array $problems, array $installedMap)
14752 {
14753 $this->problems = $problems;
14754 $this->installedMap = $installedMap;
14755
14756 parent::__construct($this->createMessage(), 2);
14757 }
14758
14759 protected function createMessage()
14760 {
14761 $text = "\n";
14762 $hasExtensionProblems = false;
14763 foreach ($this->problems as $i => $problem) {
14764 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
14765
14766 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
14767 $hasExtensionProblems = true;
14768 }
14769 }
14770
14771 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
14772 $text .= "\nPotential 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 <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
14773 }
14774
14775 if ($hasExtensionProblems) {
14776 $text .= $this->createExtensionHint();
14777 }
14778
14779 return $text;
14780 }
14781
14782 public function getProblems()
14783 {
14784 return $this->problems;
14785 }
14786
14787 private function createExtensionHint()
14788 {
14789 $paths = IniHelper::getAll();
14790
14791 if (count($paths) === 1 && empty($paths[0])) {
14792 return '';
14793 }
14794
14795 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
14796 $text .= implode("\n    - ", $paths);
14797 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
14798
14799 return $text;
14800 }
14801
14802 private function hasExtensionProblems(array $reasonSets)
14803 {
14804 foreach ($reasonSets as $reasonSet) {
14805 foreach ($reasonSet as $reason) {
14806 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
14807 return true;
14808 }
14809 }
14810 }
14811
14812 return false;
14813 }
14814 }
14815 <?php
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826
14827 namespace Composer\DependencyResolver;
14828
14829 use Composer\Package\AliasPackage;
14830
14831
14832
14833
14834 class Transaction
14835 {
14836 protected $policy;
14837 protected $pool;
14838 protected $installedMap;
14839 protected $decisions;
14840 protected $transaction;
14841
14842 public function __construct($policy, $pool, $installedMap, $decisions)
14843 {
14844 $this->policy = $policy;
14845 $this->pool = $pool;
14846 $this->installedMap = $installedMap;
14847 $this->decisions = $decisions;
14848 $this->transaction = array();
14849 }
14850
14851 public function getOperations()
14852 {
14853 $installMeansUpdateMap = $this->findUpdates();
14854
14855 $updateMap = array();
14856 $installMap = array();
14857 $uninstallMap = array();
14858
14859 foreach ($this->decisions as $i => $decision) {
14860 $literal = $decision[Decisions::DECISION_LITERAL];
14861 $reason = $decision[Decisions::DECISION_REASON];
14862
14863 $package = $this->pool->literalToPackage($literal);
14864
14865
14866  if (($literal > 0) == isset($this->installedMap[$package->id])) {
14867 continue;
14868 }
14869
14870 if ($literal > 0) {
14871 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
14872 $source = $installMeansUpdateMap[abs($literal)];
14873
14874 $updateMap[$package->id] = array(
14875 'package' => $package,
14876 'source' => $source,
14877 'reason' => $reason,
14878 );
14879
14880
14881  unset($installMeansUpdateMap[abs($literal)]);
14882 $ignoreRemove[$source->id] = true;
14883 } else {
14884 $installMap[$package->id] = array(
14885 'package' => $package,
14886 'reason' => $reason,
14887 );
14888 }
14889 }
14890 }
14891
14892 foreach ($this->decisions as $i => $decision) {
14893 $literal = $decision[Decisions::DECISION_LITERAL];
14894 $reason = $decision[Decisions::DECISION_REASON];
14895 $package = $this->pool->literalToPackage($literal);
14896
14897 if ($literal <= 0 &&
14898 isset($this->installedMap[$package->id]) &&
14899 !isset($ignoreRemove[$package->id])) {
14900 $uninstallMap[$package->id] = array(
14901 'package' => $package,
14902 'reason' => $reason,
14903 );
14904 }
14905 }
14906
14907 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
14908
14909 return $this->transaction;
14910 }
14911
14912 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
14913 {
14914 $queue = array_map(
14915 function ($operation) {
14916 return $operation['package'];
14917 },
14918 $this->findRootPackages($installMap, $updateMap)
14919 );
14920
14921 $visited = array();
14922
14923 while (!empty($queue)) {
14924 $package = array_pop($queue);
14925 $packageId = $package->id;
14926
14927 if (!isset($visited[$packageId])) {
14928 $queue[] = $package;
14929
14930 if ($package instanceof AliasPackage) {
14931 $queue[] = $package->getAliasOf();
14932 } else {
14933 foreach ($package->getRequires() as $link) {
14934 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14935
14936 foreach ($possibleRequires as $require) {
14937 $queue[] = $require;
14938 }
14939 }
14940 }
14941
14942 $visited[$package->id] = true;
14943 } else {
14944 if (isset($installMap[$packageId])) {
14945 $this->install(
14946 $installMap[$packageId]['package'],
14947 $installMap[$packageId]['reason']
14948 );
14949 unset($installMap[$packageId]);
14950 }
14951 if (isset($updateMap[$packageId])) {
14952 $this->update(
14953 $updateMap[$packageId]['source'],
14954 $updateMap[$packageId]['package'],
14955 $updateMap[$packageId]['reason']
14956 );
14957 unset($updateMap[$packageId]);
14958 }
14959 }
14960 }
14961
14962 foreach ($uninstallMap as $uninstall) {
14963 $this->uninstall($uninstall['package'], $uninstall['reason']);
14964 }
14965 }
14966
14967 protected function findRootPackages($installMap, $updateMap)
14968 {
14969 $packages = $installMap + $updateMap;
14970 $roots = $packages;
14971
14972 foreach ($packages as $packageId => $operation) {
14973 $package = $operation['package'];
14974
14975 if (!isset($roots[$packageId])) {
14976 continue;
14977 }
14978
14979 foreach ($package->getRequires() as $link) {
14980 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14981
14982 foreach ($possibleRequires as $require) {
14983 if ($require !== $package) {
14984 unset($roots[$require->id]);
14985 }
14986 }
14987 }
14988 }
14989
14990 return $roots;
14991 }
14992
14993 protected function findUpdates()
14994 {
14995 $installMeansUpdateMap = array();
14996
14997 foreach ($this->decisions as $i => $decision) {
14998 $literal = $decision[Decisions::DECISION_LITERAL];
14999 $package = $this->pool->literalToPackage($literal);
15000
15001 if ($package instanceof AliasPackage) {
15002 continue;
15003 }
15004
15005
15006  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
15007 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
15008
15009 $literals = array($package->id);
15010
15011 foreach ($updates as $update) {
15012 $literals[] = $update->id;
15013 }
15014
15015 foreach ($literals as $updateLiteral) {
15016 if ($updateLiteral !== $literal) {
15017 $installMeansUpdateMap[abs($updateLiteral)] = $package;
15018 }
15019 }
15020 }
15021 }
15022
15023 return $installMeansUpdateMap;
15024 }
15025
15026 protected function install($package, $reason)
15027 {
15028 if ($package instanceof AliasPackage) {
15029 return $this->markAliasInstalled($package, $reason);
15030 }
15031
15032 $this->transaction[] = new Operation\InstallOperation($package, $reason);
15033 }
15034
15035 protected function update($from, $to, $reason)
15036 {
15037 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
15038 }
15039
15040 protected function uninstall($package, $reason)
15041 {
15042 if ($package instanceof AliasPackage) {
15043 return $this->markAliasUninstalled($package, $reason);
15044 }
15045
15046 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
15047 }
15048
15049 protected function markAliasInstalled($package, $reason)
15050 {
15051 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
15052 }
15053
15054 protected function markAliasUninstalled($package, $reason)
15055 {
15056 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
15057 }
15058 }
15059 <?php
15060
15061
15062
15063
15064
15065
15066
15067
15068
15069
15070
15071 namespace Composer\Downloader;
15072
15073 use Composer\Package\PackageInterface;
15074 use Symfony\Component\Finder\Finder;
15075 use Composer\IO\IOInterface;
15076
15077
15078
15079
15080
15081
15082
15083
15084 abstract class ArchiveDownloader extends FileDownloader
15085 {
15086
15087
15088
15089
15090
15091 public function download(PackageInterface $package, $path, $output = true)
15092 {
15093 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
15094 $retries = 3;
15095 while ($retries--) {
15096 $fileName = parent::download($package, $path, $output);
15097
15098 if ($output) {
15099 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
15100 }
15101
15102 try {
15103 $this->filesystem->ensureDirectoryExists($temporaryDir);
15104 try {
15105 $this->extract($fileName, $temporaryDir);
15106 } catch (\Exception $e) {
15107
15108  parent::clearLastCacheWrite($package);
15109 throw $e;
15110 }
15111
15112 $this->filesystem->unlink($fileName);
15113
15114 $contentDir = $this->getFolderContent($temporaryDir);
15115
15116
15117  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
15118 $contentDir = $this->getFolderContent((string) reset($contentDir));
15119 }
15120
15121
15122  foreach ($contentDir as $file) {
15123 $file = (string) $file;
15124 $this->filesystem->rename($file, $path . '/' . basename($file));
15125 }
15126
15127 $this->filesystem->removeDirectory($temporaryDir);
15128 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
15129 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
15130 }
15131 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
15132 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
15133 }
15134 } catch (\Exception $e) {
15135
15136  $this->filesystem->removeDirectory($path);
15137 $this->filesystem->removeDirectory($temporaryDir);
15138
15139
15140  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
15141 $this->io->writeError('');
15142 if ($this->io->isDebug()) {
15143 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
15144 } else {
15145 $this->io->writeError('    Invalid zip file, retrying...');
15146 }
15147 usleep(500000);
15148 continue;
15149 }
15150
15151 throw $e;
15152 }
15153
15154 break;
15155 }
15156 }
15157
15158
15159
15160
15161 protected function getFileName(PackageInterface $package, $path)
15162 {
15163 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
15164 }
15165
15166
15167
15168
15169
15170
15171
15172
15173
15174 abstract protected function extract($file, $path);
15175
15176
15177
15178
15179
15180
15181
15182 private function getFolderContent($dir)
15183 {
15184 $finder = Finder::create()
15185 ->ignoreVCS(false)
15186 ->ignoreDotFiles(false)
15187 ->notName('.DS_Store')
15188 ->depth(0)
15189 ->in($dir);
15190
15191 return iterator_to_array($finder);
15192 }
15193 }
15194 <?php
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206 namespace Composer\Downloader;
15207
15208 use Composer\Package\PackageInterface;
15209
15210
15211
15212
15213
15214
15215 interface ChangeReportInterface
15216 {
15217
15218
15219
15220
15221
15222
15223
15224 public function getLocalChanges(PackageInterface $package, $path);
15225 }
15226 <?php
15227
15228
15229
15230
15231
15232
15233
15234
15235
15236
15237
15238 namespace Composer\Downloader;
15239
15240 use Composer\Package\PackageInterface;
15241 use Composer\IO\IOInterface;
15242 use Composer\Util\Filesystem;
15243
15244
15245
15246
15247
15248
15249 class DownloadManager
15250 {
15251 private $io;
15252 private $preferDist = false;
15253 private $preferSource = false;
15254 private $packagePreferences = array();
15255 private $filesystem;
15256 private $downloaders = array();
15257
15258
15259
15260
15261
15262
15263
15264
15265 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
15266 {
15267 $this->io = $io;
15268 $this->preferSource = $preferSource;
15269 $this->filesystem = $filesystem ?: new Filesystem();
15270 }
15271
15272
15273
15274
15275
15276
15277
15278 public function setPreferSource($preferSource)
15279 {
15280 $this->preferSource = $preferSource;
15281
15282 return $this;
15283 }
15284
15285
15286
15287
15288
15289
15290
15291 public function setPreferDist($preferDist)
15292 {
15293 $this->preferDist = $preferDist;
15294
15295 return $this;
15296 }
15297
15298
15299
15300
15301
15302
15303
15304 public function setPreferences(array $preferences)
15305 {
15306 $this->packagePreferences = $preferences;
15307
15308 return $this;
15309 }
15310
15311
15312
15313
15314
15315
15316
15317
15318 public function setOutputProgress($outputProgress)
15319 {
15320 foreach ($this->downloaders as $downloader) {
15321 $downloader->setOutputProgress($outputProgress);
15322 }
15323
15324 return $this;
15325 }
15326
15327
15328
15329
15330
15331
15332
15333
15334 public function setDownloader($type, DownloaderInterface $downloader)
15335 {
15336 $type = strtolower($type);
15337 $this->downloaders[$type] = $downloader;
15338
15339 return $this;
15340 }
15341
15342
15343
15344
15345
15346
15347
15348
15349 public function getDownloader($type)
15350 {
15351 $type = strtolower($type);
15352 if (!isset($this->downloaders[$type])) {
15353 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
15354 }
15355
15356 return $this->downloaders[$type];
15357 }
15358
15359
15360
15361
15362
15363
15364
15365
15366
15367
15368 public function getDownloaderForInstalledPackage(PackageInterface $package)
15369 {
15370 $installationSource = $package->getInstallationSource();
15371
15372 if ('metapackage' === $package->getType()) {
15373 return;
15374 }
15375
15376 if ('dist' === $installationSource) {
15377 $downloader = $this->getDownloader($package->getDistType());
15378 } elseif ('source' === $installationSource) {
15379 $downloader = $this->getDownloader($package->getSourceType());
15380 } else {
15381 throw new \InvalidArgumentException(
15382 'Package '.$package.' seems not been installed properly'
15383 );
15384 }
15385
15386 if ($installationSource !== $downloader->getInstallationSource()) {
15387 throw new \LogicException(sprintf(
15388 'Downloader "%s" is a %s type downloader and can not be used to download %s for package %s',
15389 get_class($downloader),
15390 $downloader->getInstallationSource(),
15391 $installationSource,
15392 $package
15393 ));
15394 }
15395
15396 return $downloader;
15397 }
15398
15399
15400
15401
15402
15403
15404
15405
15406
15407
15408
15409 public function download(PackageInterface $package, $targetDir, $preferSource = null)
15410 {
15411 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
15412 $sourceType = $package->getSourceType();
15413 $distType = $package->getDistType();
15414
15415 $sources = array();
15416 if ($sourceType) {
15417 $sources[] = 'source';
15418 }
15419 if ($distType) {
15420 $sources[] = 'dist';
15421 }
15422
15423 if (empty($sources)) {
15424 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
15425 }
15426
15427 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
15428 $sources = array_reverse($sources);
15429 }
15430
15431 $this->filesystem->ensureDirectoryExists($targetDir);
15432
15433 foreach ($sources as $i => $source) {
15434 if (isset($e)) {
15435 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
15436 }
15437 $package->setInstallationSource($source);
15438 try {
15439 $downloader = $this->getDownloaderForInstalledPackage($package);
15440 if ($downloader) {
15441 $downloader->download($package, $targetDir);
15442 }
15443 break;
15444 } catch (\RuntimeException $e) {
15445 if ($i === count($sources) - 1) {
15446 throw $e;
15447 }
15448
15449 $this->io->writeError(
15450 '    <warning>Failed to download '.
15451 $package->getPrettyName().
15452 ' from ' . $source . ': '.
15453 $e->getMessage().'</warning>'
15454 );
15455 }
15456 }
15457 }
15458
15459
15460
15461
15462
15463
15464
15465
15466
15467
15468 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
15469 {
15470 $downloader = $this->getDownloaderForInstalledPackage($initial);
15471 if (!$downloader) {
15472 return;
15473 }
15474
15475 $installationSource = $initial->getInstallationSource();
15476
15477 if ('dist' === $installationSource) {
15478 $initialType = $initial->getDistType();
15479 $targetType = $target->getDistType();
15480 } else {
15481 $initialType = $initial->getSourceType();
15482 $targetType = $target->getSourceType();
15483 }
15484
15485
15486  if ($target->isDev() && 'dist' === $installationSource) {
15487 $downloader->remove($initial, $targetDir);
15488 $this->download($target, $targetDir);
15489
15490 return;
15491 }
15492
15493 if ($initialType === $targetType) {
15494 $target->setInstallationSource($installationSource);
15495 try {
15496 $downloader->update($initial, $target, $targetDir);
15497
15498 return;
15499 } catch (\RuntimeException $e) {
15500 if (!$this->io->isInteractive()) {
15501 throw $e;
15502 }
15503 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
15504 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
15505 throw $e;
15506 }
15507 }
15508 }
15509
15510 $downloader->remove($initial, $targetDir);
15511 $this->download($target, $targetDir, 'source' === $installationSource);
15512 }
15513
15514
15515
15516
15517
15518
15519
15520 public function remove(PackageInterface $package, $targetDir)
15521 {
15522 $downloader = $this->getDownloaderForInstalledPackage($package);
15523 if ($downloader) {
15524 $downloader->remove($package, $targetDir);
15525 }
15526 }
15527
15528
15529
15530
15531
15532
15533
15534
15535 protected function resolvePackageInstallPreference(PackageInterface $package)
15536 {
15537 foreach ($this->packagePreferences as $pattern => $preference) {
15538 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
15539 if (preg_match($pattern, $package->getName())) {
15540 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
15541 return 'dist';
15542 }
15543
15544 return 'source';
15545 }
15546 }
15547
15548 return $package->isDev() ? 'source' : 'dist';
15549 }
15550 }
15551 <?php
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561
15562
15563 namespace Composer\Downloader;
15564
15565 use Composer\Package\PackageInterface;
15566
15567
15568
15569
15570
15571
15572
15573 interface DownloaderInterface
15574 {
15575
15576
15577
15578
15579
15580 public function getInstallationSource();
15581
15582
15583
15584
15585
15586
15587
15588 public function download(PackageInterface $package, $path);
15589
15590
15591
15592
15593
15594
15595
15596
15597 public function update(PackageInterface $initial, PackageInterface $target, $path);
15598
15599
15600
15601
15602
15603
15604
15605 public function remove(PackageInterface $package, $path);
15606
15607
15608
15609
15610
15611
15612
15613 public function setOutputProgress($outputProgress);
15614 }
15615 <?php
15616
15617
15618
15619
15620
15621
15622
15623
15624
15625
15626
15627 namespace Composer\Downloader;
15628
15629 use Composer\Package\PackageInterface;
15630
15631
15632
15633
15634
15635
15636 interface DvcsDownloaderInterface
15637 {
15638
15639
15640
15641
15642
15643
15644
15645 public function getUnpushedChanges(PackageInterface $package, $path);
15646 }
15647 <?php
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657
15658
15659 namespace Composer\Downloader;
15660
15661 use Composer\Config;
15662 use Composer\Cache;
15663 use Composer\Factory;
15664 use Composer\IO\IOInterface;
15665 use Composer\IO\NullIO;
15666 use Composer\Package\Comparer\Comparer;
15667 use Composer\Package\PackageInterface;
15668 use Composer\Package\Version\VersionParser;
15669 use Composer\Plugin\PluginEvents;
15670 use Composer\Plugin\PreFileDownloadEvent;
15671 use Composer\EventDispatcher\EventDispatcher;
15672 use Composer\Util\Filesystem;
15673 use Composer\Util\RemoteFilesystem;
15674 use Composer\Util\Url as UrlUtil;
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684 class FileDownloader implements DownloaderInterface, ChangeReportInterface
15685 {
15686 protected $io;
15687 protected $config;
15688 protected $rfs;
15689 protected $filesystem;
15690 protected $cache;
15691 protected $outputProgress = true;
15692 private $lastCacheWrites = array();
15693 private $eventDispatcher;
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
15706 {
15707 $this->io = $io;
15708 $this->config = $config;
15709 $this->eventDispatcher = $eventDispatcher;
15710 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
15711 $this->filesystem = $filesystem ?: new Filesystem();
15712 $this->cache = $cache;
15713
15714 if ($this->cache && $this->cache->gcIsNecessary()) {
15715 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
15716 }
15717 }
15718
15719
15720
15721
15722 public function getInstallationSource()
15723 {
15724 return 'dist';
15725 }
15726
15727
15728
15729
15730 public function download(PackageInterface $package, $path, $output = true)
15731 {
15732 if (!$package->getDistUrl()) {
15733 throw new \InvalidArgumentException('The given package is missing url information');
15734 }
15735
15736 if ($output) {
15737 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
15738 }
15739
15740 $urls = $package->getDistUrls();
15741 while ($url = array_shift($urls)) {
15742 try {
15743 $fileName = $this->doDownload($package, $path, $url);
15744 break;
15745 } catch (\Exception $e) {
15746 if ($this->io->isDebug()) {
15747 $this->io->writeError('');
15748 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
15749 } elseif (count($urls)) {
15750 $this->io->writeError('');
15751 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
15752 }
15753
15754 if (!count($urls)) {
15755 throw $e;
15756 }
15757 }
15758 }
15759
15760 if ($output) {
15761 $this->io->writeError('');
15762 }
15763
15764 return $fileName;
15765 }
15766
15767 protected function doDownload(PackageInterface $package, $path, $url)
15768 {
15769 $this->filesystem->emptyDirectory($path);
15770
15771 $fileName = $this->getFileName($package, $path);
15772
15773 $processedUrl = $this->processUrl($package, $url);
15774 $origin = RemoteFilesystem::getOrigin($processedUrl);
15775
15776 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
15777 if ($this->eventDispatcher) {
15778 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
15779 }
15780 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
15781
15782 try {
15783 $checksum = $package->getDistSha1Checksum();
15784 $cacheKey = $this->getCacheKey($package, $processedUrl);
15785
15786
15787  if ($this->cache && (!$checksum || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) {
15788 $this->io->writeError('Loading from cache', false);
15789 } else {
15790
15791  if (!$this->outputProgress) {
15792 $this->io->writeError('Downloading', false);
15793 }
15794
15795
15796  $retries = 3;
15797 while ($retries--) {
15798 try {
15799 $rfs->copy($origin, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
15800 break;
15801 } catch (TransportException $e) {
15802
15803  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
15804 throw $e;
15805 }
15806 $this->io->writeError('');
15807 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
15808 usleep(500000);
15809 }
15810 }
15811
15812 if (!$this->outputProgress) {
15813 $this->io->writeError(' (<comment>100%</comment>)', false);
15814 }
15815
15816 if ($this->cache) {
15817 $this->lastCacheWrites[$package->getName()] = $cacheKey;
15818 $this->cache->copyFrom($cacheKey, $fileName);
15819 }
15820 }
15821
15822 if (!file_exists($fileName)) {
15823 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
15824 .' directory is writable and you have internet connectivity');
15825 }
15826
15827 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
15828 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
15829 }
15830 } catch (\Exception $e) {
15831
15832  $this->filesystem->removeDirectory($path);
15833 $this->clearLastCacheWrite($package);
15834 throw $e;
15835 }
15836
15837 return $fileName;
15838 }
15839
15840
15841
15842
15843 public function setOutputProgress($outputProgress)
15844 {
15845 $this->outputProgress = $outputProgress;
15846
15847 return $this;
15848 }
15849
15850 protected function clearLastCacheWrite(PackageInterface $package)
15851 {
15852 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
15853 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
15854 unset($this->lastCacheWrites[$package->getName()]);
15855 }
15856 }
15857
15858
15859
15860
15861 public function update(PackageInterface $initial, PackageInterface $target, $path)
15862 {
15863 $name = $target->getName();
15864 $from = $initial->getFullPrettyVersion();
15865 $to = $target->getFullPrettyVersion();
15866
15867 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
15868 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
15869
15870 $this->remove($initial, $path, false);
15871 $this->download($target, $path, false);
15872
15873 $this->io->writeError('');
15874 }
15875
15876
15877
15878
15879 public function remove(PackageInterface $package, $path, $output = true)
15880 {
15881 if ($output) {
15882 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15883 }
15884 if (!$this->filesystem->removeDirectory($path)) {
15885 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
15886 }
15887 }
15888
15889
15890
15891
15892
15893
15894
15895
15896 protected function getFileName(PackageInterface $package, $path)
15897 {
15898 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15899 }
15900
15901
15902
15903
15904
15905
15906
15907
15908
15909 protected function processUrl(PackageInterface $package, $url)
15910 {
15911 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
15912 throw new \RuntimeException('You must enable the openssl extension to download files via https');
15913 }
15914
15915 if ($package->getDistReference()) {
15916 $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
15917 }
15918
15919 return $url;
15920 }
15921
15922 private function getCacheKey(PackageInterface $package, $processedUrl)
15923 {
15924
15925  
15926  
15927  
15928  $cacheKey = sha1($processedUrl);
15929
15930 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
15931 }
15932
15933
15934
15935
15936
15937 public function getLocalChanges(PackageInterface $package, $targetDir)
15938 {
15939 $prevIO = $this->io;
15940 $prevProgress = $this->outputProgress;
15941
15942 $this->io = new NullIO;
15943 $this->io->loadConfiguration($this->config);
15944 $this->outputProgress = false;
15945 $e = null;
15946
15947 try {
15948 $this->download($package, $targetDir.'_compare', false);
15949
15950 $comparer = new Comparer();
15951 $comparer->setSource($targetDir.'_compare');
15952 $comparer->setUpdate($targetDir);
15953 $comparer->doCompare();
15954 $output = $comparer->getChanged(true, true);
15955 $this->filesystem->removeDirectory($targetDir.'_compare');
15956 } catch (\Exception $e) {
15957 }
15958
15959 $this->io = $prevIO;
15960 $this->outputProgress = $prevProgress;
15961
15962 if ($e) {
15963 throw $e;
15964 }
15965
15966 return trim($output);
15967 }
15968 }
15969 <?php
15970
15971
15972
15973
15974
15975
15976
15977
15978
15979
15980
15981 namespace Composer\Downloader;
15982
15983
15984
15985
15986
15987
15988 class FilesystemException extends \Exception
15989 {
15990 public function __construct($message = '', $code = 0, \Exception $previous = null)
15991 {
15992 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
15993 }
15994 }
15995 <?php
15996
15997
15998
15999
16000
16001
16002
16003
16004
16005
16006
16007 namespace Composer\Downloader;
16008
16009 use Composer\Package\PackageInterface;
16010 use Composer\Util\ProcessExecutor;
16011
16012
16013
16014
16015 class FossilDownloader extends VcsDownloader
16016 {
16017
16018
16019
16020 public function doDownload(PackageInterface $package, $path, $url)
16021 {
16022
16023  $this->config->prohibitUrlByConfig($url, $this->io);
16024
16025 $url = ProcessExecutor::escape($url);
16026 $ref = ProcessExecutor::escape($package->getSourceReference());
16027 $repoFile = $path . '.fossil';
16028 $this->io->writeError("Cloning ".$package->getSourceReference());
16029 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
16030 if (0 !== $this->process->execute($command, $ignoredOutput)) {
16031 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16032 }
16033 $command = sprintf('fossil open %s --nested', ProcessExecutor::escape($repoFile));
16034 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16035 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16036 }
16037 $command = sprintf('fossil update %s', $ref);
16038 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16039 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16040 }
16041 }
16042
16043
16044
16045
16046 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16047 {
16048
16049  $this->config->prohibitUrlByConfig($url, $this->io);
16050
16051 $url = ProcessExecutor::escape($url);
16052 $ref = ProcessExecutor::escape($target->getSourceReference());
16053 $this->io->writeError(" Updating to ".$target->getSourceReference());
16054
16055 if (!$this->hasMetadataRepository($path)) {
16056 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16057 }
16058
16059 $command = sprintf('fossil pull && fossil up %s', $ref);
16060 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16061 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16062 }
16063 }
16064
16065
16066
16067
16068 public function getLocalChanges(PackageInterface $package, $path)
16069 {
16070 if (!$this->hasMetadataRepository($path)) {
16071 return null;
16072 }
16073
16074 $this->process->execute('fossil changes', $output, realpath($path));
16075
16076 return trim($output) ?: null;
16077 }
16078
16079
16080
16081
16082 protected function getCommitLogs($fromReference, $toReference, $path)
16083 {
16084 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', ProcessExecutor::escape($toReference));
16085
16086 if (0 !== $this->process->execute($command, $output, realpath($path))) {
16087 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16088 }
16089
16090 $log = '';
16091 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
16092
16093 foreach ($this->process->splitLines($output) as $line) {
16094 if (preg_match($match, $line)) {
16095 break;
16096 }
16097 $log .= $line;
16098 }
16099
16100 return $log;
16101 }
16102
16103
16104
16105
16106 protected function hasMetadataRepository($path)
16107 {
16108 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
16109 }
16110 }
16111 <?php
16112
16113
16114
16115
16116
16117
16118
16119
16120
16121
16122
16123 namespace Composer\Downloader;
16124
16125 use Composer\Config;
16126 use Composer\IO\IOInterface;
16127 use Composer\Package\PackageInterface;
16128 use Composer\Util\Filesystem;
16129 use Composer\Util\Git as GitUtil;
16130 use Composer\Util\Platform;
16131 use Composer\Util\ProcessExecutor;
16132 use Composer\Cache;
16133
16134
16135
16136
16137 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
16138 {
16139 private $hasStashedChanges = false;
16140 private $hasDiscardedChanges = false;
16141 private $gitUtil;
16142
16143 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
16144 {
16145 parent::__construct($io, $config, $process, $fs);
16146 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
16147 }
16148
16149
16150
16151
16152 public function doDownload(PackageInterface $package, $path, $url)
16153 {
16154 GitUtil::cleanEnv();
16155 $path = $this->normalizePath($path);
16156 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
16157 $ref = $package->getSourceReference();
16158 $flag = Platform::isWindows() ? '/D ' : '';
16159
16160
16161  $gitVersion = $this->gitUtil->getVersion();
16162 $msg = "Cloning ".$this->getShortHash($ref);
16163
16164 $command = 'git clone --no-checkout %url% %path% && cd '.$flag.'%path% && git remote add composer %url% && git fetch composer && git remote set-url origin %sanitizedUrl% && git remote set-url composer %sanitizedUrl%';
16165 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
16166 $this->io->writeError('', true, IOInterface::DEBUG);
16167 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
16168 try {
16169 if (!$this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref)) {
16170 $this->io->writeError('<error>Failed to update '.$url.' in cache, package installation for '.$package->getPrettyName().' might fail.</error>');
16171 }
16172 if (is_dir($cachePath)) {
16173 $command =
16174 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
16175 . '&& cd '.$flag.'%path% '
16176 . '&& git remote set-url origin %sanitizedUrl% && git remote add composer %sanitizedUrl%';
16177 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
16178 }
16179 } catch (\RuntimeException $e) {
16180 if (0 === strpos(get_class($e), 'PHPUnit')) {
16181 throw $e;
16182 }
16183 }
16184 }
16185 $this->io->writeError($msg);
16186
16187 $commandCallable = function ($url) use ($path, $command, $cachePath) {
16188 return str_replace(
16189 array('%url%', '%path%', '%cachePath%', '%sanitizedUrl%'),
16190 array(
16191 ProcessExecutor::escape($url),
16192 ProcessExecutor::escape($path),
16193 ProcessExecutor::escape($cachePath),
16194 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url)),
16195 ),
16196 $command
16197 );
16198 };
16199
16200 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
16201 if ($url !== $package->getSourceUrl()) {
16202 $this->updateOriginUrl($path, $package->getSourceUrl());
16203 } else {
16204 $this->setPushUrl($path, $url);
16205 }
16206
16207 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
16208 if ($package->getDistReference() === $package->getSourceReference()) {
16209 $package->setDistReference($newRef);
16210 }
16211 $package->setSourceReference($newRef);
16212 }
16213 }
16214
16215
16216
16217
16218 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16219 {
16220 GitUtil::cleanEnv();
16221 if (!$this->hasMetadataRepository($path)) {
16222 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16223 }
16224
16225 $updateOriginUrl = false;
16226 if (
16227 0 === $this->process->execute('git remote -v', $output, $path)
16228 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
16229 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
16230 ) {
16231 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
16232 $updateOriginUrl = true;
16233 }
16234 }
16235
16236 $ref = $target->getSourceReference();
16237 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
16238 $command = '(git remote set-url composer %s && git rev-parse --quiet --verify %s || (git fetch composer && git fetch --tags composer)) && git remote set-url composer %s';
16239
16240 $commandCallable = function ($url) use ($command, $ref) {
16241 return sprintf(
16242 $command,
16243 ProcessExecutor::escape($url),
16244 ProcessExecutor::escape($ref.'^{commit}'),
16245 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url))
16246 );
16247 };
16248
16249 $this->gitUtil->runCommand($commandCallable, $url, $path);
16250 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
16251 if ($target->getDistReference() === $target->getSourceReference()) {
16252 $target->setDistReference($newRef);
16253 }
16254 $target->setSourceReference($newRef);
16255 }
16256
16257 if ($updateOriginUrl) {
16258 $this->updateOriginUrl($path, $target->getSourceUrl());
16259 }
16260 }
16261
16262
16263
16264
16265 public function getLocalChanges(PackageInterface $package, $path)
16266 {
16267 GitUtil::cleanEnv();
16268 if (!$this->hasMetadataRepository($path)) {
16269 return;
16270 }
16271
16272 $command = 'git status --porcelain --untracked-files=no';
16273 if (0 !== $this->process->execute($command, $output, $path)) {
16274 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16275 }
16276
16277 return trim($output) ?: null;
16278 }
16279
16280 public function getUnpushedChanges(PackageInterface $package, $path)
16281 {
16282 GitUtil::cleanEnv();
16283 $path = $this->normalizePath($path);
16284 if (!$this->hasMetadataRepository($path)) {
16285 return;
16286 }
16287
16288 $command = 'git show-ref --head -d';
16289 if (0 !== $this->process->execute($command, $output, $path)) {
16290 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16291 }
16292
16293 $refs = trim($output);
16294 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
16295
16296  return;
16297 }
16298
16299 $headRef = $match[1];
16300 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
16301
16302  return;
16303 }
16304
16305
16306  $branch = $matches[1][0];
16307 $unpushedChanges = null;
16308
16309
16310  for ($i = 0; $i <= 1; $i++) {
16311
16312  foreach ($matches[1] as $candidate) {
16313 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
16314 $branch = $candidate;
16315 $remoteBranch = $match[1];
16316 break;
16317 }
16318 }
16319
16320
16321  
16322  
16323  if (!isset($remoteBranch)) {
16324 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
16325 } else {
16326 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
16327 if (0 !== $this->process->execute($command, $output, $path)) {
16328 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16329 }
16330
16331 $unpushedChanges = trim($output) ?: null;
16332 }
16333
16334
16335  
16336  if ($unpushedChanges && $i === 0) {
16337 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
16338 }
16339
16340
16341  if (!$unpushedChanges) {
16342 break;
16343 }
16344 }
16345
16346 return $unpushedChanges;
16347 }
16348
16349
16350
16351
16352 protected function cleanChanges(PackageInterface $package, $path, $update)
16353 {
16354 GitUtil::cleanEnv();
16355 $path = $this->normalizePath($path);
16356
16357 $unpushed = $this->getUnpushedChanges($package, $path);
16358 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
16359 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
16360 }
16361
16362 if (!$changes = $this->getLocalChanges($package, $path)) {
16363 return;
16364 }
16365
16366 if (!$this->io->isInteractive()) {
16367 $discardChanges = $this->config->get('discard-changes');
16368 if (true === $discardChanges) {
16369 return $this->discardChanges($path);
16370 }
16371 if ('stash' === $discardChanges) {
16372 if (!$update) {
16373 return parent::cleanChanges($package, $path, $update);
16374 }
16375
16376 return $this->stashChanges($path);
16377 }
16378
16379 return parent::cleanChanges($package, $path, $update);
16380 }
16381
16382 $changes = array_map(function ($elem) {
16383 return '    '.$elem;
16384 }, preg_split('{\s*\r?\n\s*}', $changes));
16385 $this->io->writeError('    <error>The package has modified files:</error>');
16386 $this->io->writeError(array_slice($changes, 0, 10));
16387 if (count($changes) > 10) {
16388 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
16389 }
16390
16391 while (true) {
16392 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
16393 case 'y':
16394 $this->discardChanges($path);
16395 break 2;
16396
16397 case 's':
16398 if (!$update) {
16399 goto help;
16400 }
16401
16402 $this->stashChanges($path);
16403 break 2;
16404
16405 case 'n':
16406 throw new \RuntimeException('Update aborted');
16407
16408 case 'v':
16409 $this->io->writeError($changes);
16410 break;
16411
16412 case 'd':
16413 $this->viewDiff($path);
16414 break;
16415
16416 case '?':
16417 default:
16418 help:
16419 $this->io->writeError(array(
16420 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
16421 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
16422 '    v - view modified files',
16423 '    d - view local modifications (diff)',
16424 ));
16425 if ($update) {
16426 $this->io->writeError('    s - stash changes and try to reapply them after the update');
16427 }
16428 $this->io->writeError('    ? - print help');
16429 break;
16430 }
16431 }
16432 }
16433
16434
16435
16436
16437 protected function reapplyChanges($path)
16438 {
16439 $path = $this->normalizePath($path);
16440 if ($this->hasStashedChanges) {
16441 $this->hasStashedChanges = false;
16442 $this->io->writeError('    <info>Re-applying stashed changes</info>');
16443 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
16444 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
16445 }
16446 }
16447
16448 $this->hasDiscardedChanges = false;
16449 }
16450
16451
16452
16453
16454
16455
16456
16457
16458
16459
16460
16461 protected function updateToCommit($path, $reference, $branch, $date)
16462 {
16463 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
16464
16465
16466  
16467  
16468  
16469  
16470  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
16471 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
16472
16473 $branches = null;
16474 if (0 === $this->process->execute('git branch -r', $output, $path)) {
16475 $branches = $output;
16476 }
16477
16478
16479  $gitRef = $reference;
16480 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
16481 && $branches
16482 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
16483 ) {
16484 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
16485 if (0 === $this->process->execute($command, $output, $path)) {
16486 return;
16487 }
16488 }
16489
16490
16491  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
16492
16493  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
16494 $branch = 'v' . $branch;
16495 }
16496
16497 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
16498 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
16499 if (0 === $this->process->execute($command, $output, $path)
16500 || 0 === $this->process->execute($fallbackCommand, $output, $path)
16501 ) {
16502 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
16503 if (0 === $this->process->execute($command, $output, $path)) {
16504 return;
16505 }
16506 }
16507 }
16508
16509 $command = sprintf($template, ProcessExecutor::escape($gitRef));
16510 if (0 === $this->process->execute($command, $output, $path)) {
16511 return;
16512 }
16513
16514
16515  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
16516 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
16517 }
16518
16519 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
16520 }
16521
16522 protected function updateOriginUrl($path, $url)
16523 {
16524 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
16525 $this->setPushUrl($path, $url);
16526 }
16527
16528 protected function setPushUrl($path, $url)
16529 {
16530
16531  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
16532 $protocols = $this->config->get('github-protocols');
16533 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
16534 if (!in_array('ssh', $protocols, true)) {
16535 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
16536 }
16537 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
16538 $this->process->execute($cmd, $ignoredOutput, $path);
16539 }
16540 }
16541
16542
16543
16544
16545 protected function getCommitLogs($fromReference, $toReference, $path)
16546 {
16547 $path = $this->normalizePath($path);
16548 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
16549
16550 if (0 !== $this->process->execute($command, $output, $path)) {
16551 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16552 }
16553
16554 return $output;
16555 }
16556
16557
16558
16559
16560
16561 protected function discardChanges($path)
16562 {
16563 $path = $this->normalizePath($path);
16564 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
16565 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16566 }
16567
16568 $this->hasDiscardedChanges = true;
16569 }
16570
16571
16572
16573
16574
16575 protected function stashChanges($path)
16576 {
16577 $path = $this->normalizePath($path);
16578 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
16579 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
16580 }
16581
16582 $this->hasStashedChanges = true;
16583 }
16584
16585
16586
16587
16588
16589 protected function viewDiff($path)
16590 {
16591 $path = $this->normalizePath($path);
16592 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
16593 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
16594 }
16595
16596 $this->io->writeError($output);
16597 }
16598
16599 protected function normalizePath($path)
16600 {
16601 if (Platform::isWindows() && strlen($path) > 0) {
16602 $basePath = $path;
16603 $removed = array();
16604
16605 while (!is_dir($basePath) && $basePath !== '\\') {
16606 array_unshift($removed, basename($basePath));
16607 $basePath = dirname($basePath);
16608 }
16609
16610 if ($basePath === '\\') {
16611 return $path;
16612 }
16613
16614 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
16615 }
16616
16617 return $path;
16618 }
16619
16620
16621
16622
16623 protected function hasMetadataRepository($path)
16624 {
16625 $path = $this->normalizePath($path);
16626
16627 return is_dir($path.'/.git');
16628 }
16629
16630 protected function getShortHash($reference)
16631 {
16632 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
16633 return substr($reference, 0, 10);
16634 }
16635
16636 return $reference;
16637 }
16638 }
16639 <?php
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650
16651 namespace Composer\Downloader;
16652
16653 use Composer\Config;
16654 use Composer\Cache;
16655 use Composer\EventDispatcher\EventDispatcher;
16656 use Composer\Package\PackageInterface;
16657 use Composer\Util\Platform;
16658 use Composer\Util\ProcessExecutor;
16659 use Composer\Util\RemoteFilesystem;
16660 use Composer\IO\IOInterface;
16661
16662
16663
16664
16665
16666
16667 class GzipDownloader extends ArchiveDownloader
16668 {
16669 protected $process;
16670
16671 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16672 {
16673 $this->process = $process ?: new ProcessExecutor($io);
16674 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16675 }
16676
16677 protected function extract($file, $path)
16678 {
16679 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
16680
16681
16682  if (!Platform::isWindows()) {
16683 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
16684
16685 if (0 === $this->process->execute($command, $ignoredOutput)) {
16686 return;
16687 }
16688
16689 if (extension_loaded('zlib')) {
16690
16691  $this->extractUsingExt($file, $targetFilepath);
16692
16693 return;
16694 }
16695
16696 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16697 throw new \RuntimeException($processError);
16698 }
16699
16700
16701  $this->extractUsingExt($file, $targetFilepath);
16702 }
16703
16704
16705
16706
16707 protected function getFileName(PackageInterface $package, $path)
16708 {
16709 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
16710 }
16711
16712 private function extractUsingExt($file, $targetFilepath)
16713 {
16714 $archiveFile = gzopen($file, 'rb');
16715 $targetFile = fopen($targetFilepath, 'wb');
16716 while ($string = gzread($archiveFile, 4096)) {
16717 fwrite($targetFile, $string, Platform::strlen($string));
16718 }
16719 gzclose($archiveFile);
16720 fclose($targetFile);
16721 }
16722 }
16723 <?php
16724
16725
16726
16727
16728
16729
16730
16731
16732
16733
16734
16735 namespace Composer\Downloader;
16736
16737 use Composer\Package\PackageInterface;
16738 use Composer\Util\ProcessExecutor;
16739 use Composer\Util\Hg as HgUtils;
16740
16741
16742
16743
16744 class HgDownloader extends VcsDownloader
16745 {
16746
16747
16748
16749 public function doDownload(PackageInterface $package, $path, $url)
16750 {
16751 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
16752
16753 $cloneCommand = function ($url) use ($path) {
16754 return sprintf('hg clone %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
16755 };
16756
16757 $hgUtils->runCommand($cloneCommand, $url, $path);
16758
16759 $ref = ProcessExecutor::escape($package->getSourceReference());
16760 $command = sprintf('hg up %s', $ref);
16761 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16762 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16763 }
16764 }
16765
16766
16767
16768
16769 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16770 {
16771 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
16772
16773 $ref = $target->getSourceReference();
16774 $this->io->writeError(" Updating to ".$target->getSourceReference());
16775
16776 if (!$this->hasMetadataRepository($path)) {
16777 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16778 }
16779
16780 $command = function ($url) use ($ref) {
16781 return sprintf('hg pull %s && hg up %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
16782 };
16783
16784 $hgUtils->runCommand($command, $url, $path);
16785 }
16786
16787
16788
16789
16790 public function getLocalChanges(PackageInterface $package, $path)
16791 {
16792 if (!is_dir($path.'/.hg')) {
16793 return null;
16794 }
16795
16796 $this->process->execute('hg st', $output, realpath($path));
16797
16798 return trim($output) ?: null;
16799 }
16800
16801
16802
16803
16804 protected function getCommitLogs($fromReference, $toReference, $path)
16805 {
16806 $command = sprintf('hg log -r %s:%s --style compact', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
16807
16808 if (0 !== $this->process->execute($command, $output, realpath($path))) {
16809 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16810 }
16811
16812 return $output;
16813 }
16814
16815
16816
16817
16818 protected function hasMetadataRepository($path)
16819 {
16820 return is_dir($path . '/.hg');
16821 }
16822 }
16823 <?php
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834
16835 namespace Composer\Downloader;
16836
16837 use Composer\Package\Archiver\ArchivableFilesFinder;
16838 use Composer\Package\Dumper\ArrayDumper;
16839 use Composer\Package\PackageInterface;
16840 use Composer\Package\Version\VersionGuesser;
16841 use Composer\Package\Version\VersionParser;
16842 use Composer\Util\Platform;
16843 use Composer\Util\ProcessExecutor;
16844 use Composer\Util\Filesystem as ComposerFilesystem;
16845 use Symfony\Component\Filesystem\Exception\IOException;
16846 use Symfony\Component\Filesystem\Filesystem;
16847
16848
16849
16850
16851
16852
16853
16854 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
16855 {
16856 const STRATEGY_SYMLINK = 10;
16857 const STRATEGY_MIRROR = 20;
16858
16859
16860
16861
16862 public function download(PackageInterface $package, $path, $output = true)
16863 {
16864 $url = $package->getDistUrl();
16865 $realUrl = realpath($url);
16866 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
16867 throw new \RuntimeException(sprintf(
16868 'Source path "%s" is not found for package %s',
16869 $url,
16870 $package->getName()
16871 ));
16872 }
16873
16874 if (realpath($path) === $realUrl) {
16875 if ($output) {
16876 $this->io->writeError(sprintf(
16877 '  - Installing <info>%s</info> (<comment>%s</comment>): Source already present',
16878 $package->getName(),
16879 $package->getFullPrettyVersion()
16880 ));
16881 }
16882
16883 return;
16884 }
16885
16886 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
16887
16888  
16889  
16890  
16891  throw new \RuntimeException(sprintf(
16892 'Package %s cannot install to "%s" inside its source at "%s"',
16893 $package->getName(),
16894 realpath($path),
16895 $realUrl
16896 ));
16897 }
16898
16899
16900  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
16901
16902
16903  $currentStrategy = self::STRATEGY_SYMLINK;
16904 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
16905
16906 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
16907 if ($mirrorPathRepos) {
16908 $currentStrategy = self::STRATEGY_MIRROR;
16909 }
16910
16911 if (true === $transportOptions['symlink']) {
16912 $currentStrategy = self::STRATEGY_SYMLINK;
16913 $allowedStrategies = array(self::STRATEGY_SYMLINK);
16914 } elseif (false === $transportOptions['symlink']) {
16915 $currentStrategy = self::STRATEGY_MIRROR;
16916 $allowedStrategies = array(self::STRATEGY_MIRROR);
16917 }
16918
16919
16920  if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
16921 $currentStrategy = self::STRATEGY_MIRROR;
16922 $allowedStrategies = array(self::STRATEGY_MIRROR);
16923 }
16924
16925 $fileSystem = new Filesystem();
16926 $this->filesystem->removeDirectory($path);
16927
16928 if ($output) {
16929 $this->io->writeError(sprintf(
16930 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
16931 $package->getName(),
16932 $package->getFullPrettyVersion()
16933 ), false);
16934 }
16935
16936 $isFallback = false;
16937 if (self::STRATEGY_SYMLINK == $currentStrategy) {
16938 try {
16939 if (Platform::isWindows()) {
16940
16941  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
16942 $this->filesystem->junction($realUrl, $path);
16943 } else {
16944 $absolutePath = $path;
16945 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
16946 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
16947 }
16948 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
16949 $path = rtrim($path, "/");
16950 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
16951 $fileSystem->symlink($shortestPath, $path);
16952 }
16953 } catch (IOException $e) {
16954 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
16955 $this->io->writeError('');
16956 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
16957 $currentStrategy = self::STRATEGY_MIRROR;
16958 $isFallback = true;
16959 } else {
16960 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
16961 }
16962 }
16963 }
16964
16965
16966  if (self::STRATEGY_MIRROR == $currentStrategy) {
16967 $fs = new ComposerFilesystem();
16968 $realUrl = $fs->normalizePath($realUrl);
16969
16970 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
16971 $iterator = new ArchivableFilesFinder($realUrl, array());
16972 $fileSystem->mirror($realUrl, $path, $iterator);
16973 }
16974
16975 $this->io->writeError('');
16976 }
16977
16978
16979
16980
16981 public function remove(PackageInterface $package, $path, $output = true)
16982 {
16983 $realUrl = realpath($package->getDistUrl());
16984
16985 if (realpath($path) === $realUrl) {
16986 if ($output) {
16987 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>), source is still present in $path");
16988 }
16989
16990 return;
16991 }
16992
16993
16994
16995
16996
16997
16998 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
16999 if ($output) {
17000 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
17001 }
17002 if (!$this->filesystem->removeJunction($path)) {
17003 $this->io->writeError("    <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>");
17004 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
17005 }
17006 } else {
17007 parent::remove($package, $path, $output);
17008 }
17009 }
17010
17011
17012
17013
17014 public function getVcsReference(PackageInterface $package, $path)
17015 {
17016 $parser = new VersionParser;
17017 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
17018 $dumper = new ArrayDumper;
17019
17020 $packageConfig = $dumper->dump($package);
17021 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
17022 return $packageVersion['commit'];
17023 }
17024 }
17025
17026
17027
17028
17029
17030
17031
17032
17033
17034
17035
17036
17037
17038
17039 private function safeJunctions()
17040 {
17041
17042  return function_exists('proc_open') &&
17043 (PHP_WINDOWS_VERSION_MAJOR > 6 ||
17044 (PHP_WINDOWS_VERSION_MAJOR === 6 && PHP_WINDOWS_VERSION_MINOR >= 1));
17045 }
17046 }
17047 <?php
17048
17049
17050
17051
17052
17053
17054
17055
17056
17057
17058
17059 namespace Composer\Downloader;
17060
17061 use Composer\Util\Filesystem;
17062
17063
17064
17065
17066
17067
17068
17069
17070
17071
17072 class PearPackageExtractor
17073 {
17074 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
17075
17076 private $filesystem;
17077 private $file;
17078
17079 public function __construct($file)
17080 {
17081 if (!is_file($file)) {
17082 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
17083 }
17084
17085 $this->filesystem = new Filesystem();
17086 $this->file = $file;
17087 }
17088
17089
17090
17091
17092
17093
17094
17095
17096
17097
17098 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
17099 {
17100 $extractionPath = $target.'/tarball';
17101
17102 try {
17103 $archive = new \PharData($this->file);
17104 $archive->extractTo($extractionPath, null, true);
17105
17106 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
17107 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
17108 }
17109
17110 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
17111 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
17112 $this->filesystem->removeDirectory($extractionPath);
17113 } catch (\Exception $exception) {
17114 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
17115 }
17116 }
17117
17118
17119
17120
17121
17122
17123
17124
17125
17126
17127 private function copyFiles($files, $source, $target, $roles, $vars)
17128 {
17129 foreach ($files as $file) {
17130 $from = $this->combine($source, $file['from']);
17131 $to = $this->combine($target, $roles[$file['role']]);
17132 $to = $this->combine($to, $file['to']);
17133 $tasks = $file['tasks'];
17134 $this->copyFile($from, $to, $tasks, $vars);
17135 }
17136 }
17137
17138 private function copyFile($from, $to, $tasks, $vars)
17139 {
17140 if (!is_file($from)) {
17141 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
17142 }
17143
17144 $this->filesystem->ensureDirectoryExists(dirname($to));
17145
17146 if (0 == count($tasks)) {
17147 $copied = copy($from, $to);
17148 } else {
17149 $content = file_get_contents($from);
17150 $replacements = array();
17151 foreach ($tasks as $task) {
17152 $pattern = $task['from'];
17153 $varName = $task['to'];
17154 if (isset($vars[$varName])) {
17155 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
17156 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
17157 } else {
17158 $replacements[$pattern] = $vars[$varName];
17159 }
17160 }
17161 }
17162 $content = strtr($content, $replacements);
17163
17164 $copied = file_put_contents($to, $content);
17165 }
17166
17167 if (false === $copied) {
17168 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
17169 }
17170 }
17171
17172
17173
17174
17175
17176
17177
17178
17179
17180
17181
17182 private function buildCopyActions($source, array $roles, $vars)
17183 {
17184
17185 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
17186 if (false === $package) {
17187 throw new \RuntimeException('Package definition file is not valid.');
17188 }
17189
17190 $packageSchemaVersion = $package['version'];
17191 if ('1.0' == $packageSchemaVersion) {
17192 $children = $package->release->filelist->children();
17193 $packageName = (string) $package->name;
17194 $packageVersion = (string) $package->release->version;
17195 $sourceDir = $packageName . '-' . $packageVersion;
17196 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
17197 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
17198 $children = $package->contents->children();
17199 $packageName = (string) $package->name;
17200 $packageVersion = (string) $package->version->release;
17201 $sourceDir = $packageName . '-' . $packageVersion;
17202 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
17203
17204 $namespaces = $package->getNamespaces();
17205 $package->registerXPathNamespace('ns', $namespaces['']);
17206 $releaseNodes = $package->xpath('ns:phprelease');
17207 $this->applyRelease($result, $releaseNodes, $vars);
17208 } else {
17209 throw new \RuntimeException('Unsupported schema version of package definition file.');
17210 }
17211
17212 return $result;
17213 }
17214
17215 private function applyRelease(&$actions, $releaseNodes, $vars)
17216 {
17217 foreach ($releaseNodes as $releaseNode) {
17218 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
17219 if ($requiredOs && $vars['os'] != $requiredOs) {
17220 continue;
17221 }
17222
17223 if ($releaseNode->filelist) {
17224 foreach ($releaseNode->filelist->children() as $action) {
17225 if ('install' == $action->getName()) {
17226 $name = (string) $action['name'];
17227 $as = (string) $action['as'];
17228 if (isset($actions[$name])) {
17229 $actions[$name]['to'] = $as;
17230 }
17231 } elseif ('ignore' == $action->getName()) {
17232 $name = (string) $action['name'];
17233 unset($actions[$name]);
17234 } else {
17235
17236  }
17237 }
17238 }
17239 break;
17240 }
17241 }
17242
17243 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
17244 {
17245 $result = array();
17246
17247
17248  foreach ($children as $child) {
17249
17250 if ($child->getName() == 'dir') {
17251 $dirSource = $this->combine($source, (string) $child['name']);
17252 $dirTarget = $child['baseinstalldir'] ?: $target;
17253 $dirRole = $child['role'] ?: $role;
17254 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
17255 $result = array_merge($result, $dirFiles);
17256 } elseif ($child->getName() == 'file') {
17257 $fileRole = (string) $child['role'] ?: $role;
17258 if (isset($targetRoles[$fileRole])) {
17259 $fileName = (string) ($child['name'] ?: $child[0]); 
17260  $fileSource = $this->combine($source, $fileName);
17261 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
17262 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
17263 $fileTarget = $packageName . '/' . $fileTarget;
17264 }
17265 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
17266 }
17267 }
17268 }
17269
17270 return $result;
17271 }
17272
17273 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
17274 {
17275 $result = array();
17276
17277
17278  foreach ($children as $child) {
17279
17280 if ('dir' == $child->getName()) {
17281 $dirSource = $this->combine($source, $child['name']);
17282 $dirTarget = $child['baseinstalldir'] ?: $target;
17283 $dirRole = $child['role'] ?: $role;
17284 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
17285 $result = array_merge($result, $dirFiles);
17286 } elseif ('file' == $child->getName()) {
17287 $fileRole = (string) $child['role'] ?: $role;
17288 if (isset($targetRoles[$fileRole])) {
17289 $fileSource = $this->combine($source, (string) $child['name']);
17290 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
17291 $fileTasks = array();
17292 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
17293 if ('replace' == $taskNode->getName()) {
17294 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
17295 }
17296 }
17297 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
17298 $fileTarget = $packageName . '/' . $fileTarget;
17299 }
17300 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
17301 }
17302 }
17303 }
17304
17305 return $result;
17306 }
17307
17308 private function combine($left, $right)
17309 {
17310 return rtrim($left, '/') . '/' . ltrim($right, '/');
17311 }
17312 }
17313 <?php
17314
17315
17316
17317
17318
17319
17320
17321
17322
17323
17324
17325 namespace Composer\Downloader;
17326
17327 use Composer\Package\PackageInterface;
17328 use Composer\Repository\VcsRepository;
17329 use Composer\Util\Perforce;
17330
17331
17332
17333
17334 class PerforceDownloader extends VcsDownloader
17335 {
17336
17337 protected $perforce;
17338
17339
17340
17341
17342 public function doDownload(PackageInterface $package, $path, $url)
17343 {
17344 $ref = $package->getSourceReference();
17345 $label = $this->getLabelFromSourceReference($ref);
17346
17347 $this->io->writeError('Cloning ' . $ref);
17348 $this->initPerforce($package, $path, $url);
17349 $this->perforce->setStream($ref);
17350 $this->perforce->p4Login();
17351 $this->perforce->writeP4ClientSpec();
17352 $this->perforce->connectClient();
17353 $this->perforce->syncCodeBase($label);
17354 $this->perforce->cleanupClientSpec();
17355 }
17356
17357 private function getLabelFromSourceReference($ref)
17358 {
17359 $pos = strpos($ref, '@');
17360 if (false !== $pos) {
17361 return substr($ref, $pos + 1);
17362 }
17363
17364 return null;
17365 }
17366
17367 public function initPerforce(PackageInterface $package, $path, $url)
17368 {
17369 if (!empty($this->perforce)) {
17370 $this->perforce->initializePath($path);
17371
17372 return;
17373 }
17374
17375 $repository = $package->getRepository();
17376 $repoConfig = null;
17377 if ($repository instanceof VcsRepository) {
17378 $repoConfig = $this->getRepoConfig($repository);
17379 }
17380 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
17381 }
17382
17383 private function getRepoConfig(VcsRepository $repository)
17384 {
17385 return $repository->getRepoConfig();
17386 }
17387
17388
17389
17390
17391 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17392 {
17393 $this->doDownload($target, $path, $url);
17394 }
17395
17396
17397
17398
17399 public function getLocalChanges(PackageInterface $package, $path)
17400 {
17401 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
17402 }
17403
17404
17405
17406
17407 protected function getCommitLogs($fromReference, $toReference, $path)
17408 {
17409 return $this->perforce->getCommitLogs($fromReference, $toReference);
17410 }
17411
17412 public function setPerforce($perforce)
17413 {
17414 $this->perforce = $perforce;
17415 }
17416
17417
17418
17419
17420 protected function hasMetadataRepository($path)
17421 {
17422 return true;
17423 }
17424 }
17425 <?php
17426
17427
17428
17429
17430
17431
17432
17433
17434
17435
17436
17437 namespace Composer\Downloader;
17438
17439
17440
17441
17442
17443
17444 class PharDownloader extends ArchiveDownloader
17445 {
17446
17447
17448
17449 protected function extract($file, $path)
17450 {
17451
17452  $archive = new \Phar($file);
17453 $archive->extractTo($path, null, true);
17454
17455
17456
17457
17458
17459 }
17460 }
17461 <?php
17462
17463
17464
17465
17466
17467
17468
17469
17470
17471
17472
17473 namespace Composer\Downloader;
17474
17475 use Composer\Config;
17476 use Composer\Cache;
17477 use Composer\EventDispatcher\EventDispatcher;
17478 use Composer\Util\IniHelper;
17479 use Composer\Util\Platform;
17480 use Composer\Util\ProcessExecutor;
17481 use Composer\Util\RemoteFilesystem;
17482 use Composer\IO\IOInterface;
17483 use RarArchive;
17484
17485
17486
17487
17488
17489
17490
17491
17492 class RarDownloader extends ArchiveDownloader
17493 {
17494 protected $process;
17495
17496 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17497 {
17498 $this->process = $process ?: new ProcessExecutor($io);
17499 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17500 }
17501
17502 protected function extract($file, $path)
17503 {
17504 $processError = null;
17505
17506
17507  if (!Platform::isWindows()) {
17508 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
17509
17510 if (0 === $this->process->execute($command, $ignoredOutput)) {
17511 return;
17512 }
17513
17514 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17515 }
17516
17517 if (!class_exists('RarArchive')) {
17518
17519  $iniMessage = IniHelper::getMessage();
17520
17521 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
17522 . $iniMessage . "\n" . $processError;
17523
17524 if (!Platform::isWindows()) {
17525 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
17526 }
17527
17528 throw new \RuntimeException($error);
17529 }
17530
17531 $rarArchive = RarArchive::open($file);
17532
17533 if (false === $rarArchive) {
17534 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
17535 }
17536
17537 $entries = $rarArchive->getEntries();
17538
17539 if (false === $entries) {
17540 throw new \RuntimeException('Could not retrieve RAR archive entries');
17541 }
17542
17543 foreach ($entries as $entry) {
17544 if (false === $entry->extract($path)) {
17545 throw new \RuntimeException('Could not extract entry');
17546 }
17547 }
17548
17549 $rarArchive->close();
17550 }
17551 }
17552 <?php
17553
17554
17555
17556
17557
17558
17559
17560
17561
17562
17563
17564 namespace Composer\Downloader;
17565
17566 use Composer\Package\PackageInterface;
17567 use Composer\Util\Svn as SvnUtil;
17568 use Composer\Repository\VcsRepository;
17569 use Composer\Util\ProcessExecutor;
17570
17571
17572
17573
17574
17575 class SvnDownloader extends VcsDownloader
17576 {
17577 protected $cacheCredentials = true;
17578
17579
17580
17581
17582 public function doDownload(PackageInterface $package, $path, $url)
17583 {
17584 SvnUtil::cleanEnv();
17585 $ref = $package->getSourceReference();
17586
17587 $repo = $package->getRepository();
17588 if ($repo instanceof VcsRepository) {
17589 $repoConfig = $repo->getRepoConfig();
17590 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
17591 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
17592 }
17593 }
17594
17595 $this->io->writeError(" Checking out ".$package->getSourceReference());
17596 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
17597 }
17598
17599
17600
17601
17602 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17603 {
17604 SvnUtil::cleanEnv();
17605 $ref = $target->getSourceReference();
17606
17607 if (!$this->hasMetadataRepository($path)) {
17608 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
17609 }
17610
17611 $util = new SvnUtil($url, $this->io, $this->config);
17612 $flags = "";
17613 if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
17614 $flags .= ' --ignore-ancestry';
17615 }
17616
17617 $this->io->writeError(" Checking out " . $ref);
17618 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
17619 }
17620
17621
17622
17623
17624 public function getLocalChanges(PackageInterface $package, $path)
17625 {
17626 if (!$this->hasMetadataRepository($path)) {
17627 return null;
17628 }
17629
17630 $this->process->execute('svn status --ignore-externals', $output, $path);
17631
17632 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
17633 }
17634
17635
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645
17646
17647 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
17648 {
17649 $util = new SvnUtil($baseUrl, $this->io, $this->config);
17650 $util->setCacheCredentials($this->cacheCredentials);
17651 try {
17652 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
17653 } catch (\RuntimeException $e) {
17654 throw new \RuntimeException(
17655 'Package could not be downloaded, '.$e->getMessage()
17656 );
17657 }
17658 }
17659
17660
17661
17662
17663 protected function cleanChanges(PackageInterface $package, $path, $update)
17664 {
17665 if (!$changes = $this->getLocalChanges($package, $path)) {
17666 return;
17667 }
17668
17669 if (!$this->io->isInteractive()) {
17670 if (true === $this->config->get('discard-changes')) {
17671 return $this->discardChanges($path);
17672 }
17673
17674 return parent::cleanChanges($package, $path, $update);
17675 }
17676
17677 $changes = array_map(function ($elem) {
17678 return '    '.$elem;
17679 }, preg_split('{\s*\r?\n\s*}', $changes));
17680 $countChanges = count($changes);
17681 $this->io->writeError(sprintf('    <error>The package has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
17682 $this->io->writeError(array_slice($changes, 0, 10));
17683 if ($countChanges > 10) {
17684 $remaingChanges = $countChanges - 10;
17685 $this->io->writeError(
17686 sprintf(
17687 '    <info>'.$remaingChanges.' more file%s modified, choose "v" to view the full list</info>',
17688 $remaingChanges === 1 ? '' : 's'
17689 )
17690 );
17691 }
17692
17693 while (true) {
17694 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
17695 case 'y':
17696 $this->discardChanges($path);
17697 break 2;
17698
17699 case 'n':
17700 throw new \RuntimeException('Update aborted');
17701
17702 case 'v':
17703 $this->io->writeError($changes);
17704 break;
17705
17706 case '?':
17707 default:
17708 $this->io->writeError(array(
17709 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
17710 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
17711 '    v - view modified files',
17712 '    ? - print help',
17713 ));
17714 break;
17715 }
17716 }
17717 }
17718
17719
17720
17721
17722 protected function getCommitLogs($fromReference, $toReference, $path)
17723 {
17724 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
17725
17726  $command = sprintf('svn info --non-interactive --xml %s', ProcessExecutor::escape($path));
17727 if (0 !== $this->process->execute($command, $output, $path)) {
17728 throw new \RuntimeException(
17729 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
17730 );
17731 }
17732
17733 $urlPattern = '#<url>(.*)</url>#';
17734 if (preg_match($urlPattern, $output, $matches)) {
17735 $baseUrl = $matches[1];
17736 } else {
17737 throw new \RuntimeException(
17738 'Unable to determine svn url for path '. $path
17739 );
17740 }
17741
17742
17743  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
17744 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
17745
17746 $command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision));
17747
17748 $util = new SvnUtil($baseUrl, $this->io, $this->config);
17749 $util->setCacheCredentials($this->cacheCredentials);
17750 try {
17751 return $util->executeLocal($command, $path, null, $this->io->isVerbose());
17752 } catch (\RuntimeException $e) {
17753 throw new \RuntimeException(
17754 'Failed to execute ' . $command . "\n\n".$e->getMessage()
17755 );
17756 }
17757 }
17758
17759 return "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
17760 }
17761
17762 protected function discardChanges($path)
17763 {
17764 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
17765 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
17766 }
17767 }
17768
17769
17770
17771
17772 protected function hasMetadataRepository($path)
17773 {
17774 return is_dir($path.'/.svn');
17775 }
17776 }
17777 <?php
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789 namespace Composer\Downloader;
17790
17791
17792
17793
17794
17795
17796 class TarDownloader extends ArchiveDownloader
17797 {
17798
17799
17800
17801 protected function extract($file, $path)
17802 {
17803
17804  $archive = new \PharData($file);
17805 $archive->extractTo($path, null, true);
17806 }
17807 }
17808 <?php
17809
17810
17811
17812
17813
17814
17815
17816
17817
17818
17819
17820 namespace Composer\Downloader;
17821
17822
17823
17824
17825 class TransportException extends \RuntimeException
17826 {
17827 protected $headers;
17828 protected $response;
17829 protected $statusCode;
17830
17831 public function setHeaders($headers)
17832 {
17833 $this->headers = $headers;
17834 }
17835
17836 public function getHeaders()
17837 {
17838 return $this->headers;
17839 }
17840
17841 public function setResponse($response)
17842 {
17843 $this->response = $response;
17844 }
17845
17846 public function getResponse()
17847 {
17848 return $this->response;
17849 }
17850
17851 public function setStatusCode($statusCode)
17852 {
17853 $this->statusCode = $statusCode;
17854 }
17855
17856 public function getStatusCode()
17857 {
17858 return $this->statusCode;
17859 }
17860 }
17861 <?php
17862
17863
17864
17865
17866
17867
17868
17869
17870
17871
17872
17873 namespace Composer\Downloader;
17874
17875 use Composer\Package\PackageInterface;
17876
17877
17878
17879
17880
17881
17882 interface VcsCapableDownloaderInterface
17883 {
17884
17885
17886
17887
17888
17889
17890
17891 public function getVcsReference(PackageInterface $package, $path);
17892 }
17893 <?php
17894
17895
17896
17897
17898
17899
17900
17901
17902
17903
17904
17905 namespace Composer\Downloader;
17906
17907 use Composer\Config;
17908 use Composer\Package\Dumper\ArrayDumper;
17909 use Composer\Package\PackageInterface;
17910 use Composer\Package\Version\VersionGuesser;
17911 use Composer\Package\Version\VersionParser;
17912 use Composer\Util\ProcessExecutor;
17913 use Composer\IO\IOInterface;
17914 use Composer\Util\Filesystem;
17915
17916
17917
17918
17919 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
17920 {
17921
17922 protected $io;
17923
17924 protected $config;
17925
17926 protected $process;
17927
17928 protected $filesystem;
17929
17930 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
17931 {
17932 $this->io = $io;
17933 $this->config = $config;
17934 $this->process = $process ?: new ProcessExecutor($io);
17935 $this->filesystem = $fs ?: new Filesystem($this->process);
17936 }
17937
17938
17939
17940
17941 public function getInstallationSource()
17942 {
17943 return 'source';
17944 }
17945
17946
17947
17948
17949 public function download(PackageInterface $package, $path)
17950 {
17951 if (!$package->getSourceReference()) {
17952 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
17953 }
17954
17955 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
17956 $this->filesystem->emptyDirectory($path);
17957
17958 $urls = $package->getSourceUrls();
17959 while ($url = array_shift($urls)) {
17960 try {
17961 if (Filesystem::isLocalPath($url)) {
17962
17963  
17964  $needle = 'file://';
17965 $isFileProtocol = false;
17966 if (0 === strpos($url, $needle)) {
17967 $url = substr($url, strlen($needle));
17968 $isFileProtocol = true;
17969 }
17970
17971
17972  if (false !== strpos($url, '%')) {
17973 $url = rawurldecode($url);
17974 }
17975
17976 $url = realpath($url);
17977
17978 if ($isFileProtocol) {
17979 $url = $needle . $url;
17980 }
17981 }
17982 $this->doDownload($package, $path, $url);
17983 break;
17984 } catch (\Exception $e) {
17985
17986  if ($e instanceof \PHPUnit_Framework_Exception) {
17987 throw $e;
17988 }
17989 if ($this->io->isDebug()) {
17990 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
17991 } elseif (count($urls)) {
17992 $this->io->writeError('    Failed, trying the next URL');
17993 }
17994 if (!count($urls)) {
17995 throw $e;
17996 }
17997 }
17998 }
17999 }
18000
18001
18002
18003
18004 public function update(PackageInterface $initial, PackageInterface $target, $path)
18005 {
18006 if (!$target->getSourceReference()) {
18007 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
18008 }
18009
18010 $name = $target->getName();
18011 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
18012 if ($target->getSourceType() === 'svn') {
18013 $from = $initial->getSourceReference();
18014 $to = $target->getSourceReference();
18015 } else {
18016 $from = substr($initial->getSourceReference(), 0, 7);
18017 $to = substr($target->getSourceReference(), 0, 7);
18018 }
18019 $name .= ' '.$initial->getPrettyVersion();
18020 } else {
18021 $from = $initial->getFullPrettyVersion();
18022 $to = $target->getFullPrettyVersion();
18023 }
18024
18025 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
18026 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
18027
18028 $this->cleanChanges($initial, $path, true);
18029 $urls = $target->getSourceUrls();
18030
18031 $exception = null;
18032 while ($url = array_shift($urls)) {
18033 try {
18034 if (Filesystem::isLocalPath($url)) {
18035 $url = realpath($url);
18036 }
18037 $this->doUpdate($initial, $target, $path, $url);
18038
18039 $exception = null;
18040 break;
18041 } catch (\Exception $exception) {
18042
18043  if ($exception instanceof \PHPUnit_Framework_Exception) {
18044 throw $exception;
18045 }
18046 if ($this->io->isDebug()) {
18047 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
18048 } elseif (count($urls)) {
18049 $this->io->writeError('    Failed, trying the next URL');
18050 }
18051 }
18052 }
18053
18054 $this->reapplyChanges($path);
18055
18056
18057  
18058  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
18059 $message = 'Pulling in changes:';
18060 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
18061
18062 if (!trim($logs)) {
18063 $message = 'Rolling back changes:';
18064 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
18065 }
18066
18067 if (trim($logs)) {
18068 $logs = implode("\n", array_map(function ($line) {
18069 return '      ' . $line;
18070 }, explode("\n", $logs)));
18071
18072
18073  $logs = str_replace('<', '\<', $logs);
18074
18075 $this->io->writeError('    '.$message);
18076 $this->io->writeError($logs);
18077 }
18078 }
18079
18080 if (!$urls && $exception) {
18081 throw $exception;
18082 }
18083 }
18084
18085
18086
18087
18088 public function remove(PackageInterface $package, $path)
18089 {
18090 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
18091 $this->cleanChanges($package, $path, false);
18092 if (!$this->filesystem->removeDirectory($path)) {
18093 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
18094 }
18095 }
18096
18097
18098
18099
18100
18101 public function setOutputProgress($outputProgress)
18102 {
18103 return $this;
18104 }
18105
18106
18107
18108
18109 public function getVcsReference(PackageInterface $package, $path)
18110 {
18111 $parser = new VersionParser;
18112 $guesser = new VersionGuesser($this->config, $this->process, $parser);
18113 $dumper = new ArrayDumper;
18114
18115 $packageConfig = $dumper->dump($package);
18116 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
18117 return $packageVersion['commit'];
18118 }
18119 }
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130 protected function cleanChanges(PackageInterface $package, $path, $update)
18131 {
18132
18133  if (null !== $this->getLocalChanges($package, $path)) {
18134 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
18135 }
18136 }
18137
18138
18139
18140
18141
18142
18143
18144 protected function reapplyChanges($path)
18145 {
18146 }
18147
18148
18149
18150
18151
18152
18153
18154
18155 abstract protected function doDownload(PackageInterface $package, $path, $url);
18156
18157
18158
18159
18160
18161
18162
18163
18164
18165 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
18166
18167
18168
18169
18170
18171
18172
18173
18174
18175 abstract protected function getCommitLogs($fromReference, $toReference, $path);
18176
18177
18178
18179
18180
18181
18182
18183
18184 abstract protected function hasMetadataRepository($path);
18185 }
18186 <?php
18187
18188
18189
18190
18191
18192
18193
18194
18195
18196
18197
18198 namespace Composer\Downloader;
18199
18200 use Composer\Config;
18201 use Composer\Cache;
18202 use Composer\EventDispatcher\EventDispatcher;
18203 use Composer\Package\PackageInterface;
18204 use Composer\Util\ProcessExecutor;
18205 use Composer\Util\RemoteFilesystem;
18206 use Composer\IO\IOInterface;
18207
18208
18209
18210
18211
18212
18213
18214 class XzDownloader extends ArchiveDownloader
18215 {
18216 protected $process;
18217
18218 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18219 {
18220 $this->process = $process ?: new ProcessExecutor($io);
18221
18222 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
18223 }
18224
18225 protected function extract($file, $path)
18226 {
18227 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
18228
18229 if (0 === $this->process->execute($command, $ignoredOutput)) {
18230 return;
18231 }
18232
18233 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
18234
18235 throw new \RuntimeException($processError);
18236 }
18237
18238
18239
18240
18241 protected function getFileName(PackageInterface $package, $path)
18242 {
18243 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
18244 }
18245 }
18246 <?php
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257
18258 namespace Composer\Downloader;
18259
18260 use Composer\Config;
18261 use Composer\Cache;
18262 use Composer\EventDispatcher\EventDispatcher;
18263 use Composer\Package\PackageInterface;
18264 use Composer\Util\IniHelper;
18265 use Composer\Util\Platform;
18266 use Composer\Util\ProcessExecutor;
18267 use Composer\Util\RemoteFilesystem;
18268 use Composer\IO\IOInterface;
18269 use Symfony\Component\Process\ExecutableFinder;
18270 use ZipArchive;
18271
18272
18273
18274
18275 class ZipDownloader extends ArchiveDownloader
18276 {
18277 protected static $hasSystemUnzip;
18278 private static $hasZipArchive;
18279 private static $isWindows;
18280
18281 protected $process;
18282 private $zipArchiveObject;
18283
18284 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18285 {
18286 $this->process = $process ?: new ProcessExecutor($io);
18287 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
18288 }
18289
18290
18291
18292
18293 public function download(PackageInterface $package, $path, $output = true)
18294 {
18295 if (null === self::$hasSystemUnzip) {
18296 $finder = new ExecutableFinder;
18297 self::$hasSystemUnzip = (bool) $finder->find('unzip');
18298 }
18299
18300 if (null === self::$hasZipArchive) {
18301 self::$hasZipArchive = class_exists('ZipArchive');
18302 }
18303
18304 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
18305
18306  $iniMessage = IniHelper::getMessage();
18307 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
18308
18309 throw new \RuntimeException($error);
18310 }
18311
18312 if (null === self::$isWindows) {
18313 self::$isWindows = Platform::isWindows();
18314
18315 if (!self::$isWindows && !self::$hasSystemUnzip) {
18316 $this->io->writeError("<warning>As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.</warning>");
18317 $this->io->writeError("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>");
18318 $this->io->writeError("<warning>Installing 'unzip' may remediate them.</warning>");
18319 }
18320 }
18321
18322 return parent::download($package, $path, $output);
18323 }
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333 protected function extractWithSystemUnzip($file, $path, $isLastChance)
18334 {
18335 if (!self::$hasZipArchive) {
18336
18337  $isLastChance = true;
18338 }
18339
18340 if (!self::$hasSystemUnzip && !$isLastChance) {
18341
18342  
18343  return $this->extractWithZipArchive($file, $path, true);
18344 }
18345
18346 $processError = null;
18347
18348  $overwrite = $isLastChance ? '-o' : '';
18349
18350 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
18351
18352 try {
18353 if (0 === $this->process->execute($command, $ignoredOutput)) {
18354 return true;
18355 }
18356
18357 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
18358 } catch (\Exception $e) {
18359 $processError = $e;
18360 }
18361
18362 if ($isLastChance) {
18363 throw $processError;
18364 }
18365
18366 $this->io->writeError('    '.$processError->getMessage());
18367 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
18368 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
18369
18370 return $this->extractWithZipArchive($file, $path, true);
18371 }
18372
18373
18374
18375
18376
18377
18378
18379
18380
18381 protected function extractWithZipArchive($file, $path, $isLastChance)
18382 {
18383 if (!self::$hasSystemUnzip) {
18384
18385  $isLastChance = true;
18386 }
18387
18388 if (!self::$hasZipArchive && !$isLastChance) {
18389
18390  
18391  return $this->extractWithSystemUnzip($file, $path, true);
18392 }
18393
18394 $processError = null;
18395 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
18396
18397 try {
18398 if (true === ($retval = $zipArchive->open($file))) {
18399 $extractResult = $zipArchive->extractTo($path);
18400
18401 if (true === $extractResult) {
18402 $zipArchive->close();
18403
18404 return true;
18405 }
18406
18407 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
18408 } else {
18409 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
18410 }
18411 } catch (\ErrorException $e) {
18412 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
18413 } catch (\Exception $e) {
18414 $processError = $e;
18415 }
18416
18417 if ($isLastChance) {
18418 throw $processError;
18419 }
18420
18421 $this->io->writeError('    '.$processError->getMessage());
18422 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
18423
18424 return $this->extractWithSystemUnzip($file, $path, true);
18425 }
18426
18427
18428
18429
18430
18431
18432
18433 public function extract($file, $path)
18434 {
18435
18436  if (self::$isWindows) {
18437 $this->extractWithZipArchive($file, $path, false);
18438 } else {
18439 $this->extractWithSystemUnzip($file, $path, false);
18440 }
18441 }
18442
18443
18444
18445
18446
18447
18448
18449
18450 protected function getErrorMessage($retval, $file)
18451 {
18452 switch ($retval) {
18453 case ZipArchive::ER_EXISTS:
18454 return sprintf("File '%s' already exists.", $file);
18455 case ZipArchive::ER_INCONS:
18456 return sprintf("Zip archive '%s' is inconsistent.", $file);
18457 case ZipArchive::ER_INVAL:
18458 return sprintf("Invalid argument (%s)", $file);
18459 case ZipArchive::ER_MEMORY:
18460 return sprintf("Malloc failure (%s)", $file);
18461 case ZipArchive::ER_NOENT:
18462 return sprintf("No such zip file: '%s'", $file);
18463 case ZipArchive::ER_NOZIP:
18464 return sprintf("'%s' is not a zip archive.", $file);
18465 case ZipArchive::ER_OPEN:
18466 return sprintf("Can't open zip file: %s", $file);
18467 case ZipArchive::ER_READ:
18468 return sprintf("Zip read error (%s)", $file);
18469 case ZipArchive::ER_SEEK:
18470 return sprintf("Zip seek error (%s)", $file);
18471 default:
18472 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
18473 }
18474 }
18475 }
18476 <?php
18477
18478
18479
18480
18481
18482
18483
18484
18485
18486
18487
18488 namespace Composer\EventDispatcher;
18489
18490
18491
18492
18493
18494
18495 class Event
18496 {
18497
18498
18499
18500 protected $name;
18501
18502
18503
18504
18505 protected $args;
18506
18507
18508
18509
18510 protected $flags;
18511
18512
18513
18514
18515 private $propagationStopped = false;
18516
18517
18518
18519
18520
18521
18522
18523
18524 public function __construct($name, array $args = array(), array $flags = array())
18525 {
18526 $this->name = $name;
18527 $this->args = $args;
18528 $this->flags = $flags;
18529 }
18530
18531
18532
18533
18534
18535
18536 public function getName()
18537 {
18538 return $this->name;
18539 }
18540
18541
18542
18543
18544
18545
18546 public function getArguments()
18547 {
18548 return $this->args;
18549 }
18550
18551
18552
18553
18554
18555
18556 public function getFlags()
18557 {
18558 return $this->flags;
18559 }
18560
18561
18562
18563
18564
18565
18566 public function isPropagationStopped()
18567 {
18568 return $this->propagationStopped;
18569 }
18570
18571
18572
18573
18574 public function stopPropagation()
18575 {
18576 $this->propagationStopped = true;
18577 }
18578 }
18579 <?php
18580
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591 namespace Composer\EventDispatcher;
18592
18593 use Composer\DependencyResolver\PolicyInterface;
18594 use Composer\DependencyResolver\Pool;
18595 use Composer\DependencyResolver\Request;
18596 use Composer\Installer\InstallerEvent;
18597 use Composer\IO\IOInterface;
18598 use Composer\Composer;
18599 use Composer\DependencyResolver\Operation\OperationInterface;
18600 use Composer\Repository\CompositeRepository;
18601 use Composer\Script;
18602 use Composer\Installer\PackageEvent;
18603 use Composer\Installer\BinaryInstaller;
18604 use Composer\Util\ProcessExecutor;
18605 use Composer\Script\Event as ScriptEvent;
18606 use Symfony\Component\Process\PhpExecutableFinder;
18607
18608
18609
18610
18611
18612
18613
18614
18615
18616
18617
18618
18619
18620
18621 class EventDispatcher
18622 {
18623 protected $composer;
18624 protected $io;
18625 protected $loader;
18626 protected $process;
18627 protected $listeners;
18628 private $eventStack;
18629
18630
18631
18632
18633
18634
18635
18636
18637 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
18638 {
18639 $this->composer = $composer;
18640 $this->io = $io;
18641 $this->process = $process ?: new ProcessExecutor($io);
18642 $this->eventStack = array();
18643 }
18644
18645
18646
18647
18648
18649
18650
18651
18652
18653 public function dispatch($eventName, Event $event = null)
18654 {
18655 if (null === $event) {
18656 $event = new Event($eventName);
18657 }
18658
18659 return $this->doDispatch($event);
18660 }
18661
18662
18663
18664
18665
18666
18667
18668
18669
18670
18671
18672 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
18673 {
18674 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
18675 }
18676
18677
18678
18679
18680
18681
18682
18683
18684
18685
18686
18687
18688
18689
18690
18691
18692 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
18693 {
18694 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
18695 }
18696
18697
18698
18699
18700
18701
18702
18703
18704
18705
18706
18707
18708
18709
18710
18711 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
18712 {
18713 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
18714 }
18715
18716
18717
18718
18719
18720
18721
18722
18723
18724 protected function doDispatch(Event $event)
18725 {
18726 $pathStr = 'PATH';
18727 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
18728 $pathStr = 'Path';
18729 }
18730
18731
18732  $binDir = $this->composer->getConfig()->get('bin-dir');
18733 if (is_dir($binDir)) {
18734 $binDir = realpath($binDir);
18735 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
18736 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
18737 putenv($pathStr.'='.$_SERVER[$pathStr]);
18738 }
18739 }
18740
18741 $listeners = $this->getListeners($event);
18742
18743 $this->pushEvent($event);
18744
18745 $return = 0;
18746 foreach ($listeners as $callable) {
18747 if (!is_string($callable)) {
18748 if (!is_callable($callable)) {
18749 $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
18750
18751 throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
18752 }
18753 $event = $this->checkListenerExpectedEvent($callable, $event);
18754 $return = false === call_user_func($callable, $event) ? 1 : 0;
18755 } elseif ($this->isComposerScript($callable)) {
18756 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
18757
18758 $script = explode(' ', substr($callable, 1));
18759 $scriptName = $script[0];
18760 unset($script[0]);
18761
18762 $args = array_merge($script, $event->getArguments());
18763 $flags = $event->getFlags();
18764 if (substr($callable, 0, 10) === '@composer ') {
18765 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
18766 if (0 !== ($exitCode = $this->process->execute($exec))) {
18767 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18768
18769 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
18770 }
18771 } else {
18772 if (!$this->getListeners(new Event($scriptName))) {
18773 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
18774 }
18775
18776 try {
18777 $scriptEvent = new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags);
18778 $scriptEvent->setOriginatingEvent($event);
18779 $return = $this->dispatch($scriptName, $scriptEvent);
18780 } catch (ScriptExecutionException $e) {
18781 $this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18782 throw $e;
18783 }
18784 }
18785 } elseif ($this->isPhpScript($callable)) {
18786 $className = substr($callable, 0, strpos($callable, '::'));
18787 $methodName = substr($callable, strpos($callable, '::') + 2);
18788
18789 if (!class_exists($className)) {
18790 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
18791 continue;
18792 }
18793 if (!is_callable($callable)) {
18794 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
18795 continue;
18796 }
18797
18798 try {
18799 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
18800 } catch (\Exception $e) {
18801 $message = "Script %s handling the %s event terminated with an exception";
18802 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
18803 throw $e;
18804 }
18805 } else {
18806 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
18807 $exec = $callable . ($args === '' ? '' : ' '.$args);
18808 if ($this->io->isVerbose()) {
18809 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
18810 } else {
18811 $this->io->writeError(sprintf('> %s', $exec));
18812 }
18813
18814 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
18815 if ($possibleLocalBinaries) {
18816 foreach ($possibleLocalBinaries as $localExec) {
18817 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
18818 $caller = BinaryInstaller::determineBinaryCaller($localExec);
18819 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
18820 break;
18821 }
18822 }
18823 }
18824
18825 if (substr($exec, 0, 5) === '@php ') {
18826 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
18827 } else {
18828 $finder = new PhpExecutableFinder();
18829 $phpPath = $finder->find(false);
18830 if ($phpPath) {
18831 putenv('PHP_BINARY=' . $phpPath);
18832 }
18833 }
18834
18835 if (0 !== ($exitCode = $this->process->execute($exec))) {
18836 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18837
18838 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
18839 }
18840 }
18841
18842 if ($event->isPropagationStopped()) {
18843 break;
18844 }
18845 }
18846
18847 $this->popEvent();
18848
18849 return $return;
18850 }
18851
18852 protected function getPhpExecCommand()
18853 {
18854 $finder = new PhpExecutableFinder();
18855 $phpPath = $finder->find(false);
18856 if (!$phpPath) {
18857 throw new \RuntimeException('Failed to locate PHP binary to execute '.$phpPath);
18858 }
18859 $phpArgs = $finder->findArguments();
18860 $phpArgs = $phpArgs ? ' ' . implode(' ', $phpArgs) : '';
18861 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
18862 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
18863 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
18864
18865 return ProcessExecutor::escape($phpPath) . $phpArgs . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
18866 }
18867
18868
18869
18870
18871
18872
18873 protected function executeEventPhpScript($className, $methodName, Event $event)
18874 {
18875 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
18876
18877 if ($this->io->isVerbose()) {
18878 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
18879 } else {
18880 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
18881 }
18882
18883 return $className::$methodName($event);
18884 }
18885
18886
18887
18888
18889
18890
18891 protected function checkListenerExpectedEvent($target, Event $event)
18892 {
18893 if (in_array($event->getName(), array(
18894 'init',
18895 'command',
18896 'pre-file-download',
18897 ), true)) {
18898 return $event;
18899 }
18900
18901 try {
18902 $reflected = new \ReflectionParameter($target, 0);
18903 } catch (\Exception $e) {
18904 return $event;
18905 }
18906
18907 $typehint = $reflected->getClass();
18908
18909 if (!$typehint instanceof \ReflectionClass) {
18910 return $event;
18911 }
18912
18913 $expected = $typehint->getName();
18914
18915
18916  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
18917 trigger_error('The callback '.$this->serializeCallback($target).' declared at '.$reflected->getDeclaringFunction()->getFileName().' accepts a '.$expected.' but '.$event->getName().' events use a '.get_class($event).' instance. Please adjust your type hint accordingly, see https://getcomposer.org/doc/articles/scripts.md#event-classes', E_USER_DEPRECATED);
18918 $event = new \Composer\Script\CommandEvent(
18919 $event->getName(),
18920 $event->getComposer(),
18921 $event->getIO(),
18922 $event->isDevMode(),
18923 $event->getArguments()
18924 );
18925 }
18926 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
18927 trigger_error('The callback '.$this->serializeCallback($target).' declared at '.$reflected->getDeclaringFunction()->getFileName().' accepts a '.$expected.' but '.$event->getName().' events use a '.get_class($event).' instance. Please adjust your type hint accordingly, see https://getcomposer.org/doc/articles/scripts.md#event-classes', E_USER_DEPRECATED);
18928 $event = new \Composer\Script\PackageEvent(
18929 $event->getName(),
18930 $event->getComposer(),
18931 $event->getIO(),
18932 $event->isDevMode(),
18933 $event->getPolicy(),
18934 $event->getPool(),
18935 $event->getInstalledRepo(),
18936 $event->getRequest(),
18937 $event->getOperations(),
18938 $event->getOperation()
18939 );
18940 }
18941 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
18942 trigger_error('The callback '.$this->serializeCallback($target).' declared at '.$reflected->getDeclaringFunction()->getFileName().' accepts a '.$expected.' but '.$event->getName().' events use a '.get_class($event).' instance. Please adjust your type hint accordingly, see https://getcomposer.org/doc/articles/scripts.md#event-classes', E_USER_DEPRECATED);
18943 $event = new \Composer\Script\Event(
18944 $event->getName(),
18945 $event->getComposer(),
18946 $event->getIO(),
18947 $event->isDevMode(),
18948 $event->getArguments(),
18949 $event->getFlags()
18950 );
18951 }
18952
18953 return $event;
18954 }
18955
18956 private function serializeCallback($cb)
18957 {
18958 if (is_array($cb) && count($cb) === 2) {
18959 if (is_object($cb[0])) {
18960 $cb[0] = get_class($cb[0]);
18961 }
18962 if (is_string($cb[0]) && is_string($cb[1])) {
18963 $cb = implode('::', $cb);
18964 }
18965 }
18966 if (is_string($cb)) {
18967 return $cb;
18968 }
18969
18970 return var_export($cb, true);
18971 }
18972
18973
18974
18975
18976
18977
18978
18979
18980 public function addListener($eventName, $listener, $priority = 0)
18981 {
18982 $this->listeners[$eventName][$priority][] = $listener;
18983 }
18984
18985
18986
18987
18988
18989
18990
18991
18992 public function addSubscriber(EventSubscriberInterface $subscriber)
18993 {
18994 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
18995 if (is_string($params)) {
18996 $this->addListener($eventName, array($subscriber, $params));
18997 } elseif (is_string($params[0])) {
18998 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
18999 } else {
19000 foreach ($params as $listener) {
19001 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
19002 }
19003 }
19004 }
19005 }
19006
19007
19008
19009
19010
19011
19012
19013 protected function getListeners(Event $event)
19014 {
19015 $scriptListeners = $this->getScriptListeners($event);
19016
19017 if (!isset($this->listeners[$event->getName()][0])) {
19018 $this->listeners[$event->getName()][0] = array();
19019 }
19020 krsort($this->listeners[$event->getName()]);
19021
19022 $listeners = $this->listeners;
19023 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
19024
19025 return call_user_func_array('array_merge', $listeners[$event->getName()]);
19026 }
19027
19028
19029
19030
19031
19032
19033
19034 public function hasEventListeners(Event $event)
19035 {
19036 $listeners = $this->getListeners($event);
19037
19038 return count($listeners) > 0;
19039 }
19040
19041
19042
19043
19044
19045
19046
19047 protected function getScriptListeners(Event $event)
19048 {
19049 $package = $this->composer->getPackage();
19050 $scripts = $package->getScripts();
19051
19052 if (empty($scripts[$event->getName()])) {
19053 return array();
19054 }
19055
19056 if ($this->loader) {
19057 $this->loader->unregister();
19058 }
19059
19060 $generator = $this->composer->getAutoloadGenerator();
19061 if ($event instanceof ScriptEvent) {
19062 $generator->setDevMode($event->isDevMode());
19063 }
19064
19065 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
19066 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
19067 $map = $generator->parseAutoloads($packageMap, $package);
19068 $this->loader = $generator->createLoader($map);
19069 $this->loader->register();
19070
19071 return $scripts[$event->getName()];
19072 }
19073
19074
19075
19076
19077
19078
19079
19080 protected function isPhpScript($callable)
19081 {
19082 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
19083 }
19084
19085
19086
19087
19088
19089
19090
19091 protected function isComposerScript($callable)
19092 {
19093 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
19094 }
19095
19096
19097
19098
19099
19100
19101
19102
19103 protected function pushEvent(Event $event)
19104 {
19105 $eventName = $event->getName();
19106 if (in_array($eventName, $this->eventStack)) {
19107 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
19108 }
19109
19110 return array_push($this->eventStack, $eventName);
19111 }
19112
19113
19114
19115
19116
19117
19118 protected function popEvent()
19119 {
19120 return array_pop($this->eventStack);
19121 }
19122 }
19123 <?php
19124
19125
19126
19127
19128
19129
19130
19131
19132
19133
19134
19135 namespace Composer\EventDispatcher;
19136
19137
19138
19139
19140
19141
19142
19143
19144
19145
19146
19147
19148
19149 interface EventSubscriberInterface
19150 {
19151
19152
19153
19154
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168
19169 public static function getSubscribedEvents();
19170 }
19171 <?php
19172
19173
19174
19175
19176
19177
19178
19179
19180
19181
19182
19183 namespace Composer\EventDispatcher;
19184
19185
19186
19187
19188 class ScriptExecutionException extends \RuntimeException
19189 {
19190 }
19191 <?php
19192
19193
19194
19195
19196
19197
19198
19199
19200
19201
19202
19203 namespace Composer\Exception;
19204
19205
19206
19207
19208 class NoSslException extends \RuntimeException
19209 {
19210 }
19211 <?php
19212
19213
19214
19215
19216
19217
19218
19219
19220
19221
19222
19223 namespace Composer;
19224
19225 use Composer\Config\JsonConfigSource;
19226 use Composer\Json\JsonFile;
19227 use Composer\IO\IOInterface;
19228 use Composer\Package\Archiver;
19229 use Composer\Package\Version\VersionGuesser;
19230 use Composer\Repository\RepositoryManager;
19231 use Composer\Repository\RepositoryFactory;
19232 use Composer\Repository\WritableRepositoryInterface;
19233 use Composer\Util\Filesystem;
19234 use Composer\Util\Platform;
19235 use Composer\Util\ProcessExecutor;
19236 use Composer\Util\RemoteFilesystem;
19237 use Composer\Util\Silencer;
19238 use Composer\Plugin\PluginEvents;
19239 use Composer\EventDispatcher\Event;
19240 use Seld\JsonLint\DuplicateKeyException;
19241 use Symfony\Component\Console\Formatter\OutputFormatter;
19242 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
19243 use Symfony\Component\Console\Output\ConsoleOutput;
19244 use Composer\EventDispatcher\EventDispatcher;
19245 use Composer\Autoload\AutoloadGenerator;
19246 use Composer\Package\Version\VersionParser;
19247 use Composer\Downloader\TransportException;
19248 use Seld\JsonLint\JsonParser;
19249
19250
19251
19252
19253
19254
19255
19256
19257
19258 class Factory
19259 {
19260
19261
19262
19263
19264 protected static function getHomeDir()
19265 {
19266 $home = getenv('COMPOSER_HOME');
19267 if ($home) {
19268 return $home;
19269 }
19270
19271 if (Platform::isWindows()) {
19272 if (!getenv('APPDATA')) {
19273 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
19274 }
19275
19276 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
19277 }
19278
19279 $userDir = self::getUserDir();
19280 if (is_dir($userDir . '/.composer')) {
19281 return $userDir . '/.composer';
19282 }
19283
19284 if (self::useXdg()) {
19285
19286  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
19287
19288 return $xdgConfig . '/composer';
19289 }
19290
19291 return $userDir . '/.composer';
19292 }
19293
19294
19295
19296
19297
19298 protected static function getCacheDir($home)
19299 {
19300 $cacheDir = getenv('COMPOSER_CACHE_DIR');
19301 if ($cacheDir) {
19302 return $cacheDir;
19303 }
19304
19305 $homeEnv = getenv('COMPOSER_HOME');
19306 if ($homeEnv) {
19307 return $homeEnv . '/cache';
19308 }
19309
19310 if (Platform::isWindows()) {
19311 if ($cacheDir = getenv('LOCALAPPDATA')) {
19312 $cacheDir .= '/Composer';
19313 } else {
19314 $cacheDir = $home . '/cache';
19315 }
19316
19317 return rtrim(strtr($cacheDir, '\\', '/'), '/');
19318 }
19319
19320 $userDir = self::getUserDir();
19321 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
19322 return $home . '/cache';
19323 }
19324
19325 if (self::useXdg()) {
19326 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
19327
19328 return $xdgCache . '/composer';
19329 }
19330
19331 return $home . '/cache';
19332 }
19333
19334
19335
19336
19337
19338 protected static function getDataDir($home)
19339 {
19340 $homeEnv = getenv('COMPOSER_HOME');
19341 if ($homeEnv) {
19342 return $homeEnv;
19343 }
19344
19345 if (Platform::isWindows()) {
19346 return strtr($home, '\\', '/');
19347 }
19348
19349 $userDir = self::getUserDir();
19350 if ($home !== $userDir . '/.composer' && self::useXdg()) {
19351 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
19352
19353 return $xdgData . '/composer';
19354 }
19355
19356 return $home;
19357 }
19358
19359
19360
19361
19362
19363 public static function createConfig(IOInterface $io = null, $cwd = null)
19364 {
19365 $cwd = $cwd ?: getcwd();
19366
19367 $config = new Config(true, $cwd);
19368
19369
19370  $home = self::getHomeDir();
19371 $config->merge(array('config' => array(
19372 'home' => $home,
19373 'cache-dir' => self::getCacheDir($home),
19374 'data-dir' => self::getDataDir($home),
19375 )));
19376
19377
19378  $file = new JsonFile($config->get('home').'/config.json');
19379 if ($file->exists()) {
19380 if ($io && $io->isDebug()) {
19381 $io->writeError('Loading config file ' . $file->getPath());
19382 }
19383 $config->merge($file->read());
19384 }
19385 $config->setConfigSource(new JsonConfigSource($file));
19386
19387 $htaccessProtect = (bool) $config->get('htaccess-protect');
19388 if ($htaccessProtect) {
19389
19390  
19391  
19392  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
19393 foreach ($dirs as $dir) {
19394 if (!file_exists($dir . '/.htaccess')) {
19395 if (!is_dir($dir)) {
19396 Silencer::call('mkdir', $dir, 0777, true);
19397 }
19398 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
19399 }
19400 }
19401 }
19402
19403
19404  $file = new JsonFile($config->get('home').'/auth.json');
19405 if ($file->exists()) {
19406 if ($io && $io->isDebug()) {
19407 $io->writeError('Loading config file ' . $file->getPath());
19408 }
19409 $config->merge(array('config' => $file->read()));
19410 }
19411 $config->setAuthConfigSource(new JsonConfigSource($file, true));
19412
19413
19414  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
19415 $authData = json_decode($composerAuthEnv, true);
19416
19417 if (null === $authData) {
19418 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
19419 }
19420
19421 if ($io && $io->isDebug()) {
19422 $io->writeError('Loading auth config from COMPOSER_AUTH');
19423 }
19424 $config->merge(array('config' => $authData));
19425 }
19426
19427 return $config;
19428 }
19429
19430 public static function getComposerFile()
19431 {
19432 return trim(getenv('COMPOSER')) ?: './composer.json';
19433 }
19434
19435 public static function createAdditionalStyles()
19436 {
19437 return array(
19438 'highlight' => new OutputFormatterStyle('red'),
19439 'warning' => new OutputFormatterStyle('black', 'yellow'),
19440 );
19441 }
19442
19443
19444
19445
19446
19447
19448 public static function createOutput()
19449 {
19450 $styles = self::createAdditionalStyles();
19451 $formatter = new OutputFormatter(false, $styles);
19452
19453 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
19454 }
19455
19456
19457
19458
19459 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
19460 {
19461 return RepositoryFactory::defaultRepos($io, $config, $rm);
19462 }
19463
19464
19465
19466
19467
19468
19469
19470
19471
19472
19473
19474
19475
19476 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
19477 {
19478 $cwd = $cwd ?: getcwd();
19479
19480
19481  if (null === $localConfig) {
19482 $localConfig = static::getComposerFile();
19483 }
19484
19485 if (is_string($localConfig)) {
19486 $composerFile = $localConfig;
19487
19488 $file = new JsonFile($localConfig, null, $io);
19489
19490 if (!$file->exists()) {
19491 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
19492 $message = 'Composer could not find a composer.json file in '.$cwd;
19493 } else {
19494 $message = 'Composer could not find the config file: '.$localConfig;
19495 }
19496 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
19497 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
19498 }
19499
19500 $file->validateSchema(JsonFile::LAX_SCHEMA);
19501 $jsonParser = new JsonParser;
19502 try {
19503 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
19504 } catch (DuplicateKeyException $e) {
19505 $details = $e->getDetails();
19506 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
19507 }
19508
19509 $localConfig = $file->read();
19510 }
19511
19512
19513  $config = static::createConfig($io, $cwd);
19514 $config->merge($localConfig);
19515 if (isset($composerFile)) {
19516 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
19517 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
19518
19519 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
19520 if ($localAuthFile->exists()) {
19521 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
19522 $config->merge(array('config' => $localAuthFile->read()));
19523 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
19524 }
19525 }
19526
19527 $vendorDir = $config->get('vendor-dir');
19528
19529
19530  $composer = new Composer();
19531 $composer->setConfig($config);
19532
19533 if ($fullLoad) {
19534
19535  $io->loadConfiguration($config);
19536 }
19537
19538 $rfs = self::createRemoteFilesystem($io, $config);
19539
19540
19541  $dispatcher = new EventDispatcher($composer, $io);
19542 $composer->setEventDispatcher($dispatcher);
19543
19544
19545  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
19546 $composer->setRepositoryManager($rm);
19547
19548
19549  $this->addLocalRepository($io, $rm, $vendorDir);
19550
19551
19552  
19553  if (!$fullLoad && !isset($localConfig['version'])) {
19554 $localConfig['version'] = '1.0.0';
19555 }
19556
19557
19558  $parser = new VersionParser;
19559 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
19560 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
19561 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
19562 $composer->setPackage($package);
19563
19564
19565  $im = $this->createInstallationManager();
19566 $composer->setInstallationManager($im);
19567
19568 if ($fullLoad) {
19569
19570  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
19571 $composer->setDownloadManager($dm);
19572
19573
19574  $generator = new AutoloadGenerator($dispatcher, $io);
19575 $composer->setAutoloadGenerator($generator);
19576
19577
19578  $am = $this->createArchiveManager($config, $dm);
19579 $composer->setArchiveManager($am);
19580 }
19581
19582
19583  $this->createDefaultInstallers($im, $composer, $io);
19584
19585 if ($fullLoad) {
19586 $globalComposer = null;
19587 if (realpath($config->get('home')) !== $cwd) {
19588 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
19589 }
19590
19591 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
19592 $composer->setPluginManager($pm);
19593
19594 $pm->loadInstalledPlugins();
19595 }
19596
19597
19598  if ($fullLoad && isset($composerFile)) {
19599 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
19600 ? substr($composerFile, 0, -4).'lock'
19601 : $composerFile . '.lock';
19602
19603 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
19604 $composer->setLocker($locker);
19605 }
19606
19607 if ($fullLoad) {
19608 $initEvent = new Event(PluginEvents::INIT);
19609 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
19610
19611
19612  
19613  if ($rm->getLocalRepository()) {
19614 $this->purgePackages($rm->getLocalRepository(), $im);
19615 }
19616 }
19617
19618 return $composer;
19619 }
19620
19621
19622
19623
19624
19625
19626 public static function createGlobal(IOInterface $io, $disablePlugins = false)
19627 {
19628 $factory = new static();
19629
19630 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
19631 }
19632
19633
19634
19635
19636
19637 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
19638 {
19639 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
19640 }
19641
19642
19643
19644
19645
19646 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
19647 {
19648 $composer = null;
19649 try {
19650 $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
19651 } catch (\Exception $e) {
19652 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
19653 }
19654
19655 return $composer;
19656 }
19657
19658
19659
19660
19661
19662
19663
19664 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
19665 {
19666 $cache = null;
19667 if ($config->get('cache-files-ttl') > 0) {
19668 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
19669 }
19670
19671 $dm = new Downloader\DownloadManager($io);
19672 switch ($preferred = $config->get('preferred-install')) {
19673 case 'dist':
19674 $dm->setPreferDist(true);
19675 break;
19676 case 'source':
19677 $dm->setPreferSource(true);
19678 break;
19679 case 'auto':
19680 default:
19681
19682  break;
19683 }
19684
19685 if (is_array($preferred)) {
19686 $dm->setPreferences($preferred);
19687 }
19688
19689 $executor = new ProcessExecutor($io);
19690 $fs = new Filesystem($executor);
19691
19692 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
19693 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
19694 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
19695 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
19696 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
19697 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19698 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19699 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19700 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19701 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19702 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19703 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19704 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19705
19706 return $dm;
19707 }
19708
19709
19710
19711
19712
19713
19714 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
19715 {
19716 if (null === $dm) {
19717 $io = new IO\NullIO();
19718 $io->loadConfiguration($config);
19719 $dm = $this->createDownloadManager($io, $config);
19720 }
19721
19722 $am = new Archiver\ArchiveManager($dm);
19723 $am->addArchiver(new Archiver\ZipArchiver);
19724 $am->addArchiver(new Archiver\PharArchiver);
19725
19726 return $am;
19727 }
19728
19729
19730
19731
19732
19733
19734
19735
19736 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
19737 {
19738 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
19739 }
19740
19741
19742
19743
19744 protected function createInstallationManager()
19745 {
19746 return new Installer\InstallationManager();
19747 }
19748
19749
19750
19751
19752
19753
19754 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
19755 {
19756 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
19757 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
19758 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
19759 $im->addInstaller(new Installer\MetapackageInstaller($io));
19760 }
19761
19762
19763
19764
19765
19766 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
19767 {
19768 foreach ($repo->getPackages() as $package) {
19769 if (!$im->isPackageInstalled($repo, $package)) {
19770 $repo->removePackage($package);
19771 }
19772 }
19773 }
19774
19775
19776
19777
19778
19779
19780
19781
19782 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
19783 {
19784 $factory = new static();
19785
19786 return $factory->createComposer($io, $config, $disablePlugins);
19787 }
19788
19789
19790
19791
19792
19793
19794
19795 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
19796 {
19797 static $warned = false;
19798 $disableTls = false;
19799 if ($config && $config->get('disable-tls') === true) {
19800 if (!$warned) {
19801 $io->writeError('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
19802 }
19803 $warned = true;
19804 $disableTls = true;
19805 } elseif (!extension_loaded('openssl')) {
19806 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
19807 . '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.');
19808 }
19809 $remoteFilesystemOptions = array();
19810 if ($disableTls === false) {
19811 if ($config && $config->get('cafile')) {
19812 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
19813 }
19814 if ($config && $config->get('capath')) {
19815 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
19816 }
19817 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
19818 }
19819 try {
19820 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
19821 } catch (TransportException $e) {
19822 if (false !== strpos($e->getMessage(), 'cafile')) {
19823 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
19824 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
19825 if (PHP_VERSION_ID < 50600) {
19826 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
19827 }
19828 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
19829 }
19830 throw $e;
19831 }
19832
19833 return $remoteFilesystem;
19834 }
19835
19836
19837
19838
19839 private static function useXdg()
19840 {
19841 foreach (array_keys($_SERVER) as $key) {
19842 if (substr($key, 0, 4) === 'XDG_') {
19843 return true;
19844 }
19845 }
19846
19847 return false;
19848 }
19849
19850
19851
19852
19853
19854 private static function getUserDir()
19855 {
19856 $home = getenv('HOME');
19857 if (!$home) {
19858 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
19859 }
19860
19861 return rtrim(strtr($home, '\\', '/'), '/');
19862 }
19863 }
19864 <?php
19865
19866
19867
19868
19869
19870
19871
19872
19873
19874
19875
19876 namespace Composer\IO;
19877
19878 use Composer\Config;
19879 use Composer\Util\ProcessExecutor;
19880 use Psr\Log\LoggerInterface;
19881 use Psr\Log\LogLevel;
19882
19883 abstract class BaseIO implements IOInterface, LoggerInterface
19884 {
19885 protected $authentications = array();
19886
19887
19888
19889
19890 public function getAuthentications()
19891 {
19892 return $this->authentications;
19893 }
19894
19895
19896
19897
19898 public function resetAuthentications()
19899 {
19900 $this->authentications = array();
19901 }
19902
19903
19904
19905
19906 public function hasAuthentication($repositoryName)
19907 {
19908 return isset($this->authentications[$repositoryName]);
19909 }
19910
19911
19912
19913
19914 public function getAuthentication($repositoryName)
19915 {
19916 if (isset($this->authentications[$repositoryName])) {
19917 return $this->authentications[$repositoryName];
19918 }
19919
19920 return array('username' => null, 'password' => null);
19921 }
19922
19923
19924
19925
19926 public function setAuthentication($repositoryName, $username, $password = null)
19927 {
19928 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
19929 }
19930
19931
19932
19933
19934 public function writeRaw($messages, $newline = true, $verbosity = self::NORMAL)
19935 {
19936 $this->write($messages, $newline, $verbosity);
19937 }
19938
19939
19940
19941
19942 public function writeErrorRaw($messages, $newline = true, $verbosity = self::NORMAL)
19943 {
19944 $this->writeError($messages, $newline, $verbosity);
19945 }
19946
19947
19948
19949
19950
19951
19952
19953
19954 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
19955 {
19956 if ($this->hasAuthentication($repositoryName)) {
19957 $auth = $this->getAuthentication($repositoryName);
19958 if ($auth['username'] === $username && $auth['password'] === $password) {
19959 return;
19960 }
19961
19962 $this->writeError(
19963 sprintf(
19964 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
19965 $repositoryName
19966 )
19967 );
19968 }
19969 $this->setAuthentication($repositoryName, $username, $password);
19970 }
19971
19972
19973
19974
19975 public function loadConfiguration(Config $config)
19976 {
19977 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
19978 $githubOauth = $config->get('github-oauth') ?: array();
19979 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
19980 $gitlabToken = $config->get('gitlab-token') ?: array();
19981 $httpBasic = $config->get('http-basic') ?: array();
19982
19983
19984
19985 foreach ($bitbucketOauth as $domain => $cred) {
19986 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
19987 }
19988
19989 foreach ($githubOauth as $domain => $token) {
19990 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
19991 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
19992 }
19993 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
19994 }
19995
19996 foreach ($gitlabOauth as $domain => $token) {
19997 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
19998 }
19999
20000 foreach ($gitlabToken as $domain => $token) {
20001 $this->checkAndSetAuthentication($domain, $token, 'private-token');
20002 }
20003
20004
20005  foreach ($httpBasic as $domain => $cred) {
20006 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
20007 }
20008
20009
20010  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
20011 }
20012
20013
20014
20015
20016
20017
20018
20019
20020 public function emergency($message, array $context = array())
20021 {
20022 return $this->log(LogLevel::EMERGENCY, $message, $context);
20023 }
20024
20025
20026
20027
20028
20029
20030
20031
20032
20033
20034
20035 public function alert($message, array $context = array())
20036 {
20037 return $this->log(LogLevel::ALERT, $message, $context);
20038 }
20039
20040
20041
20042
20043
20044
20045
20046
20047
20048
20049 public function critical($message, array $context = array())
20050 {
20051 return $this->log(LogLevel::CRITICAL, $message, $context);
20052 }
20053
20054
20055
20056
20057
20058
20059
20060
20061
20062 public function error($message, array $context = array())
20063 {
20064 return $this->log(LogLevel::ERROR, $message, $context);
20065 }
20066
20067
20068
20069
20070
20071
20072
20073
20074
20075
20076
20077 public function warning($message, array $context = array())
20078 {
20079 return $this->log(LogLevel::WARNING, $message, $context);
20080 }
20081
20082
20083
20084
20085
20086
20087
20088
20089 public function notice($message, array $context = array())
20090 {
20091 return $this->log(LogLevel::NOTICE, $message, $context);
20092 }
20093
20094
20095
20096
20097
20098
20099
20100
20101
20102
20103 public function info($message, array $context = array())
20104 {
20105 return $this->log(LogLevel::INFO, $message, $context);
20106 }
20107
20108
20109
20110
20111
20112
20113
20114
20115 public function debug($message, array $context = array())
20116 {
20117 return $this->log(LogLevel::DEBUG, $message, $context);
20118 }
20119
20120
20121
20122
20123
20124
20125
20126
20127
20128 public function log($level, $message, array $context = array())
20129 {
20130 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
20131 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
20132 } elseif ($level === LogLevel::WARNING) {
20133 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
20134 } elseif ($level === LogLevel::NOTICE) {
20135 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
20136 } elseif ($level === LogLevel::INFO) {
20137 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
20138 } else {
20139 $this->writeError($message, true, self::DEBUG);
20140 }
20141 }
20142 }
20143 <?php
20144
20145
20146
20147
20148
20149
20150
20151
20152
20153
20154
20155 namespace Composer\IO;
20156
20157 use Symfony\Component\Console\Helper\QuestionHelper;
20158 use Symfony\Component\Console\Output\StreamOutput;
20159 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
20160 use Symfony\Component\Console\Input\StreamableInputInterface;
20161 use Symfony\Component\Console\Input\StringInput;
20162 use Symfony\Component\Console\Helper\HelperSet;
20163
20164
20165
20166
20167 class BufferIO extends ConsoleIO
20168 {
20169
20170
20171
20172
20173
20174 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
20175 {
20176 $input = new StringInput($input);
20177 $input->setInteractive(false);
20178
20179 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
20180
20181 parent::__construct($input, $output, new HelperSet(array(
20182 new QuestionHelper(),
20183 )));
20184 }
20185
20186 public function getOutput()
20187 {
20188 fseek($this->output->getStream(), 0);
20189
20190 $output = stream_get_contents($this->output->getStream());
20191
20192 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
20193 $pre = strip_tags($matches[1]);
20194
20195 if (strlen($pre) === strlen($matches[2])) {
20196 return '';
20197 }
20198
20199
20200  return rtrim($matches[1])."\n";
20201 }, $output);
20202
20203 return $output;
20204 }
20205
20206 public function setUserInputs(array $inputs)
20207 {
20208 if (!$this->input instanceof StreamableInputInterface) {
20209 throw new \RuntimeException('Setting the user inputs requires at least the version 3.2 of the symfony/console component.');
20210 }
20211
20212 $this->input->setStream($this->createStream($inputs));
20213 $this->input->setInteractive(true);
20214 }
20215
20216 private function createStream(array $inputs)
20217 {
20218 $stream = fopen('php://memory', 'r+', false);
20219
20220 foreach ($inputs as $input) {
20221 fwrite($stream, $input.PHP_EOL);
20222 }
20223
20224 rewind($stream);
20225
20226 return $stream;
20227 }
20228 }
20229 <?php
20230
20231
20232
20233
20234
20235
20236
20237
20238
20239
20240
20241 namespace Composer\IO;
20242
20243 use Composer\Question\StrictConfirmationQuestion;
20244 use Symfony\Component\Console\Helper\HelperSet;
20245 use Symfony\Component\Console\Input\InputInterface;
20246 use Symfony\Component\Console\Output\ConsoleOutputInterface;
20247 use Symfony\Component\Console\Output\OutputInterface;
20248 use Symfony\Component\Console\Question\ChoiceQuestion;
20249 use Symfony\Component\Console\Question\Question;
20250
20251
20252
20253
20254
20255
20256
20257 class ConsoleIO extends BaseIO
20258 {
20259
20260 protected $input;
20261
20262 protected $output;
20263
20264 protected $helperSet;
20265
20266 protected $lastMessage;
20267
20268 protected $lastMessageErr;
20269
20270
20271 private $startTime;
20272
20273 private $verbosityMap;
20274
20275
20276
20277
20278
20279
20280
20281
20282 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
20283 {
20284 $this->input = $input;
20285 $this->output = $output;
20286 $this->helperSet = $helperSet;
20287 $this->verbosityMap = array(
20288 self::QUIET => OutputInterface::VERBOSITY_QUIET,
20289 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
20290 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
20291 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
20292 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
20293 );
20294 }
20295
20296
20297
20298
20299 public function enableDebugging($startTime)
20300 {
20301 $this->startTime = $startTime;
20302 }
20303
20304
20305
20306
20307 public function isInteractive()
20308 {
20309 return $this->input->isInteractive();
20310 }
20311
20312
20313
20314
20315 public function isDecorated()
20316 {
20317 return $this->output->isDecorated();
20318 }
20319
20320
20321
20322
20323 public function isVerbose()
20324 {
20325 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
20326 }
20327
20328
20329
20330
20331 public function isVeryVerbose()
20332 {
20333 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
20334 }
20335
20336
20337
20338
20339 public function isDebug()
20340 {
20341 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
20342 }
20343
20344
20345
20346
20347 public function write($messages, $newline = true, $verbosity = self::NORMAL)
20348 {
20349 $this->doWrite($messages, $newline, false, $verbosity);
20350 }
20351
20352
20353
20354
20355 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
20356 {
20357 $this->doWrite($messages, $newline, true, $verbosity);
20358 }
20359
20360
20361
20362
20363 public function writeRaw($messages, $newline = true, $verbosity = self::NORMAL)
20364 {
20365 $this->doWrite($messages, $newline, false, $verbosity, true);
20366 }
20367
20368
20369
20370
20371 public function writeErrorRaw($messages, $newline = true, $verbosity = self::NORMAL)
20372 {
20373 $this->doWrite($messages, $newline, true, $verbosity, true);
20374 }
20375
20376
20377
20378
20379
20380
20381
20382 private function doWrite($messages, $newline, $stderr, $verbosity, $raw = false)
20383 {
20384 $sfVerbosity = $this->verbosityMap[$verbosity];
20385 if ($sfVerbosity > $this->output->getVerbosity()) {
20386 return;
20387 }
20388
20389
20390  
20391  
20392  if (OutputInterface::VERBOSITY_QUIET === 0) {
20393 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
20394 }
20395
20396 if ($raw) {
20397 if ($sfVerbosity === OutputInterface::OUTPUT_NORMAL) {
20398 $sfVerbosity = OutputInterface::OUTPUT_RAW;
20399 } else {
20400 $sfVerbosity |= OutputInterface::OUTPUT_RAW;
20401 }
20402 }
20403
20404 if (null !== $this->startTime) {
20405 $memoryUsage = memory_get_usage() / 1024 / 1024;
20406 $timeSpent = microtime(true) - $this->startTime;
20407 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
20408 return sprintf('[%.1fMiB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
20409 }, (array) $messages);
20410 }
20411
20412 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
20413 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
20414 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
20415
20416 return;
20417 }
20418
20419 $this->output->write($messages, $newline, $sfVerbosity);
20420 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
20421 }
20422
20423
20424
20425
20426 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
20427 {
20428 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
20429 }
20430
20431
20432
20433
20434 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
20435 {
20436 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
20437 }
20438
20439
20440
20441
20442
20443
20444
20445
20446 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
20447 {
20448
20449  $messages = implode($newline ? "\n" : '', (array) $messages);
20450
20451
20452  if (!isset($size)) {
20453
20454  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
20455 }
20456
20457  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
20458
20459
20460  $this->doWrite($messages, false, $stderr, $verbosity);
20461
20462
20463  
20464  
20465  $fill = $size - strlen(strip_tags($messages));
20466 if ($fill > 0) {
20467
20468  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
20469
20470  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
20471 }
20472
20473 if ($newline) {
20474 $this->doWrite('', true, $stderr, $verbosity);
20475 }
20476
20477 if ($stderr) {
20478 $this->lastMessageErr = $messages;
20479 } else {
20480 $this->lastMessage = $messages;
20481 }
20482 }
20483
20484
20485
20486
20487 public function ask($question, $default = null)
20488 {
20489
20490 $helper = $this->helperSet->get('question');
20491 $question = new Question($question, $default);
20492
20493 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20494 }
20495
20496
20497
20498
20499 public function askConfirmation($question, $default = true)
20500 {
20501
20502 $helper = $this->helperSet->get('question');
20503 $question = new StrictConfirmationQuestion($question, $default);
20504
20505 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20506 }
20507
20508
20509
20510
20511 public function askAndValidate($question, $validator, $attempts = null, $default = null)
20512 {
20513
20514 $helper = $this->helperSet->get('question');
20515 $question = new Question($question, $default);
20516 $question->setValidator($validator);
20517 $question->setMaxAttempts($attempts);
20518
20519 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20520 }
20521
20522
20523
20524
20525 public function askAndHideAnswer($question)
20526 {
20527
20528 $helper = $this->helperSet->get('question');
20529 $question = new Question($question);
20530 $question->setHidden(true);
20531
20532 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20533 }
20534
20535
20536
20537
20538 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
20539 {
20540
20541 $helper = $this->helperSet->get('question');
20542 $question = new ChoiceQuestion($question, $choices, $default);
20543 $question->setMaxAttempts($attempts ?: null); 
20544  $question->setErrorMessage($errorMessage);
20545 $question->setMultiselect($multiselect);
20546
20547 $result = $helper->ask($this->input, $this->getErrorOutput(), $question);
20548
20549 if (!is_array($result)) {
20550 return (string) array_search($result, $choices, true);
20551 }
20552
20553 $results = array();
20554 foreach ($choices as $index => $choice) {
20555 if (in_array($choice, $result, true)) {
20556 $results[] = (string) $index;
20557 }
20558 }
20559
20560 return $results;
20561 }
20562
20563
20564
20565
20566 private function getErrorOutput()
20567 {
20568 if ($this->output instanceof ConsoleOutputInterface) {
20569 return $this->output->getErrorOutput();
20570 }
20571
20572 return $this->output;
20573 }
20574 }
20575 <?php
20576
20577
20578
20579
20580
20581
20582
20583
20584
20585
20586
20587 namespace Composer\IO;
20588
20589 use Composer\Config;
20590
20591
20592
20593
20594
20595
20596 interface IOInterface
20597 {
20598 const QUIET = 1;
20599 const NORMAL = 2;
20600 const VERBOSE = 4;
20601 const VERY_VERBOSE = 8;
20602 const DEBUG = 16;
20603
20604
20605
20606
20607
20608
20609 public function isInteractive();
20610
20611
20612
20613
20614
20615
20616 public function isVerbose();
20617
20618
20619
20620
20621
20622
20623 public function isVeryVerbose();
20624
20625
20626
20627
20628
20629
20630 public function isDebug();
20631
20632
20633
20634
20635
20636
20637 public function isDecorated();
20638
20639
20640
20641
20642
20643
20644
20645
20646 public function write($messages, $newline = true, $verbosity = self::NORMAL);
20647
20648
20649
20650
20651
20652
20653
20654
20655 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
20656
20657
20658
20659
20660
20661
20662
20663
20664
20665 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
20666
20667
20668
20669
20670
20671
20672
20673
20674
20675 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
20676
20677
20678
20679
20680
20681
20682
20683
20684
20685
20686 public function ask($question, $default = null);
20687
20688
20689
20690
20691
20692
20693
20694
20695
20696
20697
20698 public function askConfirmation($question, $default = true);
20699
20700
20701
20702
20703
20704
20705
20706
20707
20708
20709
20710
20711
20712
20713
20714
20715 public function askAndValidate($question, $validator, $attempts = null, $default = null);
20716
20717
20718
20719
20720
20721
20722
20723
20724 public function askAndHideAnswer($question);
20725
20726
20727
20728
20729
20730
20731
20732
20733
20734
20735
20736
20737
20738
20739 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
20740
20741
20742
20743
20744
20745
20746 public function getAuthentications();
20747
20748
20749
20750
20751
20752
20753
20754
20755 public function hasAuthentication($repositoryName);
20756
20757
20758
20759
20760
20761
20762
20763
20764 public function getAuthentication($repositoryName);
20765
20766
20767
20768
20769
20770
20771
20772
20773 public function setAuthentication($repositoryName, $username, $password = null);
20774
20775
20776
20777
20778
20779
20780 public function loadConfiguration(Config $config);
20781 }
20782 <?php
20783
20784
20785
20786
20787
20788
20789
20790
20791
20792
20793
20794 namespace Composer\IO;
20795
20796
20797
20798
20799
20800
20801 class NullIO extends BaseIO
20802 {
20803
20804
20805
20806 public function isInteractive()
20807 {
20808 return false;
20809 }
20810
20811
20812
20813
20814 public function isVerbose()
20815 {
20816 return false;
20817 }
20818
20819
20820
20821
20822 public function isVeryVerbose()
20823 {
20824 return false;
20825 }
20826
20827
20828
20829
20830 public function isDebug()
20831 {
20832 return false;
20833 }
20834
20835
20836
20837
20838 public function isDecorated()
20839 {
20840 return false;
20841 }
20842
20843
20844
20845
20846 public function write($messages, $newline = true, $verbosity = self::NORMAL)
20847 {
20848 }
20849
20850
20851
20852
20853 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
20854 {
20855 }
20856
20857
20858
20859
20860 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
20861 {
20862 }
20863
20864
20865
20866
20867 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
20868 {
20869 }
20870
20871
20872
20873
20874 public function ask($question, $default = null)
20875 {
20876 return $default;
20877 }
20878
20879
20880
20881
20882 public function askConfirmation($question, $default = true)
20883 {
20884 return $default;
20885 }
20886
20887
20888
20889
20890 public function askAndValidate($question, $validator, $attempts = false, $default = null)
20891 {
20892 return $default;
20893 }
20894
20895
20896
20897
20898 public function askAndHideAnswer($question)
20899 {
20900 return null;
20901 }
20902
20903
20904
20905
20906 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
20907 {
20908 return $default;
20909 }
20910 }
20911 <?php
20912
20913
20914
20915
20916
20917
20918
20919
20920
20921
20922
20923 namespace Composer;
20924
20925 use Composer\Autoload\AutoloadGenerator;
20926 use Composer\DependencyResolver\DefaultPolicy;
20927 use Composer\DependencyResolver\Operation\UpdateOperation;
20928 use Composer\DependencyResolver\Operation\InstallOperation;
20929 use Composer\DependencyResolver\Operation\UninstallOperation;
20930 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
20931 use Composer\DependencyResolver\Operation\OperationInterface;
20932 use Composer\DependencyResolver\PolicyInterface;
20933 use Composer\DependencyResolver\Pool;
20934 use Composer\DependencyResolver\Request;
20935 use Composer\DependencyResolver\Rule;
20936 use Composer\DependencyResolver\Solver;
20937 use Composer\DependencyResolver\SolverProblemsException;
20938 use Composer\Downloader\DownloadManager;
20939 use Composer\EventDispatcher\EventDispatcher;
20940 use Composer\Installer\InstallationManager;
20941 use Composer\Installer\InstallerEvents;
20942 use Composer\Installer\NoopInstaller;
20943 use Composer\Installer\SuggestedPackagesReporter;
20944 use Composer\IO\IOInterface;
20945 use Composer\Package\AliasPackage;
20946 use Composer\Package\BasePackage;
20947 use Composer\Package\CompletePackage;
20948 use Composer\Package\Link;
20949 use Composer\Package\Loader\ArrayLoader;
20950 use Composer\Package\Dumper\ArrayDumper;
20951 use Composer\Semver\Constraint\Constraint;
20952 use Composer\Package\Locker;
20953 use Composer\Package\PackageInterface;
20954 use Composer\Package\RootPackageInterface;
20955 use Composer\Repository\CompositeRepository;
20956 use Composer\Repository\InstalledArrayRepository;
20957 use Composer\Repository\PlatformRepository;
20958 use Composer\Repository\RepositoryInterface;
20959 use Composer\Repository\RepositoryManager;
20960 use Composer\Repository\WritableRepositoryInterface;
20961 use Composer\Script\ScriptEvents;
20962
20963
20964
20965
20966
20967
20968
20969 class Installer
20970 {
20971
20972
20973
20974 protected $io;
20975
20976
20977
20978
20979 protected $config;
20980
20981
20982
20983
20984 protected $package;
20985
20986
20987
20988
20989 protected $downloadManager;
20990
20991
20992
20993
20994 protected $repositoryManager;
20995
20996
20997
20998
20999 protected $locker;
21000
21001
21002
21003
21004 protected $installationManager;
21005
21006
21007
21008
21009 protected $eventDispatcher;
21010
21011
21012
21013
21014 protected $autoloadGenerator;
21015
21016 protected $preferSource = false;
21017 protected $preferDist = false;
21018 protected $optimizeAutoloader = false;
21019 protected $classMapAuthoritative = false;
21020 protected $apcuAutoloader = false;
21021 protected $devMode = false;
21022 protected $dryRun = false;
21023 protected $verbose = false;
21024 protected $update = false;
21025 protected $dumpAutoloader = true;
21026 protected $runScripts = true;
21027 protected $ignorePlatformReqs = false;
21028 protected $preferStable = false;
21029 protected $preferLowest = false;
21030 protected $skipSuggest = false;
21031 protected $writeLock = true;
21032 protected $executeOperations = true;
21033
21034
21035
21036
21037
21038
21039 protected $updateWhitelist = null;
21040 protected $whitelistDependencies = false; 
21041  protected $whitelistAllDependencies = false;
21042
21043
21044
21045
21046 protected $suggestedPackagesReporter;
21047
21048
21049
21050
21051 protected $additionalInstalledRepository;
21052
21053
21054
21055
21056
21057
21058
21059
21060
21061
21062
21063
21064
21065
21066 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
21067 {
21068 $this->io = $io;
21069 $this->config = $config;
21070 $this->package = $package;
21071 $this->downloadManager = $downloadManager;
21072 $this->repositoryManager = $repositoryManager;
21073 $this->locker = $locker;
21074 $this->installationManager = $installationManager;
21075 $this->eventDispatcher = $eventDispatcher;
21076 $this->autoloadGenerator = $autoloadGenerator;
21077 }
21078
21079
21080
21081
21082
21083
21084
21085 public function run()
21086 {
21087
21088  
21089  
21090  
21091  gc_collect_cycles();
21092 gc_disable();
21093
21094
21095  if (!$this->update && !$this->locker->isLocked()) {
21096 $this->update = true;
21097 }
21098
21099 if ($this->dryRun) {
21100 $this->verbose = true;
21101 $this->runScripts = false;
21102 $this->executeOperations = false;
21103 $this->writeLock = false;
21104 $this->dumpAutoloader = false;
21105 $this->installationManager->addInstaller(new NoopInstaller);
21106 $this->mockLocalRepositories($this->repositoryManager);
21107 }
21108
21109 if ($this->runScripts) {
21110 $devMode = (int) $this->devMode;
21111 putenv("COMPOSER_DEV_MODE=$devMode");
21112
21113
21114  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
21115 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
21116 }
21117
21118 $this->downloadManager->setPreferSource($this->preferSource);
21119 $this->downloadManager->setPreferDist($this->preferDist);
21120
21121
21122  $localRepo = $this->repositoryManager->getLocalRepository();
21123 if ($this->update) {
21124 $platformOverrides = $this->config->get('platform') ?: array();
21125 } else {
21126 $platformOverrides = $this->locker->getPlatformOverrides();
21127 }
21128 $platformRepo = new PlatformRepository(array(), $platformOverrides);
21129 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
21130
21131 $aliases = $this->getRootAliases();
21132 $this->aliasPlatformPackages($platformRepo, $aliases);
21133
21134 if (!$this->suggestedPackagesReporter) {
21135 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
21136 }
21137
21138 try {
21139 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
21140 if ($res !== 0) {
21141 return $res;
21142 }
21143 } catch (\Exception $e) {
21144 if ($this->executeOperations) {
21145 $this->installationManager->notifyInstalls($this->io);
21146 }
21147
21148 throw $e;
21149 }
21150 if ($this->executeOperations) {
21151 $this->installationManager->notifyInstalls($this->io);
21152 }
21153
21154
21155  if ($this->devMode && !$this->skipSuggest) {
21156 $this->suggestedPackagesReporter->output($installedRepo);
21157 }
21158
21159
21160  foreach ($localRepo->getPackages() as $package) {
21161 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
21162 continue;
21163 }
21164
21165 $replacement = is_string($package->getReplacementPackage())
21166 ? 'Use ' . $package->getReplacementPackage() . ' instead'
21167 : 'No replacement was suggested';
21168
21169 $this->io->writeError(
21170 sprintf(
21171 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
21172 $package->getPrettyName(),
21173 $replacement
21174 )
21175 );
21176 }
21177
21178
21179  if ($this->update && $this->writeLock) {
21180 $localRepo->reload();
21181
21182 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
21183 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
21184
21185 $updatedLock = $this->locker->setLockData(
21186 array_diff($localRepo->getCanonicalPackages(), $devPackages),
21187 $devPackages,
21188 $platformReqs,
21189 $platformDevReqs,
21190 $aliases,
21191 $this->package->getMinimumStability(),
21192 $this->package->getStabilityFlags(),
21193 $this->preferStable || $this->package->getPreferStable(),
21194 $this->preferLowest,
21195 $this->config->get('platform') ?: array()
21196 );
21197 if ($updatedLock) {
21198 $this->io->writeError('<info>Writing lock file</info>');
21199 }
21200 }
21201
21202 if ($this->dumpAutoloader) {
21203
21204  if ($this->optimizeAutoloader) {
21205 $this->io->writeError('<info>Generating optimized autoload files</info>');
21206 } else {
21207 $this->io->writeError('<info>Generating autoload files</info>');
21208 }
21209
21210 $this->autoloadGenerator->setDevMode($this->devMode);
21211 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
21212 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
21213 $this->autoloadGenerator->setRunScripts($this->runScripts);
21214 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
21215 }
21216
21217 if ($this->executeOperations) {
21218
21219  foreach ($localRepo->getPackages() as $package) {
21220 $this->installationManager->ensureBinariesPresence($package);
21221 }
21222
21223 $vendorDir = $this->config->get('vendor-dir');
21224 if (is_dir($vendorDir)) {
21225
21226  
21227  @touch($vendorDir);
21228 }
21229 }
21230
21231 if ($this->runScripts) {
21232
21233  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
21234 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
21235 }
21236
21237
21238  if (!defined('HHVM_VERSION')) {
21239 gc_enable();
21240 }
21241
21242 return 0;
21243 }
21244
21245
21246
21247
21248
21249
21250
21251
21252 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
21253 {
21254
21255  $lockedRepository = null;
21256 $repositories = null;
21257
21258
21259  
21260  
21261  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
21262 try {
21263 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
21264 } catch (\RuntimeException $e) {
21265
21266  if ($this->package->getDevRequires()) {
21267 throw $e;
21268 }
21269
21270  $lockedRepository = $this->locker->getLockedRepository();
21271 }
21272 }
21273
21274 $this->whitelistUpdateDependencies(
21275 $lockedRepository ?: $localRepo,
21276 $this->package->getRequires(),
21277 $this->package->getDevRequires()
21278 );
21279
21280 $this->io->writeError('<info>Loading composer repositories with package information</info>');
21281
21282
21283  $policy = $this->createPolicy();
21284 $pool = $this->createPool($this->update ? null : $lockedRepository);
21285 $pool->addRepository($installedRepo, $aliases);
21286 if ($this->update) {
21287 $repositories = $this->repositoryManager->getRepositories();
21288 foreach ($repositories as $repository) {
21289 $pool->addRepository($repository, $aliases);
21290 }
21291 }
21292
21293  
21294  
21295  if ($lockedRepository) {
21296 $pool->addRepository($lockedRepository, $aliases);
21297 }
21298
21299
21300  $request = $this->createRequest($this->package, $platformRepo);
21301
21302 if ($this->update) {
21303
21304  $removedUnstablePackages = array();
21305 foreach ($localRepo->getPackages() as $package) {
21306 if (
21307 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
21308 && $this->installationManager->isPackageInstalled($localRepo, $package)
21309 ) {
21310 $removedUnstablePackages[$package->getName()] = true;
21311 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
21312 }
21313 }
21314
21315 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
21316
21317 $request->updateAll();
21318
21319 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
21320
21321 foreach ($links as $link) {
21322 $request->install($link->getTarget(), $link->getConstraint());
21323 }
21324
21325
21326  
21327  if ($this->updateWhitelist) {
21328 $currentPackages = $this->getCurrentPackages($installedRepo);
21329
21330
21331  $candidates = array();
21332 foreach ($links as $link) {
21333 $candidates[$link->getTarget()] = true;
21334 $rootRequires[$link->getTarget()] = $link;
21335 }
21336 foreach ($currentPackages as $package) {
21337 $candidates[$package->getName()] = true;
21338 }
21339
21340
21341  foreach ($candidates as $candidate => $dummy) {
21342 foreach ($currentPackages as $curPackage) {
21343 if ($curPackage->getName() === $candidate) {
21344 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
21345 $constraint = new Constraint('=', $curPackage->getVersion());
21346 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
21347 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
21348 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
21349 $request->install($curPackage->getName(), $constraint);
21350 }
21351 break;
21352 }
21353 }
21354 }
21355 }
21356 } else {
21357 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
21358
21359 if (!$this->locker->isFresh()) {
21360 $this->io->writeError('<warning>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 <package name>`.</warning>', true, IOInterface::QUIET);
21361 }
21362
21363 foreach ($lockedRepository->getPackages() as $package) {
21364 $version = $package->getVersion();
21365 if (isset($aliases[$package->getName()][$version])) {
21366 $version = $aliases[$package->getName()][$version]['alias_normalized'];
21367 }
21368 $constraint = new Constraint('=', $version);
21369 $constraint->setPrettyString($package->getPrettyVersion());
21370 $request->install($package->getName(), $constraint);
21371 }
21372
21373 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
21374 $request->install($link->getTarget(), $link->getConstraint());
21375 }
21376 }
21377
21378
21379  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
21380
21381
21382  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
21383 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
21384 try {
21385 $operations = $solver->solve($request, $this->ignorePlatformReqs);
21386 $ruleSetSize = $solver->getRuleSetSize();
21387 $solver = null;
21388 } catch (SolverProblemsException $e) {
21389 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
21390 $this->io->writeError($e->getMessage());
21391 if ($this->update && !$this->devMode) {
21392 $this->io->writeError('<warning>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.</warning>', true, IOInterface::QUIET);
21393 }
21394
21395 return array(max(1, $e->getCode()), array());
21396 }
21397
21398
21399  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
21400
21401 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
21402
21403 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
21404 $this->io->writeError("Analyzed ".$ruleSetSize." rules to resolve dependencies", true, IOInterface::VERBOSE);
21405
21406
21407  if (!$operations) {
21408 $this->io->writeError('Nothing to install or update');
21409 }
21410
21411 $operations = $this->movePluginsToFront($operations);
21412 $operations = $this->moveUninstallsToFront($operations);
21413
21414
21415  
21416  if ($this->update) {
21417 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
21418 if (!$this->devMode) {
21419 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
21420 }
21421 } else {
21422 $devPackages = null;
21423 }
21424
21425 if ($operations) {
21426 $installs = $updates = $uninstalls = array();
21427 foreach ($operations as $operation) {
21428 if ($operation instanceof InstallOperation) {
21429 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
21430 } elseif ($operation instanceof UpdateOperation) {
21431 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
21432 } elseif ($operation instanceof UninstallOperation) {
21433 $uninstalls[] = $operation->getPackage()->getPrettyName();
21434 }
21435 }
21436
21437 $this->io->writeError(sprintf(
21438 "<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
21439 count($installs),
21440 1 === count($installs) ? '' : 's',
21441 count($updates),
21442 1 === count($updates) ? '' : 's',
21443 count($uninstalls),
21444 1 === count($uninstalls) ? '' : 's'
21445 ));
21446 if ($installs) {
21447 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
21448 }
21449 if ($updates) {
21450 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
21451 }
21452 if ($uninstalls) {
21453 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
21454 }
21455 }
21456
21457 foreach ($operations as $operation) {
21458
21459  $jobType = $operation->getJobType();
21460 if ('install' === $jobType) {
21461 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
21462 }
21463
21464
21465  if ($this->update) {
21466 $package = null;
21467 if ('update' === $jobType) {
21468 $package = $operation->getTargetPackage();
21469 } elseif ('install' === $jobType) {
21470 $package = $operation->getPackage();
21471 }
21472 if ($package && $package->isDev()) {
21473 $references = $this->package->getReferences();
21474 if (isset($references[$package->getName()])) {
21475 $this->updateInstallReferences($package, $references[$package->getName()]);
21476 }
21477 }
21478 if ('update' === $jobType) {
21479 $targetPackage = $operation->getTargetPackage();
21480 if ($targetPackage->isDev()) {
21481 $initialPackage = $operation->getInitialPackage();
21482 if ($targetPackage->getVersion() === $initialPackage->getVersion()
21483 && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference())
21484 && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference())
21485 ) {
21486 $this->io->writeError('  - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG);
21487 $this->io->writeError('', true, IOInterface::DEBUG);
21488
21489 continue;
21490 }
21491 }
21492 }
21493 }
21494
21495 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($jobType);
21496 if (defined($event) && $this->runScripts) {
21497 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
21498 }
21499
21500
21501  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
21502 $this->io->writeError('  - ' . $operation);
21503 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
21504 $this->io->writeError('  - ' . $operation);
21505 }
21506
21507 $this->installationManager->execute($localRepo, $operation);
21508
21509
21510  if ($this->verbose && $this->io->isVeryVerbose() && in_array($jobType, array('install', 'update'))) {
21511 $reason = $operation->getReason();
21512 if ($reason instanceof Rule) {
21513 switch ($reason->getReason()) {
21514 case Rule::RULE_JOB_INSTALL:
21515 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
21516 $this->io->writeError('');
21517 break;
21518 case Rule::RULE_PACKAGE_REQUIRES:
21519 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
21520 $this->io->writeError('');
21521 break;
21522 }
21523 }
21524 }
21525
21526 if ($this->executeOperations || $this->writeLock) {
21527 $localRepo->write();
21528 }
21529
21530 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($jobType);
21531 if (defined($event) && $this->runScripts) {
21532 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
21533 }
21534 }
21535
21536 if ($this->executeOperations) {
21537
21538  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
21539 $localRepo->write();
21540 }
21541
21542 return array(0, $devPackages);
21543 }
21544
21545
21546
21547
21548
21549
21550
21551
21552
21553
21554
21555 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
21556 {
21557 if (!$this->package->getDevRequires()) {
21558 return array();
21559 }
21560
21561
21562  $tempLocalRepo = clone $localRepo;
21563 foreach ($operations as $operation) {
21564 switch ($operation->getJobType()) {
21565 case 'install':
21566 case 'markAliasInstalled':
21567 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
21568 $tempLocalRepo->addPackage(clone $operation->getPackage());
21569 }
21570 break;
21571
21572 case 'uninstall':
21573 case 'markAliasUninstalled':
21574 $tempLocalRepo->removePackage($operation->getPackage());
21575 break;
21576
21577 case 'update':
21578 $tempLocalRepo->removePackage($operation->getInitialPackage());
21579 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
21580 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
21581 }
21582 break;
21583
21584 default:
21585 throw new \LogicException('Unknown type: '.$operation->getJobType());
21586 }
21587 }
21588
21589
21590  
21591  
21592  $localRepo = new InstalledArrayRepository(array());
21593 $loader = new ArrayLoader(null, true);
21594 $dumper = new ArrayDumper();
21595 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
21596 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
21597 }
21598 unset($tempLocalRepo, $loader, $dumper);
21599
21600 $policy = $this->createPolicy();
21601 $pool = $this->createPool();
21602 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
21603 $pool->addRepository($installedRepo, $aliases);
21604
21605
21606  $request = $this->createRequest($this->package, $platformRepo);
21607 $request->updateAll();
21608 foreach ($this->package->getRequires() as $link) {
21609 $request->install($link->getTarget(), $link->getConstraint());
21610 }
21611
21612
21613  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
21614 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
21615 $ops = $solver->solve($request, $this->ignorePlatformReqs);
21616 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
21617
21618 $devPackages = array();
21619 foreach ($ops as $op) {
21620 if ($op->getJobType() === 'uninstall') {
21621 $devPackages[] = $op->getPackage();
21622 }
21623 }
21624
21625 return $devPackages;
21626 }
21627
21628
21629
21630
21631 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
21632 {
21633 $finalOps = array();
21634 $packagesToSkip = array();
21635 foreach ($devPackages as $pkg) {
21636 $packagesToSkip[$pkg->getName()] = true;
21637 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
21638 if ($installedDevPkg instanceof AliasPackage) {
21639 $finalOps[] = new MarkAliasUninstalledOperation($installedDevPkg, 'non-dev install removing it');
21640 $installedDevPkg = $installedDevPkg->getAliasOf();
21641 }
21642 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
21643 }
21644 }
21645
21646
21647  foreach ($operations as $op) {
21648 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
21649 if (isset($packagesToSkip[$package->getName()])) {
21650 continue;
21651 }
21652
21653 $finalOps[] = $op;
21654 }
21655
21656 return $finalOps;
21657 }
21658
21659
21660
21661
21662
21663
21664
21665
21666
21667
21668
21669
21670
21671
21672 private function movePluginsToFront(array $operations)
21673 {
21674 $pluginsNoDeps = array();
21675 $pluginsWithDeps = array();
21676 $pluginRequires = array();
21677
21678 foreach (array_reverse($operations, true) as $idx => $op) {
21679 if ($op instanceof InstallOperation) {
21680 $package = $op->getPackage();
21681 } elseif ($op instanceof UpdateOperation) {
21682 $package = $op->getTargetPackage();
21683 } else {
21684 continue;
21685 }
21686
21687
21688  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
21689
21690
21691  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
21692
21693  $requires = array_filter(array_keys($package->getRequires()), function ($req) {
21694 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
21695 });
21696
21697
21698  if ($isPlugin && !count($requires)) {
21699
21700  array_unshift($pluginsNoDeps, $op);
21701 } else {
21702
21703  $pluginRequires = array_merge($pluginRequires, $requires);
21704
21705  array_unshift($pluginsWithDeps, $op);
21706 }
21707
21708 unset($operations[$idx]);
21709 }
21710 }
21711
21712 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
21713 }
21714
21715
21716
21717
21718
21719
21720
21721
21722 private function moveUninstallsToFront(array $operations)
21723 {
21724 $uninstOps = array();
21725 foreach ($operations as $idx => $op) {
21726 if ($op instanceof UninstallOperation) {
21727 $uninstOps[] = $op;
21728 unset($operations[$idx]);
21729 }
21730 }
21731
21732 return array_merge($uninstOps, $operations);
21733 }
21734
21735
21736
21737
21738 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
21739 {
21740
21741  
21742  
21743  $installedRootPackage = clone $this->package;
21744 $installedRootPackage->setRequires(array());
21745 $installedRootPackage->setDevRequires(array());
21746
21747 $repos = array(
21748 $localRepo,
21749 new InstalledArrayRepository(array($installedRootPackage)),
21750 $platformRepo,
21751 );
21752 $installedRepo = new CompositeRepository($repos);
21753 if ($this->additionalInstalledRepository) {
21754 $installedRepo->addRepository($this->additionalInstalledRepository);
21755 }
21756
21757 return $installedRepo;
21758 }
21759
21760
21761
21762
21763
21764 private function createPool(RepositoryInterface $lockedRepository = null)
21765 {
21766 if ($this->update) {
21767 $minimumStability = $this->package->getMinimumStability();
21768 $stabilityFlags = $this->package->getStabilityFlags();
21769
21770 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
21771 } else {
21772 $minimumStability = $this->locker->getMinimumStability();
21773 $stabilityFlags = $this->locker->getStabilityFlags();
21774
21775 $requires = array();
21776 foreach ($lockedRepository->getPackages() as $package) {
21777 $constraint = new Constraint('=', $package->getVersion());
21778 $constraint->setPrettyString($package->getPrettyVersion());
21779 $requires[$package->getName()] = $constraint;
21780 }
21781 }
21782
21783 $rootConstraints = array();
21784 foreach ($requires as $req => $constraint) {
21785
21786  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
21787 continue;
21788 }
21789 if ($constraint instanceof Link) {
21790 $rootConstraints[$req] = $constraint->getConstraint();
21791 } else {
21792 $rootConstraints[$req] = $constraint;
21793 }
21794 }
21795
21796 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
21797 }
21798
21799
21800
21801
21802 private function createPolicy()
21803 {
21804 $preferStable = null;
21805 $preferLowest = null;
21806 if (!$this->update) {
21807 $preferStable = $this->locker->getPreferStable();
21808 $preferLowest = $this->locker->getPreferLowest();
21809 }
21810
21811  
21812  if (null === $preferStable) {
21813 $preferStable = $this->preferStable || $this->package->getPreferStable();
21814 }
21815 if (null === $preferLowest) {
21816 $preferLowest = $this->preferLowest;
21817 }
21818
21819 return new DefaultPolicy($preferStable, $preferLowest);
21820 }
21821
21822
21823
21824
21825
21826
21827 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
21828 {
21829 $request = new Request();
21830
21831 $constraint = new Constraint('=', $rootPackage->getVersion());
21832 $constraint->setPrettyString($rootPackage->getPrettyVersion());
21833 $request->install($rootPackage->getName(), $constraint);
21834
21835 $fixedPackages = $platformRepo->getPackages();
21836 if ($this->additionalInstalledRepository) {
21837 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
21838 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
21839 }
21840
21841
21842  
21843  $provided = $rootPackage->getProvides();
21844 foreach ($fixedPackages as $package) {
21845 $constraint = new Constraint('=', $package->getVersion());
21846 $constraint->setPrettyString($package->getPrettyVersion());
21847
21848
21849  if ($package->getRepository() !== $platformRepo
21850 || !isset($provided[$package->getName()])
21851 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
21852 ) {
21853 $request->fix($package->getName(), $constraint);
21854 }
21855 }
21856
21857 return $request;
21858 }
21859
21860
21861
21862
21863
21864
21865
21866
21867
21868
21869
21870
21871 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
21872 {
21873 if ($task === 'force-updates' && null === $operations) {
21874 throw new \InvalidArgumentException('Missing operations argument');
21875 }
21876 if ($task === 'force-links') {
21877 $operations = array();
21878 }
21879
21880 if ($this->update && $this->updateWhitelist) {
21881 $currentPackages = $this->getCurrentPackages($installedRepo);
21882 }
21883
21884 foreach ($localRepo->getCanonicalPackages() as $package) {
21885
21886  if (!$package->isDev()) {
21887 continue;
21888 }
21889
21890
21891  foreach ($operations as $operation) {
21892 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
21893 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
21894 ) {
21895 continue 2;
21896 }
21897 }
21898
21899 if ($this->update) {
21900
21901  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
21902
21903  foreach ($currentPackages as $curPackage) {
21904 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
21905 if ($task === 'force-links') {
21906 $package->setRequires($curPackage->getRequires());
21907 $package->setConflicts($curPackage->getConflicts());
21908 $package->setProvides($curPackage->getProvides());
21909 $package->setReplaces($curPackage->getReplaces());
21910 } elseif ($task === 'force-updates') {
21911 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
21912 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
21913 ) {
21914 $operations[] = new UpdateOperation($package, $curPackage);
21915 }
21916 }
21917
21918 break;
21919 }
21920 }
21921
21922 continue;
21923 }
21924
21925
21926  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
21927 foreach ($matches as $index => $match) {
21928
21929  if (!in_array($match->getRepository(), $repositories, true)) {
21930 unset($matches[$index]);
21931 continue;
21932 }
21933
21934
21935  if ($match->getName() !== $package->getName()) {
21936 unset($matches[$index]);
21937 continue;
21938 }
21939
21940 $matches[$index] = $match->getId();
21941 }
21942
21943
21944  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
21945 $newPackage = $pool->literalToPackage($matches[0]);
21946
21947 if ($task === 'force-links' && $newPackage) {
21948 $package->setRequires($newPackage->getRequires());
21949 $package->setConflicts($newPackage->getConflicts());
21950 $package->setProvides($newPackage->getProvides());
21951 $package->setReplaces($newPackage->getReplaces());
21952 }
21953
21954 if (
21955 $task === 'force-updates'
21956 && $newPackage
21957 && (
21958 ($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
21959 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
21960 )
21961 ) {
21962 $operations[] = new UpdateOperation($package, $newPackage);
21963
21964 continue;
21965 }
21966 }
21967
21968 if ($task === 'force-updates') {
21969
21970  $references = $this->package->getReferences();
21971
21972 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
21973
21974  $operations[] = new UpdateOperation($package, clone $package);
21975 }
21976 }
21977 } else {
21978
21979  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
21980 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
21981 if ($task === 'force-links') {
21982 $package->setRequires($lockedPackage->getRequires());
21983 $package->setConflicts($lockedPackage->getConflicts());
21984 $package->setProvides($lockedPackage->getProvides());
21985 $package->setReplaces($lockedPackage->getReplaces());
21986 } elseif ($task === 'force-updates') {
21987 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
21988 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
21989 ) {
21990 $operations[] = new UpdateOperation($package, $lockedPackage);
21991 }
21992 }
21993
21994 break;
21995 }
21996 }
21997 }
21998 }
21999
22000 return $operations;
22001 }
22002
22003
22004
22005
22006
22007
22008 private function getCurrentPackages($installedRepo)
22009 {
22010 if ($this->locker->isLocked()) {
22011 try {
22012 return $this->locker->getLockedRepository(true)->getPackages();
22013 } catch (\RuntimeException $e) {
22014
22015  return $this->locker->getLockedRepository()->getPackages();
22016 }
22017 }
22018
22019 return $installedRepo->getPackages();
22020 }
22021
22022
22023
22024
22025 private function getRootAliases()
22026 {
22027 if ($this->update) {
22028 $aliases = $this->package->getAliases();
22029 } else {
22030 $aliases = $this->locker->getAliases();
22031 }
22032
22033 $normalizedAliases = array();
22034
22035 foreach ($aliases as $alias) {
22036 $normalizedAliases[$alias['package']][$alias['version']] = array(
22037 'alias' => $alias['alias'],
22038 'alias_normalized' => $alias['alias_normalized'],
22039 );
22040 }
22041
22042 return $normalizedAliases;
22043 }
22044
22045
22046
22047
22048
22049
22050
22051 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
22052 {
22053 if (!$this->update) {
22054 return;
22055 }
22056
22057 $rootRefs = $this->package->getReferences();
22058
22059 foreach ($localRepo->getCanonicalPackages() as $package) {
22060
22061  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
22062 foreach ($matches as $index => $match) {
22063
22064  if (!in_array($match->getRepository(), $repositories, true)) {
22065 unset($matches[$index]);
22066 continue;
22067 }
22068
22069
22070  if ($match->getName() !== $package->getName()) {
22071 unset($matches[$index]);
22072 continue;
22073 }
22074
22075 $matches[$index] = $match->getId();
22076 }
22077
22078
22079  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
22080 $newPackage = $pool->literalToPackage($matches[0]);
22081
22082
22083  $sourceUrl = $package->getSourceUrl();
22084 $newSourceUrl = $newPackage->getSourceUrl();
22085 $newReference = $newPackage->getSourceReference();
22086
22087 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
22088 $newReference = $rootRefs[$package->getName()];
22089 }
22090
22091 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl(), $newPackage->getDistType(), $newPackage->getDistSha1Checksum());
22092
22093 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
22094 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
22095 }
22096
22097 $package->setDistMirrors($newPackage->getDistMirrors());
22098 $package->setSourceMirrors($newPackage->getSourceMirrors());
22099 $package->setTransportOptions($newPackage->getTransportOptions());
22100 }
22101 }
22102 }
22103
22104 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl, $distType, $distShaSum)
22105 {
22106 $oldSourceRef = $package->getSourceReference();
22107
22108 if ($package->getSourceUrl() !== $sourceUrl) {
22109 $package->setSourceType($sourceType);
22110 $package->setSourceUrl($sourceUrl);
22111 $package->setSourceReference($sourceReference);
22112 }
22113
22114
22115  
22116  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $distUrl)) {
22117 $package->setDistUrl($distUrl);
22118 $package->setDistType($distType);
22119 $package->setDistSha1Checksum($distShaSum);
22120 $this->updateInstallReferences($package, $sourceReference);
22121 }
22122
22123 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
22124 $this->updateInstallReferences($package, $oldSourceRef);
22125 }
22126 }
22127
22128 private function updateInstallReferences(PackageInterface $package, $reference)
22129 {
22130 if (!$reference) {
22131 return;
22132 }
22133
22134 $package->setSourceReference($reference);
22135
22136 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $package->getDistUrl())) {
22137 $package->setDistReference($reference);
22138 $package->setDistUrl(preg_replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
22139 } elseif ($package->getDistReference()) { 
22140  $package->setDistReference($reference);
22141 }
22142 }
22143
22144
22145
22146
22147
22148 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
22149 {
22150 foreach ($aliases as $package => $versions) {
22151 foreach ($versions as $version => $alias) {
22152 $packages = $platformRepo->findPackages($package, $version);
22153 foreach ($packages as $package) {
22154 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
22155 $aliasPackage->setRootPackageAlias(true);
22156 $platformRepo->addPackage($aliasPackage);
22157 }
22158 }
22159 }
22160 }
22161
22162
22163
22164
22165
22166 private function isUpdateable(PackageInterface $package)
22167 {
22168 if (!$this->updateWhitelist) {
22169 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
22170 }
22171
22172 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
22173 $patternRegexp = BasePackage::packageNameToRegexp($whiteListedPattern);
22174 if (preg_match($patternRegexp, $package->getName())) {
22175 return true;
22176 }
22177 }
22178
22179 return false;
22180 }
22181
22182
22183
22184
22185
22186 private function extractPlatformRequirements($links)
22187 {
22188 $platformReqs = array();
22189 foreach ($links as $link) {
22190 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
22191 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
22192 }
22193 }
22194
22195 return $platformReqs;
22196 }
22197
22198
22199
22200
22201
22202
22203
22204
22205
22206
22207
22208
22209
22210
22211 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
22212 {
22213 if (!$this->updateWhitelist) {
22214 return;
22215 }
22216
22217 $rootRequires = array_merge($rootRequires, $rootDevRequires);
22218
22219 $skipPackages = array();
22220 if (!$this->whitelistAllDependencies) {
22221 foreach ($rootRequires as $require) {
22222 $skipPackages[$require->getTarget()] = true;
22223 }
22224 }
22225
22226 $pool = new Pool('dev');
22227 $pool->addRepository($localOrLockRepo);
22228
22229 $seen = array();
22230
22231 $rootRequiredPackageNames = array_keys($rootRequires);
22232
22233 foreach ($this->updateWhitelist as $packageName => $void) {
22234 $packageQueue = new \SplQueue;
22235 $nameMatchesRequiredPackage = false;
22236
22237 $depPackages = $pool->whatProvides($packageName);
22238 $matchesByPattern = array();
22239
22240  if (empty($depPackages)) {
22241
22242  $whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$');
22243 foreach ($localOrLockRepo->search($whitelistPatternSearchRegexp) as $installedPackage) {
22244 $matchesByPattern[] = $pool->whatProvides($installedPackage['name']);
22245 }
22246
22247
22248  $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName);
22249 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
22250 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
22251 $nameMatchesRequiredPackage = true;
22252 break;
22253 }
22254 }
22255 }
22256
22257 if (!empty($matchesByPattern)) {
22258 $depPackages = array_merge($depPackages, call_user_func_array('array_merge', $matchesByPattern));
22259 }
22260
22261 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
22262 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
22263 }
22264
22265 foreach ($depPackages as $depPackage) {
22266 $packageQueue->enqueue($depPackage);
22267 }
22268
22269 while (!$packageQueue->isEmpty()) {
22270 $package = $packageQueue->dequeue();
22271 if (isset($seen[$package->getId()])) {
22272 continue;
22273 }
22274
22275 $seen[$package->getId()] = true;
22276 $this->updateWhitelist[$package->getName()] = true;
22277
22278 if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) {
22279 continue;
22280 }
22281
22282 $requires = $package->getRequires();
22283
22284 foreach ($requires as $require) {
22285 $requirePackages = $pool->whatProvides($require->getTarget());
22286
22287 foreach ($requirePackages as $requirePackage) {
22288 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
22289 continue;
22290 }
22291
22292 if (isset($skipPackages[$requirePackage->getName()]) && !preg_match(BasePackage::packageNameToRegexp($packageName), $requirePackage->getName())) {
22293 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
22294 continue;
22295 }
22296
22297 $packageQueue->enqueue($requirePackage);
22298 }
22299 }
22300 }
22301 }
22302 }
22303
22304
22305
22306
22307
22308
22309
22310
22311 private function mockLocalRepositories(RepositoryManager $rm)
22312 {
22313 $packages = array();
22314 foreach ($rm->getLocalRepository()->getPackages() as $package) {
22315 $packages[(string) $package] = clone $package;
22316 }
22317 foreach ($packages as $key => $package) {
22318 if ($package instanceof AliasPackage) {
22319 $alias = (string) $package->getAliasOf();
22320 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
22321 }
22322 }
22323 $rm->setLocalRepository(
22324 new InstalledArrayRepository($packages)
22325 );
22326 }
22327
22328
22329
22330
22331
22332
22333
22334
22335 public static function create(IOInterface $io, Composer $composer)
22336 {
22337 return new static(
22338 $io,
22339 $composer->getConfig(),
22340 $composer->getPackage(),
22341 $composer->getDownloadManager(),
22342 $composer->getRepositoryManager(),
22343 $composer->getLocker(),
22344 $composer->getInstallationManager(),
22345 $composer->getEventDispatcher(),
22346 $composer->getAutoloadGenerator()
22347 );
22348 }
22349
22350
22351
22352
22353
22354 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
22355 {
22356 $this->additionalInstalledRepository = $additionalInstalledRepository;
22357
22358 return $this;
22359 }
22360
22361
22362
22363
22364
22365
22366
22367 public function setDryRun($dryRun = true)
22368 {
22369 $this->dryRun = (bool) $dryRun;
22370
22371 return $this;
22372 }
22373
22374
22375
22376
22377
22378
22379 public function isDryRun()
22380 {
22381 return $this->dryRun;
22382 }
22383
22384
22385
22386
22387
22388
22389
22390 public function setPreferSource($preferSource = true)
22391 {
22392 $this->preferSource = (bool) $preferSource;
22393
22394 return $this;
22395 }
22396
22397
22398
22399
22400
22401
22402
22403 public function setPreferDist($preferDist = true)
22404 {
22405 $this->preferDist = (bool) $preferDist;
22406
22407 return $this;
22408 }
22409
22410
22411
22412
22413
22414
22415
22416 public function setOptimizeAutoloader($optimizeAutoloader = false)
22417 {
22418 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
22419 if (!$this->optimizeAutoloader) {
22420
22421  
22422  $this->setClassMapAuthoritative(false);
22423 }
22424
22425 return $this;
22426 }
22427
22428
22429
22430
22431
22432
22433
22434
22435 public function setClassMapAuthoritative($classMapAuthoritative = false)
22436 {
22437 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
22438 if ($this->classMapAuthoritative) {
22439
22440  $this->setOptimizeAutoloader(true);
22441 }
22442
22443 return $this;
22444 }
22445
22446
22447
22448
22449
22450
22451
22452 public function setApcuAutoloader($apcuAutoloader = false)
22453 {
22454 $this->apcuAutoloader = (bool) $apcuAutoloader;
22455
22456 return $this;
22457 }
22458
22459
22460
22461
22462
22463
22464
22465 public function setUpdate($update = true)
22466 {
22467 $this->update = (bool) $update;
22468
22469 return $this;
22470 }
22471
22472
22473
22474
22475
22476
22477
22478 public function setDevMode($devMode = true)
22479 {
22480 $this->devMode = (bool) $devMode;
22481
22482 return $this;
22483 }
22484
22485
22486
22487
22488
22489
22490
22491
22492
22493 public function setDumpAutoloader($dumpAutoloader = true)
22494 {
22495 $this->dumpAutoloader = (bool) $dumpAutoloader;
22496
22497 return $this;
22498 }
22499
22500
22501
22502
22503
22504
22505
22506
22507
22508 public function setRunScripts($runScripts = true)
22509 {
22510 $this->runScripts = (bool) $runScripts;
22511
22512 return $this;
22513 }
22514
22515
22516
22517
22518
22519
22520
22521 public function setConfig(Config $config)
22522 {
22523 $this->config = $config;
22524
22525 return $this;
22526 }
22527
22528
22529
22530
22531
22532
22533
22534 public function setVerbose($verbose = true)
22535 {
22536 $this->verbose = (bool) $verbose;
22537
22538 return $this;
22539 }
22540
22541
22542
22543
22544
22545
22546 public function isVerbose()
22547 {
22548 return $this->verbose;
22549 }
22550
22551
22552
22553
22554
22555
22556
22557 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
22558 {
22559 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
22560
22561 return $this;
22562 }
22563
22564
22565
22566
22567
22568
22569
22570
22571 public function setUpdateWhitelist(array $packages)
22572 {
22573 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
22574
22575 return $this;
22576 }
22577
22578
22579
22580
22581 public function setWhitelistDependencies($updateDependencies = true)
22582 {
22583 return $this->setWhitelistTransitiveDependencies($updateDependencies);
22584 }
22585
22586
22587
22588
22589
22590
22591
22592
22593
22594
22595 public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true)
22596 {
22597 $this->whitelistDependencies = (bool) $updateTransitiveDependencies;
22598
22599 return $this;
22600 }
22601
22602
22603
22604
22605
22606
22607
22608
22609
22610
22611 public function setWhitelistAllDependencies($updateAllDependencies = true)
22612 {
22613 $this->whitelistAllDependencies = (bool) $updateAllDependencies;
22614
22615 return $this;
22616 }
22617
22618
22619
22620
22621
22622
22623
22624 public function setPreferStable($preferStable = true)
22625 {
22626 $this->preferStable = (bool) $preferStable;
22627
22628 return $this;
22629 }
22630
22631
22632
22633
22634
22635
22636
22637 public function setPreferLowest($preferLowest = true)
22638 {
22639 $this->preferLowest = (bool) $preferLowest;
22640
22641 return $this;
22642 }
22643
22644
22645
22646
22647
22648
22649
22650
22651
22652 public function setWriteLock($writeLock = true)
22653 {
22654 $this->writeLock = (bool) $writeLock;
22655
22656 return $this;
22657 }
22658
22659
22660
22661
22662
22663
22664
22665
22666
22667 public function setExecuteOperations($executeOperations = true)
22668 {
22669 $this->executeOperations = (bool) $executeOperations;
22670
22671 return $this;
22672 }
22673
22674
22675
22676
22677
22678
22679
22680 public function setSkipSuggest($skipSuggest = true)
22681 {
22682 $this->skipSuggest = (bool) $skipSuggest;
22683
22684 return $this;
22685 }
22686
22687
22688
22689
22690
22691
22692
22693
22694
22695
22696 public function disablePlugins()
22697 {
22698 $this->installationManager->disablePlugins();
22699
22700 return $this;
22701 }
22702
22703
22704
22705
22706
22707 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
22708 {
22709 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
22710
22711 return $this;
22712 }
22713 }
22714 <?php
22715
22716
22717
22718
22719
22720
22721
22722
22723
22724
22725
22726 namespace Composer\Installer;
22727
22728 use Composer\IO\IOInterface;
22729 use Composer\Package\PackageInterface;
22730 use Composer\Util\Filesystem;
22731 use Composer\Util\Platform;
22732 use Composer\Util\ProcessExecutor;
22733 use Composer\Util\Silencer;
22734
22735
22736
22737
22738
22739
22740
22741
22742 class BinaryInstaller
22743 {
22744 protected $binDir;
22745 protected $binCompat;
22746 protected $io;
22747 protected $filesystem;
22748
22749
22750
22751
22752
22753
22754
22755 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
22756 {
22757 $this->binDir = $binDir;
22758 $this->binCompat = $binCompat;
22759 $this->io = $io;
22760 $this->filesystem = $filesystem ?: new Filesystem();
22761 }
22762
22763 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
22764 {
22765 $binaries = $this->getBinaries($package);
22766 if (!$binaries) {
22767 return;
22768 }
22769 foreach ($binaries as $bin) {
22770 $binPath = $installPath.'/'.$bin;
22771 if (!file_exists($binPath)) {
22772 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
22773 continue;
22774 }
22775
22776
22777  
22778  
22779  
22780  $binPath = realpath($binPath);
22781
22782 $this->initializeBinDir();
22783 $link = $this->binDir.'/'.basename($bin);
22784 if (file_exists($link)) {
22785 if (is_link($link)) {
22786
22787  
22788  
22789  Silencer::call('chmod', $link, 0777 & ~umask());
22790 }
22791 if ($warnOnOverwrite) {
22792 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
22793 }
22794 continue;
22795 }
22796
22797 if ($this->binCompat === "auto") {
22798 if (Platform::isWindows()) {
22799 $this->installFullBinaries($binPath, $link, $bin, $package);
22800 } else {
22801 $this->installSymlinkBinaries($binPath, $link);
22802 }
22803 } elseif ($this->binCompat === "full") {
22804 $this->installFullBinaries($binPath, $link, $bin, $package);
22805 }
22806 Silencer::call('chmod', $link, 0777 & ~umask());
22807 }
22808 }
22809
22810 public function removeBinaries(PackageInterface $package)
22811 {
22812 $this->initializeBinDir();
22813
22814 $binaries = $this->getBinaries($package);
22815 if (!$binaries) {
22816 return;
22817 }
22818 foreach ($binaries as $bin) {
22819 $link = $this->binDir.'/'.basename($bin);
22820 if (is_link($link) || file_exists($link)) {
22821 $this->filesystem->unlink($link);
22822 }
22823 if (file_exists($link.'.bat')) {
22824 $this->filesystem->unlink($link.'.bat');
22825 }
22826 }
22827
22828
22829  if (is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) {
22830 Silencer::call('rmdir', $this->binDir);
22831 }
22832 }
22833
22834 public static function determineBinaryCaller($bin)
22835 {
22836 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
22837 return 'call';
22838 }
22839
22840 $handle = fopen($bin, 'r');
22841 $line = fgets($handle);
22842 fclose($handle);
22843 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
22844 return trim($match[1]);
22845 }
22846
22847 return 'php';
22848 }
22849
22850 protected function getBinaries(PackageInterface $package)
22851 {
22852 return $package->getBinaries();
22853 }
22854
22855 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
22856 {
22857
22858  if ('.bat' !== substr($binPath, -4)) {
22859 $this->installUnixyProxyBinaries($binPath, $link);
22860 @chmod($link, 0777 & ~umask());
22861 $link .= '.bat';
22862 if (file_exists($link)) {
22863 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
22864 }
22865 }
22866 if (!file_exists($link)) {
22867 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
22868 }
22869 }
22870
22871 protected function installSymlinkBinaries($binPath, $link)
22872 {
22873 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
22874 $this->installUnixyProxyBinaries($binPath, $link);
22875 }
22876 }
22877
22878 protected function installUnixyProxyBinaries($binPath, $link)
22879 {
22880 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
22881 }
22882
22883 protected function initializeBinDir()
22884 {
22885 $this->filesystem->ensureDirectoryExists($this->binDir);
22886 $this->binDir = realpath($this->binDir);
22887 }
22888
22889 protected function generateWindowsProxyCode($bin, $link)
22890 {
22891 $binPath = $this->filesystem->findShortestPath($link, $bin);
22892 $caller = self::determineBinaryCaller($bin);
22893
22894 return "@ECHO OFF\r\n".
22895 "setlocal DISABLEDELAYEDEXPANSION\r\n".
22896 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
22897 "{$caller} \"%BIN_TARGET%\" %*\r\n";
22898 }
22899
22900 protected function generateUnixyProxyCode($bin, $link)
22901 {
22902 $binPath = $this->filesystem->findShortestPath($link, $bin);
22903
22904 $binDir = ProcessExecutor::escape(dirname($binPath));
22905 $binFile = basename($binPath);
22906
22907 $proxyCode = <<<PROXY
22908 #!/usr/bin/env sh
22909
22910 dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
22911
22912 if [ -d /proc/cygdrive ]; then
22913     case \$(which php) in
22914         \$(readlink -n /proc/cygdrive)/*)
22915             # We are in Cygwin using Windows php, so the path must be translated
22916             dir=\$(cygpath -m "\$dir");
22917             ;;
22918     esac
22919 fi
22920
22921 "\${dir}/$binFile" "\$@"
22922
22923 PROXY;
22924
22925 return $proxyCode;
22926 }
22927 }
22928 <?php
22929
22930
22931
22932
22933
22934
22935
22936
22937
22938
22939
22940 namespace Composer\Installer;
22941
22942 use Composer\Package\PackageInterface;
22943
22944
22945
22946
22947
22948
22949 interface BinaryPresenceInterface
22950 {
22951
22952
22953
22954
22955
22956 public function ensureBinariesPresence(PackageInterface $package);
22957 }
22958 <?php
22959
22960
22961
22962
22963
22964
22965
22966
22967
22968
22969
22970 namespace Composer\Installer;
22971
22972 use Composer\IO\IOInterface;
22973 use Composer\Package\PackageInterface;
22974 use Composer\Package\AliasPackage;
22975 use Composer\Repository\RepositoryInterface;
22976 use Composer\Repository\InstalledRepositoryInterface;
22977 use Composer\DependencyResolver\Operation\OperationInterface;
22978 use Composer\DependencyResolver\Operation\InstallOperation;
22979 use Composer\DependencyResolver\Operation\UpdateOperation;
22980 use Composer\DependencyResolver\Operation\UninstallOperation;
22981 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
22982 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
22983 use Composer\Util\StreamContextFactory;
22984
22985
22986
22987
22988
22989
22990
22991
22992 class InstallationManager
22993 {
22994 private $installers = array();
22995 private $cache = array();
22996 private $notifiablePackages = array();
22997
22998 public function reset()
22999 {
23000 $this->notifiablePackages = array();
23001 }
23002
23003
23004
23005
23006
23007
23008 public function addInstaller(InstallerInterface $installer)
23009 {
23010 array_unshift($this->installers, $installer);
23011 $this->cache = array();
23012 }
23013
23014
23015
23016
23017
23018
23019 public function removeInstaller(InstallerInterface $installer)
23020 {
23021 if (false !== ($key = array_search($installer, $this->installers, true))) {
23022 array_splice($this->installers, $key, 1);
23023 $this->cache = array();
23024 }
23025 }
23026
23027
23028
23029
23030
23031
23032
23033
23034 public function disablePlugins()
23035 {
23036 foreach ($this->installers as $i => $installer) {
23037 if (!$installer instanceof PluginInstaller) {
23038 continue;
23039 }
23040
23041 unset($this->installers[$i]);
23042 }
23043 }
23044
23045
23046
23047
23048
23049
23050
23051
23052
23053 public function getInstaller($type)
23054 {
23055 $type = strtolower($type);
23056
23057 if (isset($this->cache[$type])) {
23058 return $this->cache[$type];
23059 }
23060
23061 foreach ($this->installers as $installer) {
23062 if ($installer->supports($type)) {
23063 return $this->cache[$type] = $installer;
23064 }
23065 }
23066
23067 throw new \InvalidArgumentException('Unknown installer type: '.$type);
23068 }
23069
23070
23071
23072
23073
23074
23075
23076
23077
23078 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23079 {
23080 if ($package instanceof AliasPackage) {
23081 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
23082 }
23083
23084 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
23085 }
23086
23087
23088
23089
23090
23091
23092
23093 public function ensureBinariesPresence(PackageInterface $package)
23094 {
23095 try {
23096 $installer = $this->getInstaller($package->getType());
23097 } catch (\InvalidArgumentException $e) {
23098
23099  return;
23100 }
23101
23102
23103  if ($installer instanceof BinaryPresenceInterface) {
23104 $installer->ensureBinariesPresence($package);
23105 }
23106 }
23107
23108
23109
23110
23111
23112
23113
23114 public function execute(RepositoryInterface $repo, OperationInterface $operation)
23115 {
23116 $method = $operation->getJobType();
23117 $this->$method($repo, $operation);
23118 }
23119
23120
23121
23122
23123
23124
23125
23126 public function install(RepositoryInterface $repo, InstallOperation $operation)
23127 {
23128 $package = $operation->getPackage();
23129 $installer = $this->getInstaller($package->getType());
23130 $installer->install($repo, $package);
23131 $this->markForNotification($package);
23132 }
23133
23134
23135
23136
23137
23138
23139
23140 public function update(RepositoryInterface $repo, UpdateOperation $operation)
23141 {
23142 $initial = $operation->getInitialPackage();
23143 $target = $operation->getTargetPackage();
23144
23145 $initialType = $initial->getType();
23146 $targetType = $target->getType();
23147
23148 if ($initialType === $targetType) {
23149 $installer = $this->getInstaller($initialType);
23150 $installer->update($repo, $initial, $target);
23151 $this->markForNotification($target);
23152 } else {
23153 $this->getInstaller($initialType)->uninstall($repo, $initial);
23154 $this->getInstaller($targetType)->install($repo, $target);
23155 }
23156 }
23157
23158
23159
23160
23161
23162
23163
23164 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
23165 {
23166 $package = $operation->getPackage();
23167 $installer = $this->getInstaller($package->getType());
23168 $installer->uninstall($repo, $package);
23169 }
23170
23171
23172
23173
23174
23175
23176
23177 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
23178 {
23179 $package = $operation->getPackage();
23180
23181 if (!$repo->hasPackage($package)) {
23182 $repo->addPackage(clone $package);
23183 }
23184 }
23185
23186
23187
23188
23189
23190
23191
23192 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
23193 {
23194 $package = $operation->getPackage();
23195
23196 $repo->removePackage($package);
23197 }
23198
23199
23200
23201
23202
23203
23204
23205 public function getInstallPath(PackageInterface $package)
23206 {
23207 $installer = $this->getInstaller($package->getType());
23208
23209 return $installer->getInstallPath($package);
23210 }
23211
23212 public function notifyInstalls(IOInterface $io)
23213 {
23214 foreach ($this->notifiablePackages as $repoUrl => $packages) {
23215 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
23216 if ($io->hasAuthentication($repositoryName)) {
23217 $auth = $io->getAuthentication($repositoryName);
23218 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
23219 $authHeader = 'Authorization: Basic '.$authStr;
23220 }
23221
23222
23223  if (strpos($repoUrl, '%package%')) {
23224 foreach ($packages as $package) {
23225 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
23226
23227 $params = array(
23228 'version' => $package->getPrettyVersion(),
23229 'version_normalized' => $package->getVersion(),
23230 );
23231 $opts = array('http' =>
23232 array(
23233 'method' => 'POST',
23234 'header' => array('Content-type: application/x-www-form-urlencoded'),
23235 'content' => http_build_query($params, '', '&'),
23236 'timeout' => 3,
23237 ),
23238 );
23239 if (isset($authHeader)) {
23240 $opts['http']['header'][] = $authHeader;
23241 }
23242
23243 $context = StreamContextFactory::getContext($url, $opts);
23244 @file_get_contents($url, false, $context);
23245 }
23246
23247 continue;
23248 }
23249
23250 $postData = array('downloads' => array());
23251 foreach ($packages as $package) {
23252 $postData['downloads'][] = array(
23253 'name' => $package->getPrettyName(),
23254 'version' => $package->getVersion(),
23255 );
23256 }
23257
23258 $opts = array('http' =>
23259 array(
23260 'method' => 'POST',
23261 'header' => array('Content-Type: application/json'),
23262 'content' => json_encode($postData),
23263 'timeout' => 6,
23264 ),
23265 );
23266 if (isset($authHeader)) {
23267 $opts['http']['header'][] = $authHeader;
23268 }
23269
23270 $context = StreamContextFactory::getContext($repoUrl, $opts);
23271 @file_get_contents($repoUrl, false, $context);
23272 }
23273
23274 $this->reset();
23275 }
23276
23277 private function markForNotification(PackageInterface $package)
23278 {
23279 if ($package->getNotificationUrl()) {
23280 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
23281 }
23282 }
23283 }
23284 <?php
23285
23286
23287
23288
23289
23290
23291
23292
23293
23294
23295
23296 namespace Composer\Installer;
23297
23298 use Composer\Composer;
23299 use Composer\DependencyResolver\PolicyInterface;
23300 use Composer\DependencyResolver\Operation\OperationInterface;
23301 use Composer\DependencyResolver\Pool;
23302 use Composer\DependencyResolver\Request;
23303 use Composer\EventDispatcher\Event;
23304 use Composer\IO\IOInterface;
23305 use Composer\Repository\CompositeRepository;
23306
23307
23308
23309
23310
23311
23312 class InstallerEvent extends Event
23313 {
23314
23315
23316
23317 private $composer;
23318
23319
23320
23321
23322 private $io;
23323
23324
23325
23326
23327 private $devMode;
23328
23329
23330
23331
23332 private $policy;
23333
23334
23335
23336
23337 private $pool;
23338
23339
23340
23341
23342 private $installedRepo;
23343
23344
23345
23346
23347 private $request;
23348
23349
23350
23351
23352 private $operations;
23353
23354
23355
23356
23357
23358
23359
23360
23361
23362
23363
23364
23365
23366
23367 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
23368 {
23369 parent::__construct($eventName);
23370
23371 $this->composer = $composer;
23372 $this->io = $io;
23373 $this->devMode = $devMode;
23374 $this->policy = $policy;
23375 $this->pool = $pool;
23376 $this->installedRepo = $installedRepo;
23377 $this->request = $request;
23378 $this->operations = $operations;
23379 }
23380
23381
23382
23383
23384 public function getComposer()
23385 {
23386 return $this->composer;
23387 }
23388
23389
23390
23391
23392 public function getIO()
23393 {
23394 return $this->io;
23395 }
23396
23397
23398
23399
23400 public function isDevMode()
23401 {
23402 return $this->devMode;
23403 }
23404
23405
23406
23407
23408 public function getPolicy()
23409 {
23410 return $this->policy;
23411 }
23412
23413
23414
23415
23416 public function getPool()
23417 {
23418 return $this->pool;
23419 }
23420
23421
23422
23423
23424 public function getInstalledRepo()
23425 {
23426 return $this->installedRepo;
23427 }
23428
23429
23430
23431
23432 public function getRequest()
23433 {
23434 return $this->request;
23435 }
23436
23437
23438
23439
23440 public function getOperations()
23441 {
23442 return $this->operations;
23443 }
23444 }
23445 <?php
23446
23447
23448
23449
23450
23451
23452
23453
23454
23455
23456
23457 namespace Composer\Installer;
23458
23459
23460
23461
23462
23463
23464 class InstallerEvents
23465 {
23466
23467
23468
23469
23470
23471
23472
23473
23474
23475 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
23476
23477
23478
23479
23480
23481
23482
23483
23484
23485
23486 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
23487 }
23488 <?php
23489
23490
23491
23492
23493
23494
23495
23496
23497
23498
23499
23500 namespace Composer\Installer;
23501
23502 use Composer\Package\PackageInterface;
23503 use Composer\Repository\InstalledRepositoryInterface;
23504 use InvalidArgumentException;
23505
23506
23507
23508
23509
23510
23511
23512 interface InstallerInterface
23513 {
23514
23515
23516
23517
23518
23519
23520 public function supports($packageType);
23521
23522
23523
23524
23525
23526
23527
23528
23529
23530 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
23531
23532
23533
23534
23535
23536
23537
23538 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
23539
23540
23541
23542
23543
23544
23545
23546
23547
23548
23549 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
23550
23551
23552
23553
23554
23555
23556
23557 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
23558
23559
23560
23561
23562
23563
23564
23565 public function getInstallPath(PackageInterface $package);
23566 }
23567 <?php
23568
23569
23570
23571
23572
23573
23574
23575
23576
23577
23578
23579 namespace Composer\Installer;
23580
23581 use Composer\Composer;
23582 use Composer\IO\IOInterface;
23583 use Composer\Repository\InstalledRepositoryInterface;
23584 use Composer\Package\PackageInterface;
23585 use Composer\Util\Filesystem;
23586 use Composer\Util\Silencer;
23587 use Composer\Util\Platform;
23588
23589
23590
23591
23592
23593
23594
23595 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
23596 {
23597 protected $composer;
23598 protected $vendorDir;
23599 protected $binDir;
23600 protected $downloadManager;
23601 protected $io;
23602 protected $type;
23603 protected $filesystem;
23604 protected $binCompat;
23605 protected $binaryInstaller;
23606
23607
23608
23609
23610
23611
23612
23613
23614
23615
23616 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
23617 {
23618 $this->composer = $composer;
23619 $this->downloadManager = $composer->getDownloadManager();
23620 $this->io = $io;
23621 $this->type = $type;
23622
23623 $this->filesystem = $filesystem ?: new Filesystem();
23624 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
23625 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
23626 }
23627
23628
23629
23630
23631 public function supports($packageType)
23632 {
23633 return $packageType === $this->type || null === $this->type;
23634 }
23635
23636
23637
23638
23639 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23640 {
23641 if (!$repo->hasPackage($package)) {
23642 return false;
23643 }
23644
23645 $installPath = $this->getInstallPath($package);
23646
23647 if (is_readable($installPath)) {
23648 return true;
23649 }
23650
23651 return (Platform::isWindows() && $this->filesystem->isJunction($installPath)) || is_link($installPath);
23652 }
23653
23654
23655
23656
23657 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23658 {
23659 $this->initializeVendorDir();
23660 $downloadPath = $this->getInstallPath($package);
23661
23662
23663  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
23664 $this->binaryInstaller->removeBinaries($package);
23665 }
23666
23667 $this->installCode($package);
23668 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
23669 if (!$repo->hasPackage($package)) {
23670 $repo->addPackage(clone $package);
23671 }
23672 }
23673
23674
23675
23676
23677 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23678 {
23679 if (!$repo->hasPackage($initial)) {
23680 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23681 }
23682
23683 $this->initializeVendorDir();
23684
23685 $this->binaryInstaller->removeBinaries($initial);
23686 $this->updateCode($initial, $target);
23687 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
23688 $repo->removePackage($initial);
23689 if (!$repo->hasPackage($target)) {
23690 $repo->addPackage(clone $target);
23691 }
23692 }
23693
23694
23695
23696
23697 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23698 {
23699 if (!$repo->hasPackage($package)) {
23700 throw new \InvalidArgumentException('Package is not installed: '.$package);
23701 }
23702
23703 $this->removeCode($package);
23704 $this->binaryInstaller->removeBinaries($package);
23705 $repo->removePackage($package);
23706
23707 $downloadPath = $this->getPackageBasePath($package);
23708 if (strpos($package->getName(), '/')) {
23709 $packageVendorDir = dirname($downloadPath);
23710 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
23711 Silencer::call('rmdir', $packageVendorDir);
23712 }
23713 }
23714 }
23715
23716
23717
23718
23719 public function getInstallPath(PackageInterface $package)
23720 {
23721 $this->initializeVendorDir();
23722
23723 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
23724 $targetDir = $package->getTargetDir();
23725
23726 return $basePath . ($targetDir ? '/'.$targetDir : '');
23727 }
23728
23729
23730
23731
23732
23733
23734 public function ensureBinariesPresence(PackageInterface $package)
23735 {
23736 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
23737 }
23738
23739
23740
23741
23742
23743
23744
23745
23746
23747
23748 protected function getPackageBasePath(PackageInterface $package)
23749 {
23750 $installPath = $this->getInstallPath($package);
23751 $targetDir = $package->getTargetDir();
23752
23753 if ($targetDir) {
23754 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
23755 }
23756
23757 return $installPath;
23758 }
23759
23760 protected function installCode(PackageInterface $package)
23761 {
23762 $downloadPath = $this->getInstallPath($package);
23763 $this->downloadManager->download($package, $downloadPath);
23764 }
23765
23766 protected function updateCode(PackageInterface $initial, PackageInterface $target)
23767 {
23768 $initialDownloadPath = $this->getInstallPath($initial);
23769 $targetDownloadPath = $this->getInstallPath($target);
23770 if ($targetDownloadPath !== $initialDownloadPath) {
23771
23772  
23773  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
23774 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
23775 ) {
23776 $this->removeCode($initial);
23777 $this->installCode($target);
23778
23779 return;
23780 }
23781
23782 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
23783 }
23784 $this->downloadManager->update($initial, $target, $targetDownloadPath);
23785 }
23786
23787 protected function removeCode(PackageInterface $package)
23788 {
23789 $downloadPath = $this->getPackageBasePath($package);
23790 $this->downloadManager->remove($package, $downloadPath);
23791 }
23792
23793 protected function initializeVendorDir()
23794 {
23795 $this->filesystem->ensureDirectoryExists($this->vendorDir);
23796 $this->vendorDir = realpath($this->vendorDir);
23797 }
23798 }
23799 <?php
23800
23801
23802
23803
23804
23805
23806
23807
23808
23809
23810
23811 namespace Composer\Installer;
23812
23813 use Composer\Repository\InstalledRepositoryInterface;
23814 use Composer\Package\PackageInterface;
23815 use Composer\Package\Version\VersionParser;
23816 use Composer\IO\IOInterface;
23817
23818
23819
23820
23821
23822
23823 class MetapackageInstaller implements InstallerInterface
23824 {
23825 private $io;
23826
23827 public function __construct(IOInterface $io)
23828 {
23829 $this->io = $io;
23830 }
23831
23832
23833
23834
23835 public function supports($packageType)
23836 {
23837 return $packageType === 'metapackage';
23838 }
23839
23840
23841
23842
23843 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23844 {
23845 return $repo->hasPackage($package);
23846 }
23847
23848
23849
23850
23851 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23852 {
23853 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
23854
23855 $repo->addPackage(clone $package);
23856 }
23857
23858
23859
23860
23861 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23862 {
23863 if (!$repo->hasPackage($initial)) {
23864 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23865 }
23866
23867 $name = $target->getName();
23868 $from = $initial->getFullPrettyVersion();
23869 $to = $target->getFullPrettyVersion();
23870 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
23871 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>)");
23872
23873 $repo->removePackage($initial);
23874 $repo->addPackage(clone $target);
23875 }
23876
23877
23878
23879
23880 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23881 {
23882 if (!$repo->hasPackage($package)) {
23883 throw new \InvalidArgumentException('Package is not installed: '.$package);
23884 }
23885
23886 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
23887
23888 $repo->removePackage($package);
23889 }
23890
23891
23892
23893
23894 public function getInstallPath(PackageInterface $package)
23895 {
23896 return '';
23897 }
23898 }
23899 <?php
23900
23901
23902
23903
23904
23905
23906
23907
23908
23909
23910
23911 namespace Composer\Installer;
23912
23913 use Composer\Repository\InstalledRepositoryInterface;
23914 use Composer\Package\PackageInterface;
23915
23916
23917
23918
23919
23920
23921
23922
23923 class NoopInstaller implements InstallerInterface
23924 {
23925
23926
23927
23928 public function supports($packageType)
23929 {
23930 return true;
23931 }
23932
23933
23934
23935
23936 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23937 {
23938 return $repo->hasPackage($package);
23939 }
23940
23941
23942
23943
23944 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23945 {
23946 if (!$repo->hasPackage($package)) {
23947 $repo->addPackage(clone $package);
23948 }
23949 }
23950
23951
23952
23953
23954 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23955 {
23956 if (!$repo->hasPackage($initial)) {
23957 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23958 }
23959
23960 $repo->removePackage($initial);
23961 if (!$repo->hasPackage($target)) {
23962 $repo->addPackage(clone $target);
23963 }
23964 }
23965
23966
23967
23968
23969 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23970 {
23971 if (!$repo->hasPackage($package)) {
23972 throw new \InvalidArgumentException('Package is not installed: '.$package);
23973 }
23974 $repo->removePackage($package);
23975 }
23976
23977
23978
23979
23980 public function getInstallPath(PackageInterface $package)
23981 {
23982 $targetDir = $package->getTargetDir();
23983
23984 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
23985 }
23986 }
23987 <?php
23988
23989
23990
23991
23992
23993
23994
23995
23996
23997
23998
23999 namespace Composer\Installer;
24000
24001 use Composer\Composer;
24002 use Composer\IO\IOInterface;
24003 use Composer\DependencyResolver\Operation\OperationInterface;
24004 use Composer\DependencyResolver\PolicyInterface;
24005 use Composer\DependencyResolver\Pool;
24006 use Composer\DependencyResolver\Request;
24007 use Composer\Repository\CompositeRepository;
24008
24009
24010
24011
24012
24013
24014 class PackageEvent extends InstallerEvent
24015 {
24016
24017
24018
24019 private $operation;
24020
24021
24022
24023
24024
24025
24026
24027
24028
24029
24030
24031
24032
24033
24034
24035 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
24036 {
24037 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
24038
24039 $this->operation = $operation;
24040 }
24041
24042
24043
24044
24045
24046
24047 public function getOperation()
24048 {
24049 return $this->operation;
24050 }
24051 }
24052 <?php
24053
24054
24055
24056
24057
24058
24059
24060
24061
24062
24063
24064 namespace Composer\Installer;
24065
24066
24067
24068
24069
24070
24071 class PackageEvents
24072 {
24073
24074
24075
24076
24077
24078
24079
24080 const PRE_PACKAGE_INSTALL = 'pre-package-install';
24081
24082
24083
24084
24085
24086
24087
24088
24089 const POST_PACKAGE_INSTALL = 'post-package-install';
24090
24091
24092
24093
24094
24095
24096
24097
24098 const PRE_PACKAGE_UPDATE = 'pre-package-update';
24099
24100
24101
24102
24103
24104
24105
24106
24107 const POST_PACKAGE_UPDATE = 'post-package-update';
24108
24109
24110
24111
24112
24113
24114
24115
24116 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
24117
24118
24119
24120
24121
24122
24123
24124
24125 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
24126 }
24127 <?php
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139 namespace Composer\Installer;
24140
24141 use Composer\IO\IOInterface;
24142 use Composer\Package\PackageInterface;
24143 use Composer\Util\Filesystem;
24144 use Composer\Util\ProcessExecutor;
24145
24146
24147
24148
24149
24150
24151 class PearBinaryInstaller extends BinaryInstaller
24152 {
24153 private $installer;
24154 private $vendorDir;
24155
24156
24157
24158
24159
24160
24161
24162
24163
24164 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
24165 {
24166 parent::__construct($io, $binDir, $binCompat, $filesystem);
24167 $this->installer = $installer;
24168 $this->vendorDir = $vendorDir;
24169 }
24170
24171 protected function getBinaries(PackageInterface $package)
24172 {
24173 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
24174 $binaries = array();
24175 if (file_exists($binariesPath)) {
24176 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
24177 if (!$value->isDir()) {
24178 $binaries[] = 'bin/'.$fileName;
24179 }
24180 }
24181 }
24182
24183 return $binaries;
24184 }
24185
24186 protected function initializeBinDir()
24187 {
24188 parent::initializeBinDir();
24189 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
24190 @chmod($this->binDir.'/composer-php', 0777 & ~umask());
24191 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
24192 @chmod($this->binDir.'/composer-php.bat', 0777 & ~umask());
24193 }
24194
24195 protected function generateWindowsProxyCode($bin, $link)
24196 {
24197 $binPath = $this->filesystem->findShortestPath($link, $bin);
24198 if ('.bat' === substr($bin, -4)) {
24199 $caller = 'call';
24200 } else {
24201 $handle = fopen($bin, 'r');
24202 $line = fgets($handle);
24203 fclose($handle);
24204 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
24205 $caller = trim($match[1]);
24206 } else {
24207 $caller = 'php';
24208 }
24209
24210 if ($caller === 'php') {
24211 return "@echo off\r\n".
24212 "pushd .\r\n".
24213 "cd %~dp0\r\n".
24214 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
24215 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
24216 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
24217 "popd\r\n".
24218 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
24219 }
24220 }
24221
24222 return "@echo off\r\n".
24223 "pushd .\r\n".
24224 "cd %~dp0\r\n".
24225 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
24226 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
24227 "popd\r\n".
24228 $caller." \"%BIN_TARGET%\" %*\r\n";
24229 }
24230
24231 private function generateWindowsPhpProxyCode()
24232 {
24233 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
24234
24235 return
24236 "@echo off\r\n" .
24237 "setlocal enabledelayedexpansion\r\n" .
24238 "set BIN_DIR=%~dp0\r\n" .
24239 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
24240 "set DIRS=.\r\n" .
24241 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
24242 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
24243 "        set DIRS=!DIRS!;%%~fP\r\n" .
24244 "    )\r\n" .
24245 ")\r\n" .
24246 "php.exe -d include_path=!DIRS! %*\r\n";
24247 }
24248
24249 private function generateUnixyPhpProxyCode()
24250 {
24251 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
24252
24253 return
24254 "#!/usr/bin/env sh\n".
24255 "SRC_DIR=`pwd`\n".
24256 "BIN_DIR=`dirname $0`\n".
24257 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
24258 "DIRS=\"\"\n".
24259 "for vendor in \$VENDOR_DIR/*; do\n".
24260 "    if [ -d \"\$vendor\" ]; then\n".
24261 "        for package in \$vendor/*; do\n".
24262 "            if [ -d \"\$package\" ]; then\n".
24263 "                DIRS=\"\${DIRS}:\${package}\"\n".
24264 "            fi\n".
24265 "        done\n".
24266 "    fi\n".
24267 "done\n".
24268 "php -d include_path=\".\$DIRS\" $@\n";
24269 }
24270 }
24271 <?php
24272
24273
24274
24275
24276
24277
24278
24279
24280
24281
24282
24283 namespace Composer\Installer;
24284
24285 use Composer\IO\IOInterface;
24286 use Composer\Composer;
24287 use Composer\Downloader\PearPackageExtractor;
24288 use Composer\Repository\InstalledRepositoryInterface;
24289 use Composer\Package\PackageInterface;
24290 use Composer\Util\Platform;
24291 use Composer\Util\Filesystem;
24292
24293
24294
24295
24296
24297
24298
24299 class PearInstaller extends LibraryInstaller
24300 {
24301
24302
24303
24304
24305
24306
24307
24308 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
24309 {
24310 $filesystem = new Filesystem();
24311 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
24312
24313 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
24314 }
24315
24316
24317
24318
24319 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24320 {
24321 $this->uninstall($repo, $initial);
24322 $this->install($repo, $target);
24323 }
24324
24325 protected function installCode(PackageInterface $package)
24326 {
24327 parent::installCode($package);
24328
24329 $isWindows = Platform::isWindows();
24330 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
24331
24332 if (!$isWindows) {
24333 $php_bin = '/usr/bin/env ' . $php_bin;
24334 }
24335
24336 $installPath = $this->getInstallPath($package);
24337 $vars = array(
24338 'os' => $isWindows ? 'windows' : 'linux',
24339 'php_bin' => $php_bin,
24340 'pear_php' => $installPath,
24341 'php_dir' => $installPath,
24342 'bin_dir' => $installPath . '/bin',
24343 'data_dir' => $installPath . '/data',
24344 'version' => $package->getPrettyVersion(),
24345 );
24346
24347 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
24348 $pearExtractor = new PearPackageExtractor($packageArchive);
24349 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
24350
24351 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
24352 $this->filesystem->unlink($packageArchive);
24353 }
24354 }
24355 <?php
24356
24357
24358
24359
24360
24361
24362
24363
24364
24365
24366
24367 namespace Composer\Installer;
24368
24369 use Composer\Composer;
24370 use Composer\IO\IOInterface;
24371 use Composer\Repository\InstalledRepositoryInterface;
24372 use Composer\Package\PackageInterface;
24373
24374
24375
24376
24377
24378
24379
24380 class PluginInstaller extends LibraryInstaller
24381 {
24382 private $installationManager;
24383
24384
24385
24386
24387
24388
24389
24390 public function __construct(IOInterface $io, Composer $composer)
24391 {
24392 parent::__construct($io, $composer, 'composer-plugin');
24393 $this->installationManager = $composer->getInstallationManager();
24394 }
24395
24396
24397
24398
24399 public function supports($packageType)
24400 {
24401 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
24402 }
24403
24404
24405
24406
24407 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24408 {
24409 $extra = $package->getExtra();
24410 if (empty($extra['class'])) {
24411 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
24412 }
24413
24414 parent::install($repo, $package);
24415 try {
24416 $this->composer->getPluginManager()->registerPackage($package, true);
24417 } catch (\Exception $e) {
24418
24419  $this->io->writeError('Plugin installation failed, rolling back');
24420 parent::uninstall($repo, $package);
24421 throw $e;
24422 }
24423 }
24424
24425
24426
24427
24428 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24429 {
24430 $extra = $target->getExtra();
24431 if (empty($extra['class'])) {
24432 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
24433 }
24434
24435 parent::update($repo, $initial, $target);
24436 $this->composer->getPluginManager()->registerPackage($target, true);
24437 }
24438 }
24439 <?php
24440
24441
24442
24443
24444
24445
24446
24447
24448
24449
24450
24451 namespace Composer\Installer;
24452
24453 use Composer\Package\PackageInterface;
24454 use Composer\Downloader\DownloadManager;
24455 use Composer\Repository\InstalledRepositoryInterface;
24456 use Composer\Util\Filesystem;
24457
24458
24459
24460
24461
24462
24463
24464 class ProjectInstaller implements InstallerInterface
24465 {
24466 private $installPath;
24467 private $downloadManager;
24468 private $filesystem;
24469
24470 public function __construct($installPath, DownloadManager $dm)
24471 {
24472 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
24473 $this->downloadManager = $dm;
24474 $this->filesystem = new Filesystem;
24475 }
24476
24477
24478
24479
24480
24481
24482
24483 public function supports($packageType)
24484 {
24485 return true;
24486 }
24487
24488
24489
24490
24491 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24492 {
24493 return false;
24494 }
24495
24496
24497
24498
24499 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24500 {
24501 $installPath = $this->installPath;
24502 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
24503 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
24504 }
24505 if (!is_dir($installPath)) {
24506 mkdir($installPath, 0777, true);
24507 }
24508 $this->downloadManager->download($package, $installPath);
24509 }
24510
24511
24512
24513
24514 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24515 {
24516 throw new \InvalidArgumentException("not supported");
24517 }
24518
24519
24520
24521
24522 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
24523 {
24524 throw new \InvalidArgumentException("not supported");
24525 }
24526
24527
24528
24529
24530
24531
24532
24533 public function getInstallPath(PackageInterface $package)
24534 {
24535 return $this->installPath;
24536 }
24537 }
24538 <?php
24539
24540
24541
24542
24543
24544
24545
24546
24547
24548
24549
24550 namespace Composer\Installer;
24551
24552 use Composer\IO\IOInterface;
24553 use Composer\Package\PackageInterface;
24554 use Composer\Repository\RepositoryInterface;
24555 use Symfony\Component\Console\Formatter\OutputFormatter;
24556
24557
24558
24559
24560
24561
24562 class SuggestedPackagesReporter
24563 {
24564
24565
24566
24567 protected $suggestedPackages = array();
24568
24569
24570
24571
24572 private $io;
24573
24574 public function __construct(IOInterface $io)
24575 {
24576 $this->io = $io;
24577 }
24578
24579
24580
24581
24582 public function getPackages()
24583 {
24584 return $this->suggestedPackages;
24585 }
24586
24587
24588
24589
24590
24591
24592
24593
24594
24595
24596
24597
24598 public function addPackage($source, $target, $reason)
24599 {
24600 $this->suggestedPackages[] = array(
24601 'source' => $source,
24602 'target' => $target,
24603 'reason' => $reason,
24604 );
24605
24606 return $this;
24607 }
24608
24609
24610
24611
24612
24613
24614
24615 public function addSuggestionsFromPackage(PackageInterface $package)
24616 {
24617 $source = $package->getPrettyName();
24618 foreach ($package->getSuggests() as $target => $reason) {
24619 $this->addPackage(
24620 $source,
24621 $target,
24622 $reason
24623 );
24624 }
24625
24626 return $this;
24627 }
24628
24629
24630
24631
24632
24633
24634
24635
24636 public function output(RepositoryInterface $installedRepo = null)
24637 {
24638 $suggestedPackages = $this->getPackages();
24639 $installedPackages = array();
24640 if (null !== $installedRepo && ! empty($suggestedPackages)) {
24641 foreach ($installedRepo->getPackages() as $package) {
24642 $installedPackages = array_merge(
24643 $installedPackages,
24644 $package->getNames()
24645 );
24646 }
24647 }
24648
24649 foreach ($suggestedPackages as $suggestion) {
24650 if (in_array($suggestion['target'], $installedPackages)) {
24651 continue;
24652 }
24653
24654 $this->io->writeError(sprintf(
24655 '%s suggests installing %s%s',
24656 $suggestion['source'],
24657 $this->escapeOutput($suggestion['target']),
24658 $this->escapeOutput('' !== $suggestion['reason'] ? ' ('.$suggestion['reason'].')' : '')
24659 ));
24660 }
24661
24662 return $this;
24663 }
24664
24665
24666
24667
24668
24669 private function escapeOutput($string)
24670 {
24671 return OutputFormatter::escape(
24672 $this->removeControlCharacters($string)
24673 );
24674 }
24675
24676
24677
24678
24679
24680 private function removeControlCharacters($string)
24681 {
24682 return preg_replace(
24683 '/[[:cntrl:]]/',
24684 '',
24685 str_replace("\n", ' ', $string)
24686 );
24687 }
24688 }
24689 <?php
24690
24691
24692
24693
24694
24695
24696
24697
24698
24699
24700
24701 namespace Composer\Json;
24702
24703 use JsonSchema\Validator;
24704 use Seld\JsonLint\JsonParser;
24705 use Seld\JsonLint\ParsingException;
24706 use Composer\Util\RemoteFilesystem;
24707 use Composer\IO\IOInterface;
24708 use Composer\Downloader\TransportException;
24709
24710
24711
24712
24713
24714
24715
24716 class JsonFile
24717 {
24718 const LAX_SCHEMA = 1;
24719 const STRICT_SCHEMA = 2;
24720
24721 const JSON_UNESCAPED_SLASHES = 64;
24722 const JSON_PRETTY_PRINT = 128;
24723 const JSON_UNESCAPED_UNICODE = 256;
24724
24725 const COMPOSER_SCHEMA_PATH = '/../../../res/composer-schema.json';
24726
24727 private $path;
24728 private $rfs;
24729 private $io;
24730
24731
24732
24733
24734
24735
24736
24737
24738
24739 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
24740 {
24741 $this->path = $path;
24742
24743 if (null === $rfs && preg_match('{^https?://}i', $path)) {
24744 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
24745 }
24746 $this->rfs = $rfs;
24747 $this->io = $io;
24748 }
24749
24750
24751
24752
24753 public function getPath()
24754 {
24755 return $this->path;
24756 }
24757
24758
24759
24760
24761
24762
24763 public function exists()
24764 {
24765 return is_file($this->path);
24766 }
24767
24768
24769
24770
24771
24772
24773
24774 public function read()
24775 {
24776 try {
24777 if ($this->rfs) {
24778 $json = $this->rfs->getContents($this->path, $this->path, false);
24779 } else {
24780 if ($this->io && $this->io->isDebug()) {
24781 $this->io->writeError('Reading ' . $this->path);
24782 }
24783 $json = file_get_contents($this->path);
24784 }
24785 } catch (TransportException $e) {
24786 throw new \RuntimeException($e->getMessage(), 0, $e);
24787 } catch (\Exception $e) {
24788 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
24789 }
24790
24791 return static::parseJson($json, $this->path);
24792 }
24793
24794
24795
24796
24797
24798
24799
24800
24801 public function write(array $hash, $options = 448)
24802 {
24803 $dir = dirname($this->path);
24804 if (!is_dir($dir)) {
24805 if (file_exists($dir)) {
24806 throw new \UnexpectedValueException(
24807 $dir.' exists and is not a directory.'
24808 );
24809 }
24810 if (!@mkdir($dir, 0777, true)) {
24811 throw new \UnexpectedValueException(
24812 $dir.' does not exist and could not be created.'
24813 );
24814 }
24815 }
24816
24817 $retries = 3;
24818 while ($retries--) {
24819 try {
24820 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
24821 break;
24822 } catch (\Exception $e) {
24823 if ($retries) {
24824 usleep(500000);
24825 continue;
24826 }
24827
24828 throw $e;
24829 }
24830 }
24831 }
24832
24833
24834
24835
24836
24837
24838
24839
24840
24841 public function validateSchema($schema = self::STRICT_SCHEMA, $schemaFile = null)
24842 {
24843 $content = file_get_contents($this->path);
24844 $data = json_decode($content);
24845
24846 if (null === $data && 'null' !== $content) {
24847 self::validateSyntax($content, $this->path);
24848 }
24849
24850 if (null === $schemaFile) {
24851 $schemaFile = __DIR__ . self::COMPOSER_SCHEMA_PATH;
24852 }
24853
24854
24855  if (false === strpos($schemaFile, '://')) {
24856 $schemaFile = 'file://' . $schemaFile;
24857 }
24858
24859 $schemaData = (object) array('$ref' => $schemaFile);
24860
24861 if ($schema === self::LAX_SCHEMA) {
24862 $schemaData->additionalProperties = true;
24863 $schemaData->required = array();
24864 }
24865
24866 $validator = new Validator();
24867 $validator->check($data, $schemaData);
24868
24869
24870
24871 if (!$validator->isValid()) {
24872 $errors = array();
24873 foreach ((array) $validator->getErrors() as $error) {
24874 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
24875 }
24876 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
24877 }
24878
24879 return true;
24880 }
24881
24882
24883
24884
24885
24886
24887
24888
24889 public static function encode($data, $options = 448)
24890 {
24891 if (PHP_VERSION_ID >= 50400) {
24892 $json = json_encode($data, $options);
24893 if (false === $json) {
24894 self::throwEncodeError(json_last_error());
24895 }
24896
24897
24898  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
24899 $json = preg_replace('/\[\s+\]/', '[]', $json);
24900 $json = preg_replace('/\{\s+\}/', '{}', $json);
24901 }
24902
24903 return $json;
24904 }
24905
24906 $json = json_encode($data);
24907 if (false === $json) {
24908 self::throwEncodeError(json_last_error());
24909 }
24910
24911 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
24912 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
24913 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
24914
24915 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
24916 return $json;
24917 }
24918
24919 return JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
24920 }
24921
24922
24923
24924
24925
24926
24927
24928 private static function throwEncodeError($code)
24929 {
24930 switch ($code) {
24931 case JSON_ERROR_DEPTH:
24932 $msg = 'Maximum stack depth exceeded';
24933 break;
24934 case JSON_ERROR_STATE_MISMATCH:
24935 $msg = 'Underflow or the modes mismatch';
24936 break;
24937 case JSON_ERROR_CTRL_CHAR:
24938 $msg = 'Unexpected control character found';
24939 break;
24940 case JSON_ERROR_UTF8:
24941 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
24942 break;
24943 default:
24944 $msg = 'Unknown error';
24945 }
24946
24947 throw new \RuntimeException('JSON encoding failed: '.$msg);
24948 }
24949
24950
24951
24952
24953
24954
24955
24956
24957
24958 public static function parseJson($json, $file = null)
24959 {
24960 if (null === $json) {
24961 return;
24962 }
24963 $data = json_decode($json, true);
24964 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
24965 self::validateSyntax($json, $file);
24966 }
24967
24968 return $data;
24969 }
24970
24971
24972
24973
24974
24975
24976
24977
24978
24979
24980 protected static function validateSyntax($json, $file = null)
24981 {
24982 $parser = new JsonParser();
24983 $result = $parser->lint($json);
24984 if (null === $result) {
24985 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
24986 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
24987 }
24988
24989 return true;
24990 }
24991
24992 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
24993 }
24994 }
24995 <?php
24996
24997
24998
24999
25000
25001
25002
25003
25004
25005
25006
25007 namespace Composer\Json;
25008
25009
25010
25011
25012
25013
25014
25015
25016
25017 class JsonFormatter
25018 {
25019
25020
25021
25022
25023
25024
25025
25026
25027
25028
25029
25030
25031 public static function format($json, $unescapeUnicode, $unescapeSlashes)
25032 {
25033 $result = '';
25034 $pos = 0;
25035 $strLen = strlen($json);
25036 $indentStr = '    ';
25037 $newLine = "\n";
25038 $outOfQuotes = true;
25039 $buffer = '';
25040 $noescape = true;
25041
25042 for ($i = 0; $i < $strLen; $i++) {
25043
25044  $char = substr($json, $i, 1);
25045
25046
25047  if ('"' === $char && $noescape) {
25048 $outOfQuotes = !$outOfQuotes;
25049 }
25050
25051 if (!$outOfQuotes) {
25052 $buffer .= $char;
25053 $noescape = '\\' === $char ? !$noescape : true;
25054 continue;
25055 } elseif ('' !== $buffer) {
25056 if ($unescapeSlashes) {
25057 $buffer = str_replace('\\/', '/', $buffer);
25058 }
25059
25060 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
25061
25062  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
25063 $l = strlen($match[1]);
25064
25065 if ($l % 2) {
25066 $code = hexdec($match[2]);
25067
25068  
25069  if (0xD800 <= $code && 0xDFFF >= $code) {
25070 return $match[0];
25071 }
25072
25073 return str_repeat('\\', $l - 1) . mb_convert_encoding(
25074 pack('H*', $match[2]),
25075 'UTF-8',
25076 'UCS-2BE'
25077 );
25078 }
25079
25080 return $match[0];
25081 }, $buffer);
25082 }
25083
25084 $result .= $buffer.$char;
25085 $buffer = '';
25086 continue;
25087 }
25088
25089 if (':' === $char) {
25090
25091  $char .= ' ';
25092 } elseif ('}' === $char || ']' === $char) {
25093 $pos--;
25094 $prevChar = substr($json, $i - 1, 1);
25095
25096 if ('{' !== $prevChar && '[' !== $prevChar) {
25097
25098  
25099  $result .= $newLine;
25100 for ($j = 0; $j < $pos; $j++) {
25101 $result .= $indentStr;
25102 }
25103 } else {
25104
25105  $result = rtrim($result);
25106 }
25107 }
25108
25109 $result .= $char;
25110
25111
25112  
25113  if (',' === $char || '{' === $char || '[' === $char) {
25114 $result .= $newLine;
25115
25116 if ('{' === $char || '[' === $char) {
25117 $pos++;
25118 }
25119
25120 for ($j = 0; $j < $pos; $j++) {
25121 $result .= $indentStr;
25122 }
25123 }
25124 }
25125
25126 return $result;
25127 }
25128 }
25129 <?php
25130
25131
25132
25133
25134
25135
25136
25137
25138
25139
25140
25141 namespace Composer\Json;
25142
25143 use Composer\Repository\PlatformRepository;
25144
25145
25146
25147
25148 class JsonManipulator
25149 {
25150 private static $DEFINES = '(?(DEFINE)
25151        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
25152        (?<boolean>   true | false | null )
25153        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
25154        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
25155        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
25156        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
25157        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
25158     )';
25159
25160 private $contents;
25161 private $newline;
25162 private $indent;
25163
25164 public function __construct($contents)
25165 {
25166 $contents = trim($contents);
25167 if ($contents === '') {
25168 $contents = '{}';
25169 }
25170 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
25171 throw new \InvalidArgumentException('The json file must be an object ({})');
25172 }
25173 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
25174 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
25175 $this->detectIndenting();
25176 }
25177
25178 public function getContents()
25179 {
25180 return $this->contents . $this->newline;
25181 }
25182
25183 public function addLink($type, $package, $constraint, $sortPackages = false)
25184 {
25185 $decoded = JsonFile::parseJson($this->contents);
25186
25187
25188  if (!isset($decoded[$type])) {
25189 return $this->addMainKey($type, array($package => $constraint));
25190 }
25191
25192 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
25193 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
25194 if (!$this->pregMatch($regex, $this->contents, $matches)) {
25195 return false;
25196 }
25197
25198 $links = $matches['value'];
25199
25200
25201  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
25202 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
25203 if ($this->pregMatch($regex, $links, $packageMatches)) {
25204
25205  $existingPackage = $packageMatches['package'];
25206 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
25207 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
25208 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
25209 }, $links);
25210 } else {
25211 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
25212
25213  $links = preg_replace(
25214 '{'.preg_quote($match[1]).'$}',
25215
25216  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
25217 $links
25218 );
25219 } else {
25220
25221  $links = '{' . $this->newline .
25222 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
25223 $this->indent . '}';
25224 }
25225 }
25226
25227 if (true === $sortPackages) {
25228 $requirements = json_decode($links, true);
25229 $this->sortPackages($requirements);
25230 $links = $this->format($requirements);
25231 }
25232
25233 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
25234
25235 return true;
25236 }
25237
25238
25239
25240
25241
25242
25243
25244
25245 private function sortPackages(array &$packages = array())
25246 {
25247 $prefix = function ($requirement) {
25248 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
25249 return preg_replace(
25250 array(
25251 '/^php/',
25252 '/^hhvm/',
25253 '/^ext/',
25254 '/^lib/',
25255 '/^\D/',
25256 ),
25257 array(
25258 '0-$0',
25259 '1-$0',
25260 '2-$0',
25261 '3-$0',
25262 '4-$0',
25263 ),
25264 $requirement
25265 );
25266 }
25267
25268 return '5-'.$requirement;
25269 };
25270
25271 uksort($packages, function ($a, $b) use ($prefix) {
25272 return strnatcmp($prefix($a), $prefix($b));
25273 });
25274 }
25275
25276 public function addRepository($name, $config)
25277 {
25278 return $this->addSubNode('repositories', $name, $config);
25279 }
25280
25281 public function removeRepository($name)
25282 {
25283 return $this->removeSubNode('repositories', $name);
25284 }
25285
25286 public function addConfigSetting($name, $value)
25287 {
25288 return $this->addSubNode('config', $name, $value);
25289 }
25290
25291 public function removeConfigSetting($name)
25292 {
25293 return $this->removeSubNode('config', $name);
25294 }
25295
25296 public function addProperty($name, $value)
25297 {
25298 if (substr($name, 0, 6) === 'extra.') {
25299 return $this->addSubNode('extra', substr($name, 6), $value);
25300 }
25301
25302 if (substr($name, 0, 8) === 'scripts.') {
25303 return $this->addSubNode('scripts', substr($name, 8), $value);
25304 }
25305
25306 return $this->addMainKey($name, $value);
25307 }
25308
25309 public function removeProperty($name)
25310 {
25311 if (substr($name, 0, 6) === 'extra.') {
25312 return $this->removeSubNode('extra', substr($name, 6));
25313 }
25314
25315 if (substr($name, 0, 8) === 'scripts.') {
25316 return $this->removeSubNode('scripts', substr($name, 8));
25317 }
25318
25319 return $this->removeMainKey($name);
25320 }
25321
25322 public function addSubNode($mainNode, $name, $value)
25323 {
25324 $decoded = JsonFile::parseJson($this->contents);
25325
25326 $subName = null;
25327 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
25328 list($name, $subName) = explode('.', $name, 2);
25329 }
25330
25331
25332  if (!isset($decoded[$mainNode])) {
25333 if ($subName !== null) {
25334 $this->addMainKey($mainNode, array($name => array($subName => $value)));
25335 } else {
25336 $this->addMainKey($mainNode, array($name => $value));
25337 }
25338
25339 return true;
25340 }
25341
25342
25343  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
25344 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
25345
25346 try {
25347 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
25348 return false;
25349 }
25350 } catch (\RuntimeException $e) {
25351 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
25352 return false;
25353 }
25354 throw $e;
25355 }
25356
25357 $children = $match['content'];
25358
25359  if (!@json_decode($children)) {
25360 return false;
25361 }
25362
25363 $that = $this;
25364
25365
25366  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
25367 if ($this->pregMatch($childRegex, $children, $matches)) {
25368 $children = preg_replace_callback($childRegex, function ($matches) use ($subName, $value, $that) {
25369 if ($subName !== null) {
25370 $curVal = json_decode($matches['content'], true);
25371 if (!is_array($curVal)) {
25372 $curVal = array();
25373 }
25374 $curVal[$subName] = $value;
25375 $value = $curVal;
25376 }
25377
25378 return $matches['start'] . $that->format($value, 1) . $matches['end'];
25379 }, $children);
25380 } else {
25381 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
25382
25383 $whitespace = '';
25384 if (!empty($match['trailingspace'])) {
25385 $whitespace = $match['trailingspace'];
25386 }
25387
25388 if (!empty($match['content'])) {
25389 if ($subName !== null) {
25390 $value = array($subName => $value);
25391 }
25392
25393
25394  $children = preg_replace(
25395 '#'.$whitespace.'}$#',
25396 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
25397 $children
25398 );
25399 } else {
25400 if ($subName !== null) {
25401 $value = array($subName => $value);
25402 }
25403
25404
25405  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
25406 }
25407 }
25408
25409 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
25410 return $m['start'] . $children . $m['end'];
25411 }, $this->contents);
25412
25413 return true;
25414 }
25415
25416 public function removeSubNode($mainNode, $name)
25417 {
25418 $decoded = JsonFile::parseJson($this->contents);
25419
25420
25421  if (empty($decoded[$mainNode])) {
25422 return true;
25423 }
25424
25425
25426  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
25427 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
25428 try {
25429 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
25430 return false;
25431 }
25432 } catch (\RuntimeException $e) {
25433 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
25434 return false;
25435 }
25436 throw $e;
25437 }
25438
25439 $children = $match['content'];
25440
25441
25442  if (!@json_decode($children, true)) {
25443 return false;
25444 }
25445
25446 $subName = null;
25447 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
25448 list($name, $subName) = explode('.', $name, 2);
25449 }
25450
25451
25452  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
25453 return true;
25454 }
25455
25456
25457  $keyRegex = str_replace('/', '\\\\?/', preg_quote($name));
25458 if ($this->pregMatch('{"'.$keyRegex.'"\s*:}i', $children)) {
25459
25460  if (preg_match_all('{'.self::$DEFINES.'"'.$keyRegex.'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
25461 $bestMatch = '';
25462 foreach ($matches[0] as $match) {
25463 if (strlen($bestMatch) < strlen($match)) {
25464 $bestMatch = $match;
25465 }
25466 }
25467 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
25468 if (1 !== $count) {
25469 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
25470 if (1 !== $count) {
25471 return false;
25472 }
25473 }
25474 }
25475 } else {
25476 $childrenClean = $children;
25477 }
25478
25479
25480  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
25481 if (empty($match['content'])) {
25482 $newline = $this->newline;
25483 $indent = $this->indent;
25484
25485 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
25486 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
25487 }, $this->contents);
25488
25489
25490  if ($subName !== null) {
25491 $curVal = json_decode($children, true);
25492 unset($curVal[$name][$subName]);
25493 $this->addSubNode($mainNode, $name, $curVal[$name]);
25494 }
25495
25496 return true;
25497 }
25498
25499 $that = $this;
25500 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
25501 if ($subName !== null) {
25502 $curVal = json_decode($matches['content'], true);
25503 unset($curVal[$name][$subName]);
25504 $childrenClean = $that->format($curVal, 0);
25505 }
25506
25507 return $matches['start'] . $childrenClean . $matches['end'];
25508 }, $this->contents);
25509
25510 return true;
25511 }
25512
25513 public function addMainKey($key, $content)
25514 {
25515 $decoded = JsonFile::parseJson($this->contents);
25516 $content = $this->format($content);
25517
25518
25519  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
25520 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
25521 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
25522
25523  if (!@json_decode('{'.$matches['key'].'}')) {
25524 return false;
25525 }
25526
25527 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
25528
25529 return true;
25530 }
25531
25532
25533  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
25534 $this->contents = preg_replace(
25535 '#'.$match[1].'\}$#',
25536 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
25537 $this->contents
25538 );
25539
25540 return true;
25541 }
25542
25543
25544  $this->contents = preg_replace(
25545 '#\}$#',
25546 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
25547 $this->contents
25548 );
25549
25550 return true;
25551 }
25552
25553 public function removeMainKey($key)
25554 {
25555 $decoded = JsonFile::parseJson($this->contents);
25556
25557 if (!array_key_exists($key, $decoded)) {
25558 return true;
25559 }
25560
25561
25562  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
25563 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
25564 if ($this->pregMatch($regex, $this->contents, $matches)) {
25565
25566  if (!@json_decode('{'.$matches['removal'].'}')) {
25567 return false;
25568 }
25569
25570
25571  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
25572 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
25573 }
25574
25575 $this->contents = $matches['start'] . $matches['end'];
25576 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
25577 $this->contents = "{\n}";
25578 }
25579
25580 return true;
25581 }
25582
25583 return false;
25584 }
25585
25586 public function format($data, $depth = 0)
25587 {
25588 if (is_array($data)) {
25589 reset($data);
25590
25591 if (is_numeric(key($data))) {
25592 foreach ($data as $key => $val) {
25593 $data[$key] = $this->format($val, $depth + 1);
25594 }
25595
25596 return '['.implode(', ', $data).']';
25597 }
25598
25599 $out = '{' . $this->newline;
25600 $elems = array();
25601 foreach ($data as $key => $val) {
25602 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
25603 }
25604
25605 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
25606 }
25607
25608 return JsonFile::encode($data);
25609 }
25610
25611 protected function detectIndenting()
25612 {
25613 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
25614 $this->indent = $match[1];
25615 } else {
25616 $this->indent = '    ';
25617 }
25618 }
25619
25620 protected function pregMatch($re, $str, &$matches = array())
25621 {
25622 $count = preg_match($re, $str, $matches);
25623
25624 if ($count === false) {
25625 switch (preg_last_error()) {
25626 case PREG_NO_ERROR:
25627 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
25628 case PREG_INTERNAL_ERROR:
25629 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
25630 case PREG_BACKTRACK_LIMIT_ERROR:
25631 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
25632 case PREG_RECURSION_LIMIT_ERROR:
25633 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
25634 case PREG_BAD_UTF8_ERROR:
25635 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
25636 case PREG_BAD_UTF8_OFFSET_ERROR:
25637 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
25638 case 6: 
25639  if (PHP_VERSION_ID > 70000) {
25640 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
25641 }
25642
25643  default:
25644 throw new \RuntimeException('Failed to execute regex: Unknown error');
25645 }
25646 }
25647
25648 return $count;
25649 }
25650 }
25651 <?php
25652
25653
25654
25655
25656
25657
25658
25659
25660
25661
25662
25663 namespace Composer\Json;
25664
25665 use Exception;
25666
25667
25668
25669
25670 class JsonValidationException extends Exception
25671 {
25672 protected $errors;
25673
25674 public function __construct($message, $errors = array(), Exception $previous = null)
25675 {
25676 $this->errors = $errors;
25677 parent::__construct($message, 0, $previous);
25678 }
25679
25680 public function getErrors()
25681 {
25682 return $this->errors;
25683 }
25684 }
25685 <?php
25686
25687
25688
25689
25690
25691
25692
25693
25694
25695
25696
25697 namespace Composer\Package;
25698
25699 use Composer\Semver\Constraint\Constraint;
25700 use Composer\Package\Version\VersionParser;
25701
25702
25703
25704
25705 class AliasPackage extends BasePackage implements CompletePackageInterface
25706 {
25707 protected $version;
25708 protected $prettyVersion;
25709 protected $dev;
25710 protected $rootPackageAlias = false;
25711 protected $stability;
25712
25713
25714 protected $aliasOf;
25715
25716 protected $requires;
25717
25718 protected $devRequires;
25719
25720 protected $conflicts;
25721
25722 protected $provides;
25723
25724 protected $replaces;
25725
25726
25727
25728
25729
25730
25731
25732
25733 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
25734 {
25735 parent::__construct($aliasOf->getName());
25736
25737 $this->version = $version;
25738 $this->prettyVersion = $prettyVersion;
25739 $this->aliasOf = $aliasOf;
25740 $this->stability = VersionParser::parseStability($version);
25741 $this->dev = $this->stability === 'dev';
25742
25743 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
25744 $links = $aliasOf->{'get' . ucfirst($type)}();
25745 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
25746 }
25747 }
25748
25749
25750
25751
25752 public function getAliasOf()
25753 {
25754 return $this->aliasOf;
25755 }
25756
25757
25758
25759
25760 public function getVersion()
25761 {
25762 return $this->version;
25763 }
25764
25765
25766
25767
25768 public function getStability()
25769 {
25770 return $this->stability;
25771 }
25772
25773
25774
25775
25776 public function getPrettyVersion()
25777 {
25778 return $this->prettyVersion;
25779 }
25780
25781
25782
25783
25784 public function isDev()
25785 {
25786 return $this->dev;
25787 }
25788
25789
25790
25791
25792 public function getRequires()
25793 {
25794 return $this->requires;
25795 }
25796
25797
25798
25799
25800 public function getConflicts()
25801 {
25802 return $this->conflicts;
25803 }
25804
25805
25806
25807
25808 public function getProvides()
25809 {
25810 return $this->provides;
25811 }
25812
25813
25814
25815
25816 public function getReplaces()
25817 {
25818 return $this->replaces;
25819 }
25820
25821
25822
25823
25824 public function getDevRequires()
25825 {
25826 return $this->devRequires;
25827 }
25828
25829
25830
25831
25832
25833
25834
25835
25836
25837
25838 public function setRootPackageAlias($value)
25839 {
25840 return $this->rootPackageAlias = $value;
25841 }
25842
25843
25844
25845
25846
25847 public function isRootPackageAlias()
25848 {
25849 return $this->rootPackageAlias;
25850 }
25851
25852
25853
25854
25855
25856
25857
25858 protected function replaceSelfVersionDependencies(array $links, $linkType)
25859 {
25860 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
25861 $newLinks = array();
25862 foreach ($links as $link) {
25863
25864  if ('self.version' === $link->getPrettyConstraint()) {
25865 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
25866 }
25867 }
25868 $links = array_merge($links, $newLinks);
25869 } else {
25870 foreach ($links as $index => $link) {
25871 if ('self.version' === $link->getPrettyConstraint()) {
25872 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
25873 }
25874 }
25875 }
25876
25877 return $links;
25878 }
25879
25880
25881
25882
25883
25884 public function getType()
25885 {
25886 return $this->aliasOf->getType();
25887 }
25888
25889 public function getTargetDir()
25890 {
25891 return $this->aliasOf->getTargetDir();
25892 }
25893
25894 public function getExtra()
25895 {
25896 return $this->aliasOf->getExtra();
25897 }
25898
25899 public function setInstallationSource($type)
25900 {
25901 $this->aliasOf->setInstallationSource($type);
25902 }
25903
25904 public function getInstallationSource()
25905 {
25906 return $this->aliasOf->getInstallationSource();
25907 }
25908
25909 public function getSourceType()
25910 {
25911 return $this->aliasOf->getSourceType();
25912 }
25913
25914 public function getSourceUrl()
25915 {
25916 return $this->aliasOf->getSourceUrl();
25917 }
25918
25919 public function getSourceUrls()
25920 {
25921 return $this->aliasOf->getSourceUrls();
25922 }
25923
25924 public function getSourceReference()
25925 {
25926 return $this->aliasOf->getSourceReference();
25927 }
25928
25929 public function setSourceReference($reference)
25930 {
25931 return $this->aliasOf->setSourceReference($reference);
25932 }
25933
25934 public function setSourceMirrors($mirrors)
25935 {
25936 return $this->aliasOf->setSourceMirrors($mirrors);
25937 }
25938
25939 public function getSourceMirrors()
25940 {
25941 return $this->aliasOf->getSourceMirrors();
25942 }
25943
25944 public function getDistType()
25945 {
25946 return $this->aliasOf->getDistType();
25947 }
25948
25949 public function getDistUrl()
25950 {
25951 return $this->aliasOf->getDistUrl();
25952 }
25953
25954 public function getDistUrls()
25955 {
25956 return $this->aliasOf->getDistUrls();
25957 }
25958
25959 public function getDistReference()
25960 {
25961 return $this->aliasOf->getDistReference();
25962 }
25963
25964 public function setDistReference($reference)
25965 {
25966 return $this->aliasOf->setDistReference($reference);
25967 }
25968
25969 public function getDistSha1Checksum()
25970 {
25971 return $this->aliasOf->getDistSha1Checksum();
25972 }
25973
25974 public function setTransportOptions(array $options)
25975 {
25976 return $this->aliasOf->setTransportOptions($options);
25977 }
25978
25979 public function getTransportOptions()
25980 {
25981 return $this->aliasOf->getTransportOptions();
25982 }
25983
25984 public function setDistMirrors($mirrors)
25985 {
25986 return $this->aliasOf->setDistMirrors($mirrors);
25987 }
25988
25989 public function getDistMirrors()
25990 {
25991 return $this->aliasOf->getDistMirrors();
25992 }
25993
25994 public function getScripts()
25995 {
25996 return $this->aliasOf->getScripts();
25997 }
25998
25999 public function getLicense()
26000 {
26001 return $this->aliasOf->getLicense();
26002 }
26003
26004 public function getAutoload()
26005 {
26006 return $this->aliasOf->getAutoload();
26007 }
26008
26009 public function getDevAutoload()
26010 {
26011 return $this->aliasOf->getDevAutoload();
26012 }
26013
26014 public function getIncludePaths()
26015 {
26016 return $this->aliasOf->getIncludePaths();
26017 }
26018
26019 public function getRepositories()
26020 {
26021 return $this->aliasOf->getRepositories();
26022 }
26023
26024 public function getReleaseDate()
26025 {
26026 return $this->aliasOf->getReleaseDate();
26027 }
26028
26029 public function getBinaries()
26030 {
26031 return $this->aliasOf->getBinaries();
26032 }
26033
26034 public function getKeywords()
26035 {
26036 return $this->aliasOf->getKeywords();
26037 }
26038
26039 public function getDescription()
26040 {
26041 return $this->aliasOf->getDescription();
26042 }
26043
26044 public function getHomepage()
26045 {
26046 return $this->aliasOf->getHomepage();
26047 }
26048
26049 public function getSuggests()
26050 {
26051 return $this->aliasOf->getSuggests();
26052 }
26053
26054 public function getAuthors()
26055 {
26056 return $this->aliasOf->getAuthors();
26057 }
26058
26059 public function getSupport()
26060 {
26061 return $this->aliasOf->getSupport();
26062 }
26063
26064 public function getNotificationUrl()
26065 {
26066 return $this->aliasOf->getNotificationUrl();
26067 }
26068
26069 public function getArchiveExcludes()
26070 {
26071 return $this->aliasOf->getArchiveExcludes();
26072 }
26073
26074 public function isAbandoned()
26075 {
26076 return $this->aliasOf->isAbandoned();
26077 }
26078
26079 public function getReplacementPackage()
26080 {
26081 return $this->aliasOf->getReplacementPackage();
26082 }
26083
26084 public function __toString()
26085 {
26086 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
26087 }
26088
26089 public function setDistUrl($url)
26090 {
26091 return $this->aliasOf->setDistUrl($url);
26092 }
26093
26094 public function setDistType($type)
26095 {
26096 return $this->aliasOf->setDistType($type);
26097 }
26098 }
26099 <?php
26100
26101
26102
26103
26104
26105
26106
26107
26108
26109
26110
26111 namespace Composer\Package\Archiver;
26112
26113 use FilterIterator;
26114 use PharData;
26115
26116 class ArchivableFilesFilter extends FilterIterator
26117 {
26118 private $dirs = array();
26119
26120
26121
26122
26123 public function accept()
26124 {
26125 $file = $this->getInnerIterator()->current();
26126 if ($file->isDir()) {
26127 $this->dirs[] = (string) $file;
26128
26129 return false;
26130 }
26131
26132 return true;
26133 }
26134
26135 public function addEmptyDir(PharData $phar, $sources)
26136 {
26137 foreach ($this->dirs as $filepath) {
26138 $localname = str_replace($sources . "/", '', $filepath);
26139 $phar->addEmptyDir($localname);
26140 }
26141 }
26142 }
26143 <?php
26144
26145
26146
26147
26148
26149
26150
26151
26152
26153
26154
26155 namespace Composer\Package\Archiver;
26156
26157 use Composer\Util\Filesystem;
26158 use FilesystemIterator;
26159 use Symfony\Component\Finder\Finder;
26160 use Symfony\Component\Finder\SplFileInfo;
26161
26162
26163
26164
26165
26166
26167
26168
26169
26170 class ArchivableFilesFinder extends \FilterIterator
26171 {
26172
26173
26174
26175 protected $finder;
26176
26177
26178
26179
26180
26181
26182
26183
26184 public function __construct($sources, array $excludes, $ignoreFilters = false)
26185 {
26186 $fs = new Filesystem();
26187
26188 $sources = $fs->normalizePath($sources);
26189
26190 if ($ignoreFilters) {
26191 $filters = array();
26192 } else {
26193 $filters = array(
26194 new HgExcludeFilter($sources),
26195 new GitExcludeFilter($sources),
26196 new ComposerExcludeFilter($sources, $excludes),
26197 );
26198 }
26199
26200 $this->finder = new Finder();
26201
26202 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
26203 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
26204 return false;
26205 }
26206
26207 $relativePath = preg_replace(
26208 '#^'.preg_quote($sources, '#').'#',
26209 '',
26210 $fs->normalizePath($file->getRealPath())
26211 );
26212
26213 $exclude = false;
26214 foreach ($filters as $filter) {
26215 $exclude = $filter->filter($relativePath, $exclude);
26216 }
26217
26218 return !$exclude;
26219 };
26220
26221 if (method_exists($filter, 'bindTo')) {
26222 $filter = $filter->bindTo(null);
26223 }
26224
26225 $this->finder
26226 ->in($sources)
26227 ->filter($filter)
26228 ->ignoreVCS(true)
26229 ->ignoreDotFiles(false);
26230
26231 parent::__construct($this->finder->getIterator());
26232 }
26233
26234 public function accept()
26235 {
26236
26237 $current = $this->getInnerIterator()->current();
26238
26239 if (!$current->isDir()) {
26240 return true;
26241 }
26242
26243 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
26244
26245 return !$iterator->valid();
26246 }
26247 }
26248 <?php
26249
26250
26251
26252
26253
26254
26255
26256
26257
26258
26259
26260 namespace Composer\Package\Archiver;
26261
26262 use Composer\Downloader\DownloadManager;
26263 use Composer\Package\PackageInterface;
26264 use Composer\Package\RootPackageInterface;
26265 use Composer\Util\Filesystem;
26266 use Composer\Json\JsonFile;
26267
26268
26269
26270
26271
26272 class ArchiveManager
26273 {
26274 protected $downloadManager;
26275
26276 protected $archivers = array();
26277
26278
26279
26280
26281 protected $overwriteFiles = true;
26282
26283
26284
26285
26286 public function __construct(DownloadManager $downloadManager)
26287 {
26288 $this->downloadManager = $downloadManager;
26289 }
26290
26291
26292
26293
26294 public function addArchiver(ArchiverInterface $archiver)
26295 {
26296 $this->archivers[] = $archiver;
26297 }
26298
26299
26300
26301
26302
26303
26304
26305
26306 public function setOverwriteFiles($overwriteFiles)
26307 {
26308 $this->overwriteFiles = $overwriteFiles;
26309
26310 return $this;
26311 }
26312
26313
26314
26315
26316
26317
26318
26319
26320 public function getPackageFilename(PackageInterface $package)
26321 {
26322 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
26323
26324 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
26325 array_push($nameParts, $package->getDistReference(), $package->getDistType());
26326 } else {
26327 array_push($nameParts, $package->getPrettyVersion(), $package->getDistReference());
26328 }
26329
26330 if ($package->getSourceReference()) {
26331 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
26332 }
26333
26334 $name = implode('-', array_filter($nameParts, function ($p) {
26335 return !empty($p);
26336 }));
26337
26338 return str_replace('/', '-', $name);
26339 }
26340
26341
26342
26343
26344
26345
26346
26347
26348
26349
26350
26351
26352
26353
26354 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
26355 {
26356 if (empty($format)) {
26357 throw new \InvalidArgumentException('Format must be specified');
26358 }
26359
26360
26361  $usableArchiver = null;
26362 foreach ($this->archivers as $archiver) {
26363 if ($archiver->supports($format, $package->getSourceType())) {
26364 $usableArchiver = $archiver;
26365 break;
26366 }
26367 }
26368
26369
26370  if (null === $usableArchiver) {
26371 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
26372 }
26373
26374 $filesystem = new Filesystem();
26375 if (null === $fileName) {
26376 $packageName = $this->getPackageFilename($package);
26377 } else {
26378 $packageName = $fileName;
26379 }
26380
26381
26382  $filesystem->ensureDirectoryExists($targetDir);
26383 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
26384 $filesystem->ensureDirectoryExists(dirname($target));
26385
26386 if (!$this->overwriteFiles && file_exists($target)) {
26387 return $target;
26388 }
26389
26390 if ($package instanceof RootPackageInterface) {
26391 $sourcePath = realpath('.');
26392 } else {
26393
26394  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
26395 $filesystem->ensureDirectoryExists($sourcePath);
26396
26397 try {
26398
26399  $this->downloadManager->download($package, $sourcePath);
26400 } catch (\Exception $e) {
26401 $filesystem->removeDirectory($sourcePath);
26402 throw $e;
26403 }
26404
26405
26406  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
26407 $jsonFile = new JsonFile($composerJsonPath);
26408 $jsonData = $jsonFile->read();
26409 if (!empty($jsonData['archive']['exclude'])) {
26410 $package->setArchiveExcludes($jsonData['archive']['exclude']);
26411 }
26412 }
26413 }
26414
26415
26416  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
26417 $filesystem->ensureDirectoryExists(dirname($tempTarget));
26418
26419 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
26420 $filesystem->rename($archivePath, $target);
26421
26422
26423  if (!$package instanceof RootPackageInterface) {
26424 $filesystem->removeDirectory($sourcePath);
26425 }
26426 $filesystem->remove($tempTarget);
26427
26428 return $target;
26429 }
26430 }
26431 <?php
26432
26433
26434
26435
26436
26437
26438
26439
26440
26441
26442
26443 namespace Composer\Package\Archiver;
26444
26445
26446
26447
26448
26449
26450 interface ArchiverInterface
26451 {
26452
26453
26454
26455
26456
26457
26458
26459
26460
26461
26462 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
26463
26464
26465
26466
26467
26468
26469
26470
26471
26472 public function supports($format, $sourceType);
26473 }
26474 <?php
26475
26476
26477
26478
26479
26480
26481
26482
26483
26484
26485
26486 namespace Composer\Package\Archiver;
26487
26488 use Symfony\Component\Finder;
26489
26490
26491
26492
26493 abstract class BaseExcludeFilter
26494 {
26495
26496
26497
26498 protected $sourcePath;
26499
26500
26501
26502
26503 protected $excludePatterns;
26504
26505
26506
26507
26508 public function __construct($sourcePath)
26509 {
26510 $this->sourcePath = $sourcePath;
26511 $this->excludePatterns = array();
26512 }
26513
26514
26515
26516
26517
26518
26519
26520
26521
26522
26523
26524 public function filter($relativePath, $exclude)
26525 {
26526 foreach ($this->excludePatterns as $patternData) {
26527 list($pattern, $negate, $stripLeadingSlash) = $patternData;
26528
26529 if ($stripLeadingSlash) {
26530 $path = substr($relativePath, 1);
26531 } else {
26532 $path = $relativePath;
26533 }
26534
26535 if (preg_match($pattern, $path)) {
26536 $exclude = !$negate;
26537 }
26538 }
26539
26540 return $exclude;
26541 }
26542
26543
26544
26545
26546
26547
26548
26549
26550
26551 protected function parseLines(array $lines, $lineParser)
26552 {
26553 return array_filter(
26554 array_map(
26555 function ($line) use ($lineParser) {
26556 $line = trim($line);
26557
26558 if (!$line || 0 === strpos($line, '#')) {
26559 return null;
26560 }
26561
26562 return call_user_func($lineParser, $line);
26563 },
26564 $lines
26565 ),
26566 function ($pattern) {
26567 return $pattern !== null;
26568 }
26569 );
26570 }
26571
26572
26573
26574
26575
26576
26577
26578
26579 protected function generatePatterns($rules)
26580 {
26581 $patterns = array();
26582 foreach ($rules as $rule) {
26583 $patterns[] = $this->generatePattern($rule);
26584 }
26585
26586 return $patterns;
26587 }
26588
26589
26590
26591
26592
26593
26594
26595
26596 protected function generatePattern($rule)
26597 {
26598 $negate = false;
26599 $pattern = '{';
26600
26601 if (strlen($rule) && $rule[0] === '!') {
26602 $negate = true;
26603 $rule = substr($rule, 1);
26604 }
26605
26606 if (strlen($rule) && $rule[0] === '/') {
26607 $pattern .= '^/';
26608 $rule = substr($rule, 1);
26609 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
26610 $pattern .= '/';
26611 $rule = substr($rule, 0, -1);
26612 } elseif (false === strpos($rule, '/')) {
26613 $pattern .= '/';
26614 }
26615
26616
26617  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
26618
26619 return array($pattern . '}', $negate, false);
26620 }
26621 }
26622 <?php
26623
26624
26625
26626
26627
26628
26629
26630
26631
26632
26633
26634 namespace Composer\Package\Archiver;
26635
26636
26637
26638
26639
26640
26641 class ComposerExcludeFilter extends BaseExcludeFilter
26642 {
26643
26644
26645
26646
26647 public function __construct($sourcePath, array $excludeRules)
26648 {
26649 parent::__construct($sourcePath);
26650 $this->excludePatterns = $this->generatePatterns($excludeRules);
26651 }
26652 }
26653 <?php
26654
26655
26656
26657
26658
26659
26660
26661
26662
26663
26664
26665 namespace Composer\Package\Archiver;
26666
26667
26668
26669
26670
26671
26672
26673
26674 class GitExcludeFilter extends BaseExcludeFilter
26675 {
26676
26677
26678
26679
26680
26681 public function __construct($sourcePath)
26682 {
26683 parent::__construct($sourcePath);
26684
26685 if (file_exists($sourcePath.'/.gitignore')) {
26686 $this->excludePatterns = $this->parseLines(
26687 file($sourcePath.'/.gitignore'),
26688 array($this, 'parseGitIgnoreLine')
26689 );
26690 }
26691 if (file_exists($sourcePath.'/.gitattributes')) {
26692 $this->excludePatterns = array_merge(
26693 $this->excludePatterns,
26694 $this->parseLines(
26695 file($sourcePath.'/.gitattributes'),
26696 array($this, 'parseGitAttributesLine')
26697 )
26698 );
26699 }
26700 }
26701
26702
26703
26704
26705
26706
26707
26708
26709 public function parseGitIgnoreLine($line)
26710 {
26711 return $this->generatePattern($line);
26712 }
26713
26714
26715
26716
26717
26718
26719
26720
26721 public function parseGitAttributesLine($line)
26722 {
26723 $parts = preg_split('#\s+#', $line);
26724
26725 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
26726 return $this->generatePattern($parts[0]);
26727 }
26728
26729 return null;
26730 }
26731 }
26732 <?php
26733
26734
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744 namespace Composer\Package\Archiver;
26745
26746 use Symfony\Component\Finder;
26747
26748
26749
26750
26751
26752
26753 class HgExcludeFilter extends BaseExcludeFilter
26754 {
26755 const HG_IGNORE_REGEX = 1;
26756 const HG_IGNORE_GLOB = 2;
26757
26758
26759
26760
26761
26762 protected $patternMode;
26763
26764
26765
26766
26767
26768
26769 public function __construct($sourcePath)
26770 {
26771 parent::__construct($sourcePath);
26772
26773 $this->patternMode = self::HG_IGNORE_REGEX;
26774
26775 if (file_exists($sourcePath.'/.hgignore')) {
26776 $this->excludePatterns = $this->parseLines(
26777 file($sourcePath.'/.hgignore'),
26778 array($this, 'parseHgIgnoreLine')
26779 );
26780 }
26781 }
26782
26783
26784
26785
26786
26787
26788
26789
26790 public function parseHgIgnoreLine($line)
26791 {
26792 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
26793 if ($matches[1] === 'glob') {
26794 $this->patternMode = self::HG_IGNORE_GLOB;
26795 } else {
26796 $this->patternMode = self::HG_IGNORE_REGEX;
26797 }
26798
26799 return null;
26800 }
26801
26802 if ($this->patternMode == self::HG_IGNORE_GLOB) {
26803 return $this->patternFromGlob($line);
26804 }
26805
26806 return $this->patternFromRegex($line);
26807 }
26808
26809
26810
26811
26812
26813
26814
26815
26816 protected function patternFromGlob($line)
26817 {
26818 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
26819 $pattern = str_replace('[^/]*', '.*', $pattern);
26820
26821 return array($pattern, false, true);
26822 }
26823
26824
26825
26826
26827
26828
26829
26830
26831 public function patternFromRegex($line)
26832 {
26833
26834  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
26835
26836 return array($pattern, false, true);
26837 }
26838 }
26839 <?php
26840
26841
26842
26843
26844
26845
26846
26847
26848
26849
26850
26851 namespace Composer\Package\Archiver;
26852
26853
26854
26855
26856
26857
26858 class PharArchiver implements ArchiverInterface
26859 {
26860 protected static $formats = array(
26861 'zip' => \Phar::ZIP,
26862 'tar' => \Phar::TAR,
26863 'tar.gz' => \Phar::TAR,
26864 'tar.bz2' => \Phar::TAR,
26865 );
26866
26867 protected static $compressFormats = array(
26868 'tar.gz' => \Phar::GZ,
26869 'tar.bz2' => \Phar::BZ2,
26870 );
26871
26872
26873
26874
26875 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
26876 {
26877 $sources = realpath($sources);
26878
26879
26880  if (file_exists($target)) {
26881 unlink($target);
26882 }
26883
26884 try {
26885 $filename = substr($target, 0, strrpos($target, $format) - 1);
26886
26887
26888  if (isset(static::$compressFormats[$format])) {
26889
26890  $target = $filename . '.tar';
26891 }
26892
26893 $phar = new \PharData($target, null, null, static::$formats[$format]);
26894 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
26895 $filesOnly = new ArchivableFilesFilter($files);
26896 $phar->buildFromIterator($filesOnly, $sources);
26897 $filesOnly->addEmptyDir($phar, $sources);
26898
26899 if (isset(static::$compressFormats[$format])) {
26900
26901  if (!$phar->canCompress(static::$compressFormats[$format])) {
26902 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
26903 }
26904
26905
26906  unlink($target);
26907
26908
26909  $phar->compress(static::$compressFormats[$format]);
26910
26911
26912  $target = $filename . '.' . $format;
26913 }
26914
26915 return $target;
26916 } catch (\UnexpectedValueException $e) {
26917 $message = sprintf(
26918 "Could not create archive '%s' from '%s': %s",
26919 $target,
26920 $sources,
26921 $e->getMessage()
26922 );
26923
26924 throw new \RuntimeException($message, $e->getCode(), $e);
26925 }
26926 }
26927
26928
26929
26930
26931 public function supports($format, $sourceType)
26932 {
26933 return isset(static::$formats[$format]);
26934 }
26935 }
26936 <?php
26937
26938
26939
26940
26941
26942
26943
26944
26945
26946
26947
26948 namespace Composer\Package\Archiver;
26949
26950 use ZipArchive;
26951 use Composer\Util\Filesystem;
26952
26953
26954
26955
26956 class ZipArchiver implements ArchiverInterface
26957 {
26958 protected static $formats = array(
26959 'zip' => 1,
26960 );
26961
26962
26963
26964
26965 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
26966 {
26967 $fs = new Filesystem();
26968 $sources = $fs->normalizePath($sources);
26969
26970 $zip = new ZipArchive();
26971 $res = $zip->open($target, ZipArchive::CREATE);
26972 if ($res === true) {
26973 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
26974 foreach ($files as $file) {
26975
26976 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
26977 $localname = str_replace($sources.'/', '', $filepath);
26978 if ($file->isDir()) {
26979 $zip->addEmptyDir($localname);
26980 } else {
26981 $zip->addFile($filepath, $localname);
26982 }
26983 }
26984 if ($zip->close()) {
26985 return $target;
26986 }
26987 }
26988 $message = sprintf(
26989 "Could not create archive '%s' from '%s': %s",
26990 $target,
26991 $sources,
26992 $zip->getStatusString()
26993 );
26994 throw new \RuntimeException($message);
26995 }
26996
26997
26998
26999
27000 public function supports($format, $sourceType)
27001 {
27002 return isset(static::$formats[$format]) && $this->compressionAvailable();
27003 }
27004
27005 private function compressionAvailable()
27006 {
27007 return class_exists('ZipArchive');
27008 }
27009 }
27010 <?php
27011
27012
27013
27014
27015
27016
27017
27018
27019
27020
27021
27022 namespace Composer\Package;
27023
27024 use Composer\Repository\RepositoryInterface;
27025 use Composer\Repository\PlatformRepository;
27026
27027
27028
27029
27030
27031
27032 abstract class BasePackage implements PackageInterface
27033 {
27034 public static $supportedLinkTypes = array(
27035 'require' => array('description' => 'requires', 'method' => 'requires'),
27036 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
27037 'provide' => array('description' => 'provides', 'method' => 'provides'),
27038 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
27039 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
27040 );
27041
27042 const STABILITY_STABLE = 0;
27043 const STABILITY_RC = 5;
27044 const STABILITY_BETA = 10;
27045 const STABILITY_ALPHA = 15;
27046 const STABILITY_DEV = 20;
27047
27048 public static $stabilities = array(
27049 'stable' => self::STABILITY_STABLE,
27050 'RC' => self::STABILITY_RC,
27051 'beta' => self::STABILITY_BETA,
27052 'alpha' => self::STABILITY_ALPHA,
27053 'dev' => self::STABILITY_DEV,
27054 );
27055
27056
27057
27058
27059
27060 public $id;
27061
27062 protected $name;
27063
27064 protected $prettyName;
27065
27066 protected $repository;
27067
27068 protected $transportOptions = array();
27069
27070
27071
27072
27073
27074
27075 public function __construct($name)
27076 {
27077 $this->prettyName = $name;
27078 $this->name = strtolower($name);
27079 $this->id = -1;
27080 }
27081
27082
27083
27084
27085 public function getName()
27086 {
27087 return $this->name;
27088 }
27089
27090
27091
27092
27093 public function getPrettyName()
27094 {
27095 return $this->prettyName;
27096 }
27097
27098
27099
27100
27101 public function getNames()
27102 {
27103 $names = array(
27104 $this->getName() => true,
27105 );
27106
27107 foreach ($this->getProvides() as $link) {
27108 $names[$link->getTarget()] = true;
27109 }
27110
27111 foreach ($this->getReplaces() as $link) {
27112 $names[$link->getTarget()] = true;
27113 }
27114
27115 return array_keys($names);
27116 }
27117
27118
27119
27120
27121 public function setId($id)
27122 {
27123 $this->id = $id;
27124 }
27125
27126
27127
27128
27129 public function getId()
27130 {
27131 return $this->id;
27132 }
27133
27134
27135
27136
27137 public function setRepository(RepositoryInterface $repository)
27138 {
27139 if ($this->repository && $repository !== $this->repository) {
27140 throw new \LogicException('A package can only be added to one repository');
27141 }
27142 $this->repository = $repository;
27143 }
27144
27145
27146
27147
27148 public function getRepository()
27149 {
27150 return $this->repository;
27151 }
27152
27153
27154
27155
27156 public function getTransportOptions()
27157 {
27158 return $this->transportOptions;
27159 }
27160
27161
27162
27163
27164
27165
27166 public function setTransportOptions(array $options)
27167 {
27168 $this->transportOptions = $options;
27169 }
27170
27171
27172
27173
27174
27175
27176 public function isPlatform()
27177 {
27178 return $this->getRepository() instanceof PlatformRepository;
27179 }
27180
27181
27182
27183
27184
27185
27186 public function getUniqueName()
27187 {
27188 return $this->getName().'-'.$this->getVersion();
27189 }
27190
27191 public function equals(PackageInterface $package)
27192 {
27193 $self = $this;
27194 if ($this instanceof AliasPackage) {
27195 $self = $this->getAliasOf();
27196 }
27197 if ($package instanceof AliasPackage) {
27198 $package = $package->getAliasOf();
27199 }
27200
27201 return $package === $self;
27202 }
27203
27204
27205
27206
27207
27208
27209 public function __toString()
27210 {
27211 return $this->getUniqueName();
27212 }
27213
27214 public function getPrettyString()
27215 {
27216 return $this->getPrettyName().' '.$this->getPrettyVersion();
27217 }
27218
27219
27220
27221
27222 public function getFullPrettyVersion($truncate = true)
27223 {
27224 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
27225 return $this->getPrettyVersion();
27226 }
27227
27228
27229  if ($truncate && strlen($this->getSourceReference()) === 40) {
27230 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
27231 }
27232
27233 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
27234 }
27235
27236 public function getStabilityPriority()
27237 {
27238 return self::$stabilities[$this->getStability()];
27239 }
27240
27241 public function __clone()
27242 {
27243 $this->repository = null;
27244 $this->id = -1;
27245 }
27246
27247
27248
27249
27250
27251
27252
27253
27254 public static function packageNameToRegexp($whiteListedPattern, $wrap = '{^%s$}i')
27255 {
27256 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
27257
27258 return sprintf($wrap, $cleanedWhiteListedPattern);
27259 }
27260 }
27261 <?php
27262
27263
27264
27265
27266
27267
27268
27269
27270
27271
27272
27273 namespace Composer\Package\Comparer;
27274
27275
27276
27277
27278
27279
27280 class Comparer
27281 {
27282 private $source;
27283 private $update;
27284 private $changed;
27285
27286 public function setSource($source)
27287 {
27288 $this->source = $source;
27289 }
27290
27291 public function setUpdate($update)
27292 {
27293 $this->update = $update;
27294 }
27295
27296 public function getChanged($toString = false, $explicated = false)
27297 {
27298 $changed = $this->changed;
27299 if (!count($changed)) {
27300 return false;
27301 }
27302 if ($explicated) {
27303 foreach ($changed as $sectionKey => $itemSection) {
27304 foreach ($itemSection as $itemKey => $item) {
27305 $changed[$sectionKey][$itemKey] = $item.' ('.$sectionKey.')';
27306 }
27307 }
27308 }
27309
27310 if ($toString) {
27311 foreach ($changed as $sectionKey => $itemSection) {
27312 foreach ($itemSection as $itemKey => $item) {
27313 $changed['string'][] = $item."\r\n";
27314 }
27315 }
27316 $changed = implode("\r\n", $changed['string']);
27317 }
27318
27319 return $changed;
27320 }
27321
27322 public function doCompare()
27323 {
27324 $source = array();
27325 $destination = array();
27326 $this->changed = array();
27327 $currentDirectory = getcwd();
27328 chdir($this->source);
27329 $source = $this->doTree('.', $source);
27330 if (!is_array($source)) {
27331 return;
27332 }
27333 chdir($currentDirectory);
27334 chdir($this->update);
27335 $destination = $this->doTree('.', $destination);
27336 if (!is_array($destination)) {
27337 exit;
27338 }
27339 chdir($currentDirectory);
27340 foreach ($source as $dir => $value) {
27341 foreach ($value as $file => $hash) {
27342 if (isset($destination[$dir][$file])) {
27343 if ($hash !== $destination[$dir][$file]) {
27344 $this->changed['changed'][] = $dir.'/'.$file;
27345 }
27346 } else {
27347 $this->changed['removed'][] = $dir.'/'.$file;
27348 }
27349 }
27350 }
27351 foreach ($destination as $dir => $value) {
27352 foreach ($value as $file => $hash) {
27353 if (!isset($source[$dir][$file])) {
27354 $this->changed['added'][] = $dir.'/'.$file;
27355 }
27356 }
27357 }
27358 }
27359
27360 private function doTree($dir, &$array)
27361 {
27362 if ($dh = opendir($dir)) {
27363 while ($file = readdir($dh)) {
27364 if ($file !== '.' && $file !== '..') {
27365 if (is_dir($dir.'/'.$file)) {
27366 if (!count($array)) {
27367 $array[0] = 'Temp';
27368 }
27369 if (!$this->doTree($dir.'/'.$file, $array)) {
27370 return false;
27371 }
27372 } else {
27373 if (filesize($dir.'/'.$file)) {
27374 set_time_limit(30);
27375 $array[$dir][$file] = md5_file($dir.'/'.$file);
27376 }
27377 }
27378 }
27379 }
27380 if (count($array) > 1 && isset($array['0'])) {
27381 unset($array['0']);
27382 }
27383
27384 return $array;
27385 }
27386
27387 return false;
27388 }
27389 }
27390 <?php
27391
27392
27393
27394
27395
27396
27397
27398
27399
27400
27401
27402 namespace Composer\Package;
27403
27404
27405
27406
27407
27408
27409 class CompletePackage extends Package implements CompletePackageInterface
27410 {
27411 protected $repositories;
27412 protected $license = array();
27413 protected $keywords;
27414 protected $authors;
27415 protected $description;
27416 protected $homepage;
27417 protected $scripts = array();
27418 protected $support = array();
27419 protected $abandoned = false;
27420
27421
27422
27423
27424 public function setScripts(array $scripts)
27425 {
27426 $this->scripts = $scripts;
27427 }
27428
27429
27430
27431
27432 public function getScripts()
27433 {
27434 return $this->scripts;
27435 }
27436
27437
27438
27439
27440
27441
27442 public function setRepositories($repositories)
27443 {
27444 $this->repositories = $repositories;
27445 }
27446
27447
27448
27449
27450 public function getRepositories()
27451 {
27452 return $this->repositories;
27453 }
27454
27455
27456
27457
27458
27459
27460 public function setLicense(array $license)
27461 {
27462 $this->license = $license;
27463 }
27464
27465
27466
27467
27468 public function getLicense()
27469 {
27470 return $this->license;
27471 }
27472
27473
27474
27475
27476
27477
27478 public function setKeywords(array $keywords)
27479 {
27480 $this->keywords = $keywords;
27481 }
27482
27483
27484
27485
27486 public function getKeywords()
27487 {
27488 return $this->keywords;
27489 }
27490
27491
27492
27493
27494
27495
27496 public function setAuthors(array $authors)
27497 {
27498 $this->authors = $authors;
27499 }
27500
27501
27502
27503
27504 public function getAuthors()
27505 {
27506 return $this->authors;
27507 }
27508
27509
27510
27511
27512
27513
27514 public function setDescription($description)
27515 {
27516 $this->description = $description;
27517 }
27518
27519
27520
27521
27522 public function getDescription()
27523 {
27524 return $this->description;
27525 }
27526
27527
27528
27529
27530
27531
27532 public function setHomepage($homepage)
27533 {
27534 $this->homepage = $homepage;
27535 }
27536
27537
27538
27539
27540 public function getHomepage()
27541 {
27542 return $this->homepage;
27543 }
27544
27545
27546
27547
27548
27549
27550 public function setSupport(array $support)
27551 {
27552 $this->support = $support;
27553 }
27554
27555
27556
27557
27558 public function getSupport()
27559 {
27560 return $this->support;
27561 }
27562
27563
27564
27565
27566 public function isAbandoned()
27567 {
27568 return (bool) $this->abandoned;
27569 }
27570
27571
27572
27573
27574 public function setAbandoned($abandoned)
27575 {
27576 $this->abandoned = $abandoned;
27577 }
27578
27579
27580
27581
27582
27583
27584 public function getReplacementPackage()
27585 {
27586 return is_string($this->abandoned) ? $this->abandoned : null;
27587 }
27588 }
27589 <?php
27590
27591
27592
27593
27594
27595
27596
27597
27598
27599
27600
27601 namespace Composer\Package;
27602
27603
27604
27605
27606
27607
27608 interface CompletePackageInterface extends PackageInterface
27609 {
27610
27611
27612
27613
27614
27615 public function getScripts();
27616
27617
27618
27619
27620
27621
27622
27623
27624 public function getRepositories();
27625
27626
27627
27628
27629
27630
27631 public function getLicense();
27632
27633
27634
27635
27636
27637
27638 public function getKeywords();
27639
27640
27641
27642
27643
27644
27645 public function getDescription();
27646
27647
27648
27649
27650
27651
27652 public function getHomepage();
27653
27654
27655
27656
27657
27658
27659
27660
27661 public function getAuthors();
27662
27663
27664
27665
27666
27667
27668 public function getSupport();
27669
27670
27671
27672
27673
27674
27675 public function isAbandoned();
27676
27677
27678
27679
27680
27681
27682 public function getReplacementPackage();
27683 }
27684 <?php
27685
27686
27687
27688
27689
27690
27691
27692
27693
27694
27695
27696 namespace Composer\Package\Dumper;
27697
27698 use Composer\Package\BasePackage;
27699 use Composer\Package\PackageInterface;
27700 use Composer\Package\CompletePackageInterface;
27701 use Composer\Package\RootPackageInterface;
27702
27703
27704
27705
27706
27707 class ArrayDumper
27708 {
27709 public function dump(PackageInterface $package)
27710 {
27711 $keys = array(
27712 'binaries' => 'bin',
27713 'type',
27714 'extra',
27715 'installationSource' => 'installation-source',
27716 'autoload',
27717 'devAutoload' => 'autoload-dev',
27718 'notificationUrl' => 'notification-url',
27719 'includePaths' => 'include-path',
27720 );
27721
27722 $data = array();
27723 $data['name'] = $package->getPrettyName();
27724 $data['version'] = $package->getPrettyVersion();
27725 $data['version_normalized'] = $package->getVersion();
27726
27727 if ($package->getTargetDir()) {
27728 $data['target-dir'] = $package->getTargetDir();
27729 }
27730
27731 if ($package->getSourceType()) {
27732 $data['source']['type'] = $package->getSourceType();
27733 $data['source']['url'] = $package->getSourceUrl();
27734 if (null !== ($value = $package->getSourceReference())) {
27735 $data['source']['reference'] = $value;
27736 }
27737 if ($mirrors = $package->getSourceMirrors()) {
27738 $data['source']['mirrors'] = $mirrors;
27739 }
27740 }
27741
27742 if ($package->getDistType()) {
27743 $data['dist']['type'] = $package->getDistType();
27744 $data['dist']['url'] = $package->getDistUrl();
27745 if (null !== ($value = $package->getDistReference())) {
27746 $data['dist']['reference'] = $value;
27747 }
27748 if (null !== ($value = $package->getDistSha1Checksum())) {
27749 $data['dist']['shasum'] = $value;
27750 }
27751 if ($mirrors = $package->getDistMirrors()) {
27752 $data['dist']['mirrors'] = $mirrors;
27753 }
27754 }
27755
27756 if ($package->getArchiveExcludes()) {
27757 $data['archive']['exclude'] = $package->getArchiveExcludes();
27758 }
27759
27760 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
27761 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
27762 foreach ($links as $link) {
27763 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
27764 }
27765 ksort($data[$type]);
27766 }
27767 }
27768
27769 if ($packages = $package->getSuggests()) {
27770 ksort($packages);
27771 $data['suggest'] = $packages;
27772 }
27773
27774 if ($package->getReleaseDate()) {
27775 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
27776 }
27777
27778 $data = $this->dumpValues($package, $keys, $data);
27779
27780 if ($package instanceof CompletePackageInterface) {
27781 $keys = array(
27782 'scripts',
27783 'license',
27784 'authors',
27785 'description',
27786 'homepage',
27787 'keywords',
27788 'repositories',
27789 'support',
27790 );
27791
27792 $data = $this->dumpValues($package, $keys, $data);
27793
27794 if (isset($data['keywords']) && is_array($data['keywords'])) {
27795 sort($data['keywords']);
27796 }
27797
27798 if ($package->isAbandoned()) {
27799 $data['abandoned'] = $package->getReplacementPackage() ?: true;
27800 }
27801 }
27802
27803 if ($package instanceof RootPackageInterface) {
27804 $minimumStability = $package->getMinimumStability();
27805 if ($minimumStability) {
27806 $data['minimum-stability'] = $minimumStability;
27807 }
27808 }
27809
27810 if (count($package->getTransportOptions()) > 0) {
27811 $data['transport-options'] = $package->getTransportOptions();
27812 }
27813
27814 return $data;
27815 }
27816
27817 private function dumpValues(PackageInterface $package, array $keys, array $data)
27818 {
27819 foreach ($keys as $method => $key) {
27820 if (is_numeric($method)) {
27821 $method = $key;
27822 }
27823
27824 $getter = 'get'.ucfirst($method);
27825 $value = $package->$getter();
27826
27827 if (null !== $value && !(is_array($value) && 0 === count($value))) {
27828 $data[$key] = $value;
27829 }
27830 }
27831
27832 return $data;
27833 }
27834 }
27835 <?php
27836
27837
27838
27839
27840
27841
27842
27843
27844
27845
27846
27847 namespace Composer\Package;
27848
27849 use Composer\Semver\Constraint\ConstraintInterface;
27850
27851
27852
27853
27854
27855
27856 class Link
27857 {
27858
27859
27860
27861 protected $source;
27862
27863
27864
27865
27866 protected $target;
27867
27868
27869
27870
27871 protected $constraint;
27872
27873
27874
27875
27876 protected $description;
27877
27878
27879
27880
27881 protected $prettyConstraint;
27882
27883
27884
27885
27886
27887
27888
27889
27890
27891
27892 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
27893 {
27894 $this->source = strtolower($source);
27895 $this->target = strtolower($target);
27896 $this->constraint = $constraint;
27897 $this->description = $description;
27898 $this->prettyConstraint = $prettyConstraint;
27899 }
27900
27901
27902
27903
27904 public function getDescription()
27905 {
27906 return $this->description;
27907 }
27908
27909
27910
27911
27912 public function getSource()
27913 {
27914 return $this->source;
27915 }
27916
27917
27918
27919
27920 public function getTarget()
27921 {
27922 return $this->target;
27923 }
27924
27925
27926
27927
27928 public function getConstraint()
27929 {
27930 return $this->constraint;
27931 }
27932
27933
27934
27935
27936
27937 public function getPrettyConstraint()
27938 {
27939 if (null === $this->prettyConstraint) {
27940 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
27941 }
27942
27943 return $this->prettyConstraint;
27944 }
27945
27946
27947
27948
27949 public function __toString()
27950 {
27951 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
27952 }
27953
27954
27955
27956
27957
27958 public function getPrettyString(PackageInterface $sourcePackage)
27959 {
27960 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
27961 }
27962 }
27963 <?php
27964
27965
27966
27967
27968
27969
27970
27971
27972
27973
27974
27975 namespace Composer\Package\LinkConstraint;
27976
27977 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
27978
27979 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
27980
27981
27982
27983
27984 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
27985 {
27986 }
27987 <?php
27988
27989
27990
27991
27992
27993
27994
27995
27996
27997
27998
27999 namespace Composer\Package\LinkConstraint;
28000
28001 use Composer\Semver\Constraint\ConstraintInterface;
28002
28003 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
28004
28005
28006
28007
28008 interface LinkConstraintInterface extends ConstraintInterface
28009 {
28010 }
28011 <?php
28012
28013
28014
28015
28016
28017
28018
28019
28020
28021
28022
28023 namespace Composer\Package\LinkConstraint;
28024
28025 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
28026
28027 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
28028
28029
28030
28031
28032 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
28033 {
28034 }
28035 <?php
28036
28037
28038
28039
28040
28041
28042
28043
28044
28045
28046
28047 namespace Composer\Package\LinkConstraint;
28048
28049 use Composer\Semver\Constraint\AbstractConstraint;
28050
28051 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
28052
28053
28054
28055
28056 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
28057 {
28058 }
28059 <?php
28060
28061
28062
28063
28064
28065
28066
28067
28068
28069
28070
28071 namespace Composer\Package\LinkConstraint;
28072
28073 use Composer\Semver\Constraint\Constraint;
28074
28075 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
28076
28077
28078
28079
28080 class VersionConstraint extends Constraint implements LinkConstraintInterface
28081 {
28082 }
28083 <?php
28084
28085
28086
28087
28088
28089
28090
28091
28092
28093
28094
28095 namespace Composer\Package\Loader;
28096
28097 use Composer\Package;
28098 use Composer\Package\AliasPackage;
28099 use Composer\Package\Link;
28100 use Composer\Package\RootAliasPackage;
28101 use Composer\Package\RootPackageInterface;
28102 use Composer\Package\Version\VersionParser;
28103 use Composer\Semver\VersionParser as SemverVersionParser;
28104
28105
28106
28107
28108
28109 class ArrayLoader implements LoaderInterface
28110 {
28111 protected $versionParser;
28112 protected $loadOptions;
28113
28114 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
28115 {
28116 if (!$parser) {
28117 $parser = new VersionParser;
28118 }
28119 $this->versionParser = $parser;
28120 $this->loadOptions = $loadOptions;
28121 }
28122
28123 public function load(array $config, $class = 'Composer\Package\CompletePackage')
28124 {
28125 if (!isset($config['name'])) {
28126 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
28127 }
28128 if (!isset($config['version'])) {
28129 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
28130 }
28131
28132
28133  if (isset($config['version_normalized'])) {
28134 $version = $config['version_normalized'];
28135 } else {
28136 $version = $this->versionParser->normalize($config['version']);
28137 }
28138 $package = new $class($config['name'], $version, $config['version']);
28139 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
28140
28141 if (isset($config['target-dir'])) {
28142 $package->setTargetDir($config['target-dir']);
28143 }
28144
28145 if (isset($config['extra']) && is_array($config['extra'])) {
28146 $package->setExtra($config['extra']);
28147 }
28148
28149 if (isset($config['bin'])) {
28150 foreach ((array) $config['bin'] as $key => $bin) {
28151 $config['bin'][$key] = ltrim($bin, '/');
28152 }
28153 $package->setBinaries((array) $config['bin']);
28154 }
28155
28156 if (isset($config['installation-source'])) {
28157 $package->setInstallationSource($config['installation-source']);
28158 }
28159
28160 if (isset($config['source'])) {
28161 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
28162 throw new \UnexpectedValueException(sprintf(
28163 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
28164 $config['name'],
28165 json_encode($config['source'])
28166 ));
28167 }
28168 $package->setSourceType($config['source']['type']);
28169 $package->setSourceUrl($config['source']['url']);
28170 $package->setSourceReference(isset($config['source']['reference']) ? $config['source']['reference'] : null);
28171 if (isset($config['source']['mirrors'])) {
28172 $package->setSourceMirrors($config['source']['mirrors']);
28173 }
28174 }
28175
28176 if (isset($config['dist'])) {
28177 if (!isset($config['dist']['type'])
28178 || !isset($config['dist']['url'])) {
28179 throw new \UnexpectedValueException(sprintf(
28180 "Package %s's dist key should be specified as ".
28181 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
28182 $config['name'],
28183 json_encode($config['dist'])
28184 ));
28185 }
28186 $package->setDistType($config['dist']['type']);
28187 $package->setDistUrl($config['dist']['url']);
28188 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
28189 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
28190 if (isset($config['dist']['mirrors'])) {
28191 $package->setDistMirrors($config['dist']['mirrors']);
28192 }
28193 }
28194
28195 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
28196 if (isset($config[$type])) {
28197 $method = 'set'.ucfirst($opts['method']);
28198 $package->{$method}(
28199 $this->parseLinks(
28200 $package->getName(),
28201 $package->getPrettyVersion(),
28202 $opts['description'],
28203 $config[$type]
28204 )
28205 );
28206 }
28207 }
28208
28209 if (isset($config['suggest']) && is_array($config['suggest'])) {
28210 foreach ($config['suggest'] as $target => $reason) {
28211 if ('self.version' === trim($reason)) {
28212 $config['suggest'][$target] = $package->getPrettyVersion();
28213 }
28214 }
28215 $package->setSuggests($config['suggest']);
28216 }
28217
28218 if (isset($config['autoload'])) {
28219 $package->setAutoload($config['autoload']);
28220 }
28221
28222 if (isset($config['autoload-dev'])) {
28223 $package->setDevAutoload($config['autoload-dev']);
28224 }
28225
28226 if (isset($config['include-path'])) {
28227 $package->setIncludePaths($config['include-path']);
28228 }
28229
28230 if (!empty($config['time'])) {
28231 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
28232
28233 try {
28234 $date = new \DateTime($time, new \DateTimeZone('UTC'));
28235 $package->setReleaseDate($date);
28236 } catch (\Exception $e) {
28237 }
28238 }
28239
28240 if (!empty($config['notification-url'])) {
28241 $package->setNotificationUrl($config['notification-url']);
28242 }
28243
28244 if (!empty($config['archive']['exclude'])) {
28245 $package->setArchiveExcludes($config['archive']['exclude']);
28246 }
28247
28248 if ($package instanceof Package\CompletePackageInterface) {
28249 if (isset($config['scripts']) && is_array($config['scripts'])) {
28250 foreach ($config['scripts'] as $event => $listeners) {
28251 $config['scripts'][$event] = (array) $listeners;
28252 }
28253 if (isset($config['scripts']['composer'])) {
28254 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
28255 }
28256 $package->setScripts($config['scripts']);
28257 }
28258
28259 if (!empty($config['description']) && is_string($config['description'])) {
28260 $package->setDescription($config['description']);
28261 }
28262
28263 if (!empty($config['homepage']) && is_string($config['homepage'])) {
28264 $package->setHomepage($config['homepage']);
28265 }
28266
28267 if (!empty($config['keywords']) && is_array($config['keywords'])) {
28268 $package->setKeywords($config['keywords']);
28269 }
28270
28271 if (!empty($config['license'])) {
28272 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
28273 }
28274
28275 if (!empty($config['authors']) && is_array($config['authors'])) {
28276 $package->setAuthors($config['authors']);
28277 }
28278
28279 if (isset($config['support'])) {
28280 $package->setSupport($config['support']);
28281 }
28282
28283 if (isset($config['abandoned'])) {
28284 $package->setAbandoned($config['abandoned']);
28285 }
28286 }
28287
28288 if ($aliasNormalized = $this->getBranchAlias($config)) {
28289 if ($package instanceof RootPackageInterface) {
28290 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
28291 } else {
28292 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
28293 }
28294 }
28295
28296 if ($this->loadOptions && isset($config['transport-options'])) {
28297 $package->setTransportOptions($config['transport-options']);
28298 }
28299
28300 return $package;
28301 }
28302
28303
28304
28305
28306
28307
28308
28309
28310 public function parseLinks($source, $sourceVersion, $description, $links)
28311 {
28312 $res = array();
28313 foreach ($links as $target => $constraint) {
28314 if (!is_string($constraint)) {
28315 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
28316 }
28317 if ('self.version' === $constraint) {
28318 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
28319 } else {
28320 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
28321 }
28322
28323 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
28324 }
28325
28326 return $res;
28327 }
28328
28329
28330
28331
28332
28333
28334
28335 public function getBranchAlias(array $config)
28336 {
28337 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
28338 || !isset($config['extra']['branch-alias'])
28339 || !is_array($config['extra']['branch-alias'])
28340 ) {
28341 return;
28342 }
28343
28344 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
28345
28346  if ('-dev' !== substr($targetBranch, -4)) {
28347 continue;
28348 }
28349
28350
28351  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
28352 if ('-dev' !== substr($validatedTargetBranch, -4)) {
28353 continue;
28354 }
28355
28356
28357  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
28358 continue;
28359 }
28360
28361
28362  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
28363 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
28364 && (stripos($targetPrefix, $sourcePrefix) !== 0)
28365 ) {
28366 continue;
28367 }
28368
28369 return $validatedTargetBranch;
28370 }
28371 }
28372 }
28373 <?php
28374
28375
28376
28377
28378
28379
28380
28381
28382
28383
28384
28385 namespace Composer\Package\Loader;
28386
28387
28388
28389
28390 class InvalidPackageException extends \Exception
28391 {
28392 private $errors;
28393 private $warnings;
28394 private $data;
28395
28396 public function __construct(array $errors, array $warnings, array $data)
28397 {
28398 $this->errors = $errors;
28399 $this->warnings = $warnings;
28400 $this->data = $data;
28401 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
28402 }
28403
28404 public function getData()
28405 {
28406 return $this->data;
28407 }
28408
28409 public function getErrors()
28410 {
28411 return $this->errors;
28412 }
28413
28414 public function getWarnings()
28415 {
28416 return $this->warnings;
28417 }
28418 }
28419 <?php
28420
28421
28422
28423
28424
28425
28426
28427
28428
28429
28430
28431 namespace Composer\Package\Loader;
28432
28433 use Composer\Json\JsonFile;
28434
28435
28436
28437
28438 class JsonLoader
28439 {
28440 private $loader;
28441
28442 public function __construct(LoaderInterface $loader)
28443 {
28444 $this->loader = $loader;
28445 }
28446
28447
28448
28449
28450
28451 public function load($json)
28452 {
28453 if ($json instanceof JsonFile) {
28454 $config = $json->read();
28455 } elseif (file_exists($json)) {
28456 $config = JsonFile::parseJson(file_get_contents($json), $json);
28457 } elseif (is_string($json)) {
28458 $config = JsonFile::parseJson($json);
28459 }
28460
28461 return $this->loader->load($config);
28462 }
28463 }
28464 <?php
28465
28466
28467
28468
28469
28470
28471
28472
28473
28474
28475
28476 namespace Composer\Package\Loader;
28477
28478
28479
28480
28481
28482
28483 interface LoaderInterface
28484 {
28485
28486
28487
28488
28489
28490
28491
28492 public function load(array $package, $class = 'Composer\Package\CompletePackage');
28493 }
28494 <?php
28495
28496
28497
28498
28499
28500
28501
28502
28503
28504
28505
28506 namespace Composer\Package\Loader;
28507
28508 use Composer\Package\BasePackage;
28509 use Composer\Package\AliasPackage;
28510 use Composer\Config;
28511 use Composer\IO\IOInterface;
28512 use Composer\Package\RootPackageInterface;
28513 use Composer\Repository\RepositoryFactory;
28514 use Composer\Package\Version\VersionGuesser;
28515 use Composer\Package\Version\VersionParser;
28516 use Composer\Repository\RepositoryManager;
28517 use Composer\Util\ProcessExecutor;
28518
28519
28520
28521
28522
28523
28524
28525
28526 class RootPackageLoader extends ArrayLoader
28527 {
28528
28529
28530
28531 private $manager;
28532
28533
28534
28535
28536 private $config;
28537
28538
28539
28540
28541 private $versionGuesser;
28542
28543
28544
28545
28546 private $io;
28547
28548 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null, IOInterface $io = null)
28549 {
28550 parent::__construct($parser);
28551
28552 $this->manager = $manager;
28553 $this->config = $config;
28554 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
28555 $this->io = $io;
28556 }
28557
28558
28559
28560
28561
28562
28563
28564 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
28565 {
28566 if (!isset($config['name'])) {
28567 $config['name'] = '__root__';
28568 } elseif ($this->io) {
28569 if ($err = ValidatingArrayLoader::hasPackageNamingError($config['name'])) {
28570 $this->io->writeError('<warning>Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
28571 }
28572 }
28573 $autoVersioned = false;
28574 if (!isset($config['version'])) {
28575 $commit = null;
28576
28577
28578  if (getenv('COMPOSER_ROOT_VERSION')) {
28579 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
28580 } else {
28581 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
28582 if ($versionData) {
28583 $config['version'] = $versionData['pretty_version'];
28584 $config['version_normalized'] = $versionData['version'];
28585 $commit = $versionData['commit'];
28586 }
28587 }
28588
28589 if (!isset($config['version'])) {
28590 $config['version'] = '1.0.0';
28591 $autoVersioned = true;
28592 }
28593
28594 if ($commit) {
28595 $config['source'] = array(
28596 'type' => '',
28597 'url' => '',
28598 'reference' => $commit,
28599 );
28600 $config['dist'] = array(
28601 'type' => '',
28602 'url' => '',
28603 'reference' => $commit,
28604 );
28605 }
28606 }
28607
28608 $realPackage = $package = parent::load($config, $class);
28609 if ($realPackage instanceof AliasPackage) {
28610 $realPackage = $package->getAliasOf();
28611 }
28612
28613 if ($autoVersioned) {
28614 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
28615 }
28616
28617 if (isset($config['minimum-stability'])) {
28618 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
28619 }
28620
28621 $aliases = array();
28622 $stabilityFlags = array();
28623 $references = array();
28624 foreach (array('require', 'require-dev') as $linkType) {
28625 if (isset($config[$linkType])) {
28626 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
28627 $method = 'get'.ucfirst($linkInfo['method']);
28628 $links = array();
28629 foreach ($realPackage->$method() as $link) {
28630 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
28631 }
28632 $aliases = $this->extractAliases($links, $aliases);
28633 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
28634 $references = $this->extractReferences($links, $references);
28635 }
28636 }
28637
28638 if ($this->io) {
28639 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
28640 if (isset($config[$linkType])) {
28641 foreach ($config[$linkType] as $linkName => $constraint) {
28642 if ($err = ValidatingArrayLoader::hasPackageNamingError($linkName, true)) {
28643 $this->io->writeError('<warning>Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
28644 }
28645 }
28646 }
28647 }
28648 }
28649
28650 if (isset($links[$config['name']])) {
28651 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
28652 'Did you accidentally name your root package after an external package?', $config['name']));
28653 }
28654
28655 $realPackage->setAliases($aliases);
28656 $realPackage->setStabilityFlags($stabilityFlags);
28657 $realPackage->setReferences($references);
28658
28659 if (isset($config['prefer-stable'])) {
28660 $realPackage->setPreferStable((bool) $config['prefer-stable']);
28661 }
28662
28663 if (isset($config['config'])) {
28664 $realPackage->setConfig($config['config']);
28665 }
28666
28667 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
28668 foreach ($repos as $repo) {
28669 $this->manager->addRepository($repo);
28670 }
28671 $realPackage->setRepositories($this->config->getRepositories());
28672
28673 return $package;
28674 }
28675
28676 private function extractAliases(array $requires, array $aliases)
28677 {
28678 foreach ($requires as $reqName => $reqVersion) {
28679 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
28680 $aliases[] = array(
28681 'package' => strtolower($reqName),
28682 'version' => $this->versionParser->normalize($match[1], $reqVersion),
28683 'alias' => $match[2],
28684 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
28685 );
28686 }
28687 }
28688
28689 return $aliases;
28690 }
28691
28692 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
28693 {
28694 $stabilities = BasePackage::$stabilities;
28695 $minimumStability = $stabilities[$minimumStability];
28696 foreach ($requires as $reqName => $reqVersion) {
28697 $constraints = array();
28698
28699
28700  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
28701 foreach ($orSplit as $orConstraint) {
28702 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
28703 foreach ($andSplit as $andConstraint) {
28704 $constraints[] = $andConstraint;
28705 }
28706 }
28707
28708
28709  $match = false;
28710 foreach ($constraints as $constraint) {
28711 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
28712 $name = strtolower($reqName);
28713 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
28714
28715 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
28716 continue;
28717 }
28718 $stabilityFlags[$name] = $stability;
28719 $match = true;
28720 }
28721 }
28722
28723 if ($match) {
28724 continue;
28725 }
28726
28727 foreach ($constraints as $constraint) {
28728
28729  
28730  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
28731 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
28732 $name = strtolower($reqName);
28733 $stability = $stabilities[$stabilityName];
28734 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
28735 continue;
28736 }
28737 $stabilityFlags[$name] = $stability;
28738 }
28739 }
28740 }
28741
28742 return $stabilityFlags;
28743 }
28744
28745 private function extractReferences(array $requires, array $references)
28746 {
28747 foreach ($requires as $reqName => $reqVersion) {
28748 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
28749 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) {
28750 $name = strtolower($reqName);
28751 $references[$name] = $match[1];
28752 }
28753 }
28754
28755 return $references;
28756 }
28757 }
28758 <?php
28759
28760
28761
28762
28763
28764
28765
28766
28767
28768
28769
28770 namespace Composer\Package\Loader;
28771
28772 use Composer\Package\BasePackage;
28773 use Composer\Semver\Constraint\Constraint;
28774 use Composer\Package\Version\VersionParser;
28775 use Composer\Repository\PlatformRepository;
28776 use Composer\Spdx\SpdxLicenses;
28777
28778
28779
28780
28781 class ValidatingArrayLoader implements LoaderInterface
28782 {
28783 const CHECK_ALL = 3;
28784 const CHECK_UNBOUND_CONSTRAINTS = 1;
28785 const CHECK_STRICT_CONSTRAINTS = 2;
28786
28787 private $loader;
28788 private $versionParser;
28789 private $errors;
28790 private $warnings;
28791 private $config;
28792 private $strictName;
28793 private $flags;
28794
28795 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
28796 {
28797 $this->loader = $loader;
28798 $this->versionParser = $parser ?: new VersionParser();
28799 $this->strictName = $strictName;
28800 $this->flags = $flags;
28801 }
28802
28803 public function load(array $config, $class = 'Composer\Package\CompletePackage')
28804 {
28805 $this->errors = array();
28806 $this->warnings = array();
28807 $this->config = $config;
28808
28809 if ($err = self::hasPackageNamingError($config['name'])) {
28810 $this->warnings[] = 'Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.';
28811 }
28812
28813 if ($this->strictName) {
28814 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
28815 } else {
28816 $this->validateString('name', true);
28817 }
28818
28819 if (!empty($this->config['version'])) {
28820 try {
28821 $this->versionParser->normalize($this->config['version']);
28822 } catch (\Exception $e) {
28823 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
28824 unset($this->config['version']);
28825 }
28826 }
28827
28828 if (!empty($this->config['config']['platform'])) {
28829 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
28830 try {
28831 $this->versionParser->normalize($platform);
28832 } catch (\Exception $e) {
28833 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
28834 }
28835 }
28836 }
28837
28838 $this->validateRegex('type', '[A-Za-z0-9-]+');
28839 $this->validateString('target-dir');
28840 $this->validateArray('extra');
28841
28842 if (isset($this->config['bin'])) {
28843 if (is_string($this->config['bin'])) {
28844 $this->validateString('bin');
28845 } else {
28846 $this->validateFlatArray('bin');
28847 }
28848 }
28849
28850 $this->validateArray('scripts'); 
28851  $this->validateString('description');
28852 $this->validateUrl('homepage');
28853 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
28854
28855 $releaseDate = null;
28856 $this->validateString('time');
28857 if (!empty($this->config['time'])) {
28858 try {
28859 $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
28860 } catch (\Exception $e) {
28861 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
28862 unset($this->config['time']);
28863 }
28864 }
28865
28866
28867  if (isset($this->config['license']) && (!$releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days'))) {
28868 if (is_array($this->config['license']) || is_string($this->config['license'])) {
28869 $licenses = (array) $this->config['license'];
28870
28871
28872  foreach ($licenses as $key => $license) {
28873 if ('proprietary' === $license) {
28874 unset($licenses[$key]);
28875 }
28876 }
28877
28878 $licenseValidator = new SpdxLicenses();
28879 if (count($licenses) === 1 && !$licenseValidator->validate($licenses) && $licenseValidator->validate(trim($licenses[0]))) {
28880 $this->warnings[] = sprintf(
28881 'License %s must not contain extra spaces, make sure to trim it.',
28882 json_encode($this->config['license'])
28883 );
28884 } elseif (array() !== $licenses && !$licenseValidator->validate($licenses)) {
28885 $this->warnings[] = sprintf(
28886 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
28887 'If the software is closed-source, you may use "proprietary" as license.',
28888 json_encode($this->config['license'])
28889 );
28890 }
28891 }
28892 }
28893
28894 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
28895 foreach ($this->config['authors'] as $key => $author) {
28896 if (!is_array($author)) {
28897 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
28898 unset($this->config['authors'][$key]);
28899 continue;
28900 }
28901 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
28902 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
28903 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
28904 unset($this->config['authors'][$key][$authorData]);
28905 }
28906 }
28907 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
28908 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
28909 unset($this->config['authors'][$key]['homepage']);
28910 }
28911 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
28912 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
28913 unset($this->config['authors'][$key]['email']);
28914 }
28915 if (empty($this->config['authors'][$key])) {
28916 unset($this->config['authors'][$key]);
28917 }
28918 }
28919 if (empty($this->config['authors'])) {
28920 unset($this->config['authors']);
28921 }
28922 }
28923
28924 if ($this->validateArray('support') && !empty($this->config['support'])) {
28925 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss', 'chat') as $key) {
28926 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
28927 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
28928 unset($this->config['support'][$key]);
28929 }
28930 }
28931
28932 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
28933 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
28934 unset($this->config['support']['email']);
28935 }
28936
28937 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
28938 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
28939 unset($this->config['support']['irc']);
28940 }
28941
28942 foreach (array('issues', 'forum', 'wiki', 'source', 'docs', 'chat') as $key) {
28943 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
28944 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
28945 unset($this->config['support'][$key]);
28946 }
28947 }
28948 if (empty($this->config['support'])) {
28949 unset($this->config['support']);
28950 }
28951 }
28952
28953 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
28954 $stableConstraint = new Constraint('=', '1.0.0');
28955
28956 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
28957 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
28958 foreach ($this->config[$linkType] as $package => $constraint) {
28959 if ($err = self::hasPackageNamingError($package, true)) {
28960 $this->warnings[] = 'Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.';
28961 } elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
28962 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
28963 }
28964 if (!is_string($constraint)) {
28965 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
28966 unset($this->config[$linkType][$package]);
28967 } elseif ('self.version' !== $constraint) {
28968 try {
28969 $linkConstraint = $this->versionParser->parseConstraints($constraint);
28970 } catch (\Exception $e) {
28971 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
28972 unset($this->config[$linkType][$package]);
28973 continue;
28974 }
28975
28976
28977  if (
28978 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
28979 && 'require' === $linkType
28980 && $linkConstraint->matches($unboundConstraint)
28981 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
28982 ) {
28983 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
28984 } elseif (
28985
28986  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
28987 && 'require' === $linkType
28988 && substr($linkConstraint, 0, 1) === '='
28989 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
28990 ) {
28991 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
28992 }
28993 }
28994 }
28995 }
28996 }
28997
28998 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
28999 foreach ($this->config['suggest'] as $package => $description) {
29000 if (!is_string($description)) {
29001 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
29002 unset($this->config['suggest'][$package]);
29003 }
29004 }
29005 }
29006
29007 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
29008 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
29009 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
29010 unset($this->config['minimum-stability']);
29011 }
29012 }
29013
29014 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
29015 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
29016 foreach ($this->config['autoload'] as $type => $typeConfig) {
29017 if (!in_array($type, $types)) {
29018 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
29019 unset($this->config['autoload'][$type]);
29020 }
29021 if ($type === 'psr-4') {
29022 foreach ($typeConfig as $namespace => $dirs) {
29023 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
29024 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
29025 }
29026 }
29027 }
29028 }
29029 }
29030
29031 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
29032 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
29033
29034  
29035  unset($this->config['autoload']['psr-4']);
29036 }
29037
29038
29039  
29040
29041
29042  
29043
29044 $this->validateFlatArray('include-path');
29045 $this->validateArray('transport-options');
29046
29047
29048  if (isset($this->config['extra']['branch-alias'])) {
29049 if (!is_array($this->config['extra']['branch-alias'])) {
29050 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
29051 } else {
29052 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
29053
29054  if ('-dev' !== substr($targetBranch, -4)) {
29055 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
29056 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29057
29058 continue;
29059 }
29060
29061
29062  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
29063 if ('-dev' !== substr($validatedTargetBranch, -4)) {
29064 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
29065 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29066
29067 continue;
29068 }
29069
29070
29071  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
29072 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
29073 && (stripos($targetPrefix, $sourcePrefix) !== 0)
29074 ) {
29075 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
29076 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29077 }
29078 }
29079 }
29080 }
29081
29082 if ($this->errors) {
29083 throw new InvalidPackageException($this->errors, $this->warnings, $config);
29084 }
29085
29086 $package = $this->loader->load($this->config, $class);
29087 $this->config = null;
29088
29089 return $package;
29090 }
29091
29092 public function getWarnings()
29093 {
29094 return $this->warnings;
29095 }
29096
29097 public function getErrors()
29098 {
29099 return $this->errors;
29100 }
29101
29102 public static function hasPackageNamingError($name, $isLink = false)
29103 {
29104 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
29105 return;
29106 }
29107
29108 if (!preg_match('{^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9]([_.-]?[a-z0-9]+)*$}iD', $name)) {
29109 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]([_.-]?[a-z0-9]+)*".';
29110 }
29111
29112 $reservedNames = array('nul', 'con', 'prn', 'aux', 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9', 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9');
29113 $bits = explode('/', strtolower($name));
29114 if (in_array($bits[0], $reservedNames, true) || in_array($bits[1], $reservedNames, true)) {
29115 return $name.' is reserved, package and vendor names can not match any of: '.implode(', ', $reservedNames).'.';
29116 }
29117
29118 if (preg_match('{\.json$}', $name)) {
29119 return $name.' is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.';
29120 }
29121
29122 if (preg_match('{[A-Z]}', $name)) {
29123 if ($isLink) {
29124 return $name.' is invalid, it should not contain uppercase characters. Please use '.strtolower($name).' instead.';
29125 }
29126
29127 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
29128 $suggestName = strtolower($suggestName);
29129
29130 return $name.' is invalid, it should not contain uppercase characters. We suggest using '.$suggestName.' instead.';
29131 }
29132 }
29133
29134 private function validateRegex($property, $regex, $mandatory = false)
29135 {
29136 if (!$this->validateString($property, $mandatory)) {
29137 return false;
29138 }
29139
29140 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
29141 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
29142 if ($mandatory) {
29143 $this->errors[] = $message;
29144 } else {
29145 $this->warnings[] = $message;
29146 }
29147 unset($this->config[$property]);
29148
29149 return false;
29150 }
29151
29152 return true;
29153 }
29154
29155 private function validateString($property, $mandatory = false)
29156 {
29157 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
29158 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
29159 unset($this->config[$property]);
29160
29161 return false;
29162 }
29163
29164 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
29165 if ($mandatory) {
29166 $this->errors[] = $property.' : must be present';
29167 }
29168 unset($this->config[$property]);
29169
29170 return false;
29171 }
29172
29173 return true;
29174 }
29175
29176 private function validateArray($property, $mandatory = false)
29177 {
29178 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
29179 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
29180 unset($this->config[$property]);
29181
29182 return false;
29183 }
29184
29185 if (!isset($this->config[$property]) || !count($this->config[$property])) {
29186 if ($mandatory) {
29187 $this->errors[] = $property.' : must be present and contain at least one element';
29188 }
29189 unset($this->config[$property]);
29190
29191 return false;
29192 }
29193
29194 return true;
29195 }
29196
29197 private function validateFlatArray($property, $regex = null, $mandatory = false)
29198 {
29199 if (!$this->validateArray($property, $mandatory)) {
29200 return false;
29201 }
29202
29203 $pass = true;
29204 foreach ($this->config[$property] as $key => $value) {
29205 if (!is_string($value) && !is_numeric($value)) {
29206 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
29207 unset($this->config[$property][$key]);
29208 $pass = false;
29209
29210 continue;
29211 }
29212
29213 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
29214 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
29215 unset($this->config[$property][$key]);
29216 $pass = false;
29217 }
29218 }
29219
29220 return $pass;
29221 }
29222
29223 private function validateUrl($property, $mandatory = false)
29224 {
29225 if (!$this->validateString($property, $mandatory)) {
29226 return false;
29227 }
29228
29229 if (!$this->filterUrl($this->config[$property])) {
29230 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
29231 unset($this->config[$property]);
29232
29233 return false;
29234 }
29235
29236 return true;
29237 }
29238
29239 private function filterUrl($value, array $schemes = array('http', 'https'))
29240 {
29241 if ($value === '') {
29242 return true;
29243 }
29244
29245 $bits = parse_url($value);
29246 if (empty($bits['scheme']) || empty($bits['host'])) {
29247 return false;
29248 }
29249
29250 if (!in_array($bits['scheme'], $schemes, true)) {
29251 return false;
29252 }
29253
29254 return true;
29255 }
29256 }
29257 <?php
29258
29259
29260
29261
29262
29263
29264
29265
29266
29267
29268
29269 namespace Composer\Package;
29270
29271 use Composer\Json\JsonFile;
29272 use Composer\Installer\InstallationManager;
29273 use Composer\Repository\RepositoryManager;
29274 use Composer\Util\ProcessExecutor;
29275 use Composer\Repository\ArrayRepository;
29276 use Composer\Package\Dumper\ArrayDumper;
29277 use Composer\Package\Loader\ArrayLoader;
29278 use Composer\Util\Git as GitUtil;
29279 use Composer\IO\IOInterface;
29280 use Seld\JsonLint\ParsingException;
29281
29282
29283
29284
29285
29286
29287
29288 class Locker
29289 {
29290 private $lockFile;
29291 private $repositoryManager;
29292 private $installationManager;
29293 private $hash;
29294 private $contentHash;
29295 private $loader;
29296 private $dumper;
29297 private $process;
29298 private $lockDataCache;
29299
29300
29301
29302
29303
29304
29305
29306
29307
29308
29309 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
29310 {
29311 $this->lockFile = $lockFile;
29312 $this->repositoryManager = $repositoryManager;
29313 $this->installationManager = $installationManager;
29314 $this->hash = md5($composerFileContents);
29315 $this->contentHash = self::getContentHash($composerFileContents);
29316 $this->loader = new ArrayLoader(null, true);
29317 $this->dumper = new ArrayDumper();
29318 $this->process = new ProcessExecutor($io);
29319 }
29320
29321
29322
29323
29324
29325
29326
29327
29328 public static function getContentHash($composerFileContents)
29329 {
29330 $content = json_decode($composerFileContents, true);
29331
29332 $relevantKeys = array(
29333 'name',
29334 'version',
29335 'require',
29336 'require-dev',
29337 'conflict',
29338 'replace',
29339 'provide',
29340 'minimum-stability',
29341 'prefer-stable',
29342 'repositories',
29343 'extra',
29344 );
29345
29346 $relevantContent = array();
29347
29348 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
29349 $relevantContent[$key] = $content[$key];
29350 }
29351 if (isset($content['config']['platform'])) {
29352 $relevantContent['config']['platform'] = $content['config']['platform'];
29353 }
29354
29355 ksort($relevantContent);
29356
29357 return md5(json_encode($relevantContent));
29358 }
29359
29360
29361
29362
29363
29364
29365 public function isLocked()
29366 {
29367 if (!$this->lockFile->exists()) {
29368 return false;
29369 }
29370
29371 $data = $this->getLockData();
29372
29373 return isset($data['packages']);
29374 }
29375
29376
29377
29378
29379
29380
29381 public function isFresh()
29382 {
29383 $lock = $this->lockFile->read();
29384
29385 if (!empty($lock['content-hash'])) {
29386
29387  return $this->contentHash === $lock['content-hash'];
29388 }
29389
29390
29391  if (!empty($lock['hash'])) {
29392 return $this->hash === $lock['hash'];
29393 }
29394
29395
29396  return false;
29397 }
29398
29399
29400
29401
29402
29403
29404
29405
29406 public function getLockedRepository($withDevReqs = false)
29407 {
29408 $lockData = $this->getLockData();
29409 $packages = new ArrayRepository();
29410
29411 $lockedPackages = $lockData['packages'];
29412 if ($withDevReqs) {
29413 if (isset($lockData['packages-dev'])) {
29414 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
29415 } else {
29416 throw new \RuntimeException('The lock file does not contain require-dev information, run install with the --no-dev option or run update to install those packages.');
29417 }
29418 }
29419
29420 if (empty($lockedPackages)) {
29421 return $packages;
29422 }
29423
29424 if (isset($lockedPackages[0]['name'])) {
29425 foreach ($lockedPackages as $info) {
29426 $packages->addPackage($this->loader->load($info));
29427 }
29428
29429 return $packages;
29430 }
29431
29432 throw new \RuntimeException('Your composer.lock was created before 2012-09-15, and is not supported anymore. Run "composer update" to generate a new one.');
29433 }
29434
29435
29436
29437
29438
29439
29440
29441 public function getPlatformRequirements($withDevReqs = false)
29442 {
29443 $lockData = $this->getLockData();
29444 $requirements = array();
29445
29446 if (!empty($lockData['platform'])) {
29447 $requirements = $this->loader->parseLinks(
29448 '__ROOT__',
29449 '1.0.0',
29450 'requires',
29451 isset($lockData['platform']) ? $lockData['platform'] : array()
29452 );
29453 }
29454
29455 if ($withDevReqs && !empty($lockData['platform-dev'])) {
29456 $devRequirements = $this->loader->parseLinks(
29457 '__ROOT__',
29458 '1.0.0',
29459 'requires',
29460 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
29461 );
29462
29463 $requirements = array_merge($requirements, $devRequirements);
29464 }
29465
29466 return $requirements;
29467 }
29468
29469 public function getMinimumStability()
29470 {
29471 $lockData = $this->getLockData();
29472
29473 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
29474 }
29475
29476 public function getStabilityFlags()
29477 {
29478 $lockData = $this->getLockData();
29479
29480 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
29481 }
29482
29483 public function getPreferStable()
29484 {
29485 $lockData = $this->getLockData();
29486
29487
29488  
29489  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
29490 }
29491
29492 public function getPreferLowest()
29493 {
29494 $lockData = $this->getLockData();
29495
29496
29497  
29498  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
29499 }
29500
29501 public function getPlatformOverrides()
29502 {
29503 $lockData = $this->getLockData();
29504
29505 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
29506 }
29507
29508 public function getAliases()
29509 {
29510 $lockData = $this->getLockData();
29511
29512 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
29513 }
29514
29515 public function getLockData()
29516 {
29517 if (null !== $this->lockDataCache) {
29518 return $this->lockDataCache;
29519 }
29520
29521 if (!$this->lockFile->exists()) {
29522 throw new \LogicException('No lockfile found. Unable to read locked packages');
29523 }
29524
29525 return $this->lockDataCache = $this->lockFile->read();
29526 }
29527
29528
29529
29530
29531
29532
29533
29534
29535
29536
29537
29538
29539
29540
29541
29542
29543
29544 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
29545 {
29546 $lock = array(
29547 '_readme' => array('This file locks the dependencies of your project to a known state',
29548 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies',
29549 'This file is @gener'.'ated automatically', ),
29550 'content-hash' => $this->contentHash,
29551 'packages' => null,
29552 'packages-dev' => null,
29553 'aliases' => array(),
29554 'minimum-stability' => $minimumStability,
29555 'stability-flags' => $stabilityFlags,
29556 'prefer-stable' => $preferStable,
29557 'prefer-lowest' => $preferLowest,
29558 );
29559
29560 foreach ($aliases as $package => $versions) {
29561 foreach ($versions as $version => $alias) {
29562 $lock['aliases'][] = array(
29563 'alias' => $alias['alias'],
29564 'alias_normalized' => $alias['alias_normalized'],
29565 'version' => $version,
29566 'package' => $package,
29567 );
29568 }
29569 }
29570
29571 $lock['packages'] = $this->lockPackages($packages);
29572 if (null !== $devPackages) {
29573 $lock['packages-dev'] = $this->lockPackages($devPackages);
29574 }
29575
29576 $lock['platform'] = $platformReqs;
29577 $lock['platform-dev'] = $platformDevReqs;
29578 if ($platformOverrides) {
29579 $lock['platform-overrides'] = $platformOverrides;
29580 }
29581
29582 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
29583 if ($this->lockFile->exists()) {
29584 unlink($this->lockFile->getPath());
29585 }
29586
29587 return false;
29588 }
29589
29590 try {
29591 $isLocked = $this->isLocked();
29592 } catch (ParsingException $e) {
29593 $isLocked = false;
29594 }
29595 if (!$isLocked || $lock !== $this->getLockData()) {
29596 $this->lockFile->write($lock);
29597 $this->lockDataCache = null;
29598
29599 return true;
29600 }
29601
29602 return false;
29603 }
29604
29605 private function lockPackages(array $packages)
29606 {
29607 $locked = array();
29608
29609 foreach ($packages as $package) {
29610 if ($package instanceof AliasPackage) {
29611 continue;
29612 }
29613
29614 $name = $package->getPrettyName();
29615 $version = $package->getPrettyVersion();
29616
29617 if (!$name || !$version) {
29618 throw new \LogicException(sprintf(
29619 'Package "%s" has no version or name and can not be locked',
29620 $package
29621 ));
29622 }
29623
29624 $spec = $this->dumper->dump($package);
29625 unset($spec['version_normalized']);
29626
29627
29628  $time = isset($spec['time']) ? $spec['time'] : null;
29629 unset($spec['time']);
29630 if ($package->isDev() && $package->getInstallationSource() === 'source') {
29631
29632  $time = $this->getPackageTime($package) ?: $time;
29633 }
29634 if (null !== $time) {
29635 $spec['time'] = $time;
29636 }
29637
29638 unset($spec['installation-source']);
29639
29640 $locked[] = $spec;
29641 }
29642
29643 usort($locked, function ($a, $b) {
29644 $comparison = strcmp($a['name'], $b['name']);
29645
29646 if (0 !== $comparison) {
29647 return $comparison;
29648 }
29649
29650
29651  return strcmp($a['version'], $b['version']);
29652 });
29653
29654 return $locked;
29655 }
29656
29657
29658
29659
29660
29661
29662
29663 private function getPackageTime(PackageInterface $package)
29664 {
29665 if (!function_exists('proc_open')) {
29666 return null;
29667 }
29668
29669 $path = realpath($this->installationManager->getInstallPath($package));
29670 $sourceType = $package->getSourceType();
29671 $datetime = null;
29672
29673 if ($path && in_array($sourceType, array('git', 'hg'))) {
29674 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
29675 switch ($sourceType) {
29676 case 'git':
29677 GitUtil::cleanEnv();
29678
29679 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
29680 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
29681 }
29682 break;
29683
29684 case 'hg':
29685 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
29686 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
29687 }
29688 break;
29689 }
29690 }
29691
29692 return $datetime ? $datetime->format(DATE_RFC3339) : null;
29693 }
29694 }
29695 <?php
29696
29697
29698
29699
29700
29701
29702
29703
29704
29705
29706
29707 namespace Composer\Package;
29708
29709 use Composer\Package\Version\VersionParser;
29710 use Composer\Util\ComposerMirror;
29711
29712
29713
29714
29715
29716
29717 class Package extends BasePackage
29718 {
29719 protected $type;
29720 protected $targetDir;
29721 protected $installationSource;
29722 protected $sourceType;
29723 protected $sourceUrl;
29724 protected $sourceReference;
29725 protected $sourceMirrors;
29726 protected $distType;
29727 protected $distUrl;
29728 protected $distReference;
29729 protected $distSha1Checksum;
29730 protected $distMirrors;
29731 protected $version;
29732 protected $prettyVersion;
29733 protected $releaseDate;
29734 protected $extra = array();
29735 protected $binaries = array();
29736 protected $dev;
29737 protected $stability;
29738 protected $notificationUrl;
29739
29740
29741 protected $requires = array();
29742
29743 protected $conflicts = array();
29744
29745 protected $provides = array();
29746
29747 protected $replaces = array();
29748
29749 protected $devRequires = array();
29750 protected $suggests = array();
29751 protected $autoload = array();
29752 protected $devAutoload = array();
29753 protected $includePaths = array();
29754 protected $archiveExcludes = array();
29755
29756
29757
29758
29759
29760
29761
29762
29763 public function __construct($name, $version, $prettyVersion)
29764 {
29765 parent::__construct($name);
29766
29767 $this->version = $version;
29768 $this->prettyVersion = $prettyVersion;
29769
29770 $this->stability = VersionParser::parseStability($version);
29771 $this->dev = $this->stability === 'dev';
29772 }
29773
29774
29775
29776
29777 public function isDev()
29778 {
29779 return $this->dev;
29780 }
29781
29782
29783
29784
29785 public function setType($type)
29786 {
29787 $this->type = $type;
29788 }
29789
29790
29791
29792
29793 public function getType()
29794 {
29795 return $this->type ?: 'library';
29796 }
29797
29798
29799
29800
29801 public function getStability()
29802 {
29803 return $this->stability;
29804 }
29805
29806
29807
29808
29809 public function setTargetDir($targetDir)
29810 {
29811 $this->targetDir = $targetDir;
29812 }
29813
29814
29815
29816
29817 public function getTargetDir()
29818 {
29819 if (null === $this->targetDir) {
29820 return;
29821 }
29822
29823 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
29824 }
29825
29826
29827
29828
29829 public function setExtra(array $extra)
29830 {
29831 $this->extra = $extra;
29832 }
29833
29834
29835
29836
29837 public function getExtra()
29838 {
29839 return $this->extra;
29840 }
29841
29842
29843
29844
29845 public function setBinaries(array $binaries)
29846 {
29847 $this->binaries = $binaries;
29848 }
29849
29850
29851
29852
29853 public function getBinaries()
29854 {
29855 return $this->binaries;
29856 }
29857
29858
29859
29860
29861 public function setInstallationSource($type)
29862 {
29863 $this->installationSource = $type;
29864 }
29865
29866
29867
29868
29869 public function getInstallationSource()
29870 {
29871 return $this->installationSource;
29872 }
29873
29874
29875
29876
29877 public function setSourceType($type)
29878 {
29879 $this->sourceType = $type;
29880 }
29881
29882
29883
29884
29885 public function getSourceType()
29886 {
29887 return $this->sourceType;
29888 }
29889
29890
29891
29892
29893 public function setSourceUrl($url)
29894 {
29895 $this->sourceUrl = $url;
29896 }
29897
29898
29899
29900
29901 public function getSourceUrl()
29902 {
29903 return $this->sourceUrl;
29904 }
29905
29906
29907
29908
29909 public function setSourceReference($reference)
29910 {
29911 $this->sourceReference = $reference;
29912 }
29913
29914
29915
29916
29917 public function getSourceReference()
29918 {
29919 return $this->sourceReference;
29920 }
29921
29922
29923
29924
29925 public function setSourceMirrors($mirrors)
29926 {
29927 $this->sourceMirrors = $mirrors;
29928 }
29929
29930
29931
29932
29933 public function getSourceMirrors()
29934 {
29935 return $this->sourceMirrors;
29936 }
29937
29938
29939
29940
29941 public function getSourceUrls()
29942 {
29943 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
29944 }
29945
29946
29947
29948
29949 public function setDistType($type)
29950 {
29951 $this->distType = $type;
29952 }
29953
29954
29955
29956
29957 public function getDistType()
29958 {
29959 return $this->distType;
29960 }
29961
29962
29963
29964
29965 public function setDistUrl($url)
29966 {
29967 $this->distUrl = $url;
29968 }
29969
29970
29971
29972
29973 public function getDistUrl()
29974 {
29975 return $this->distUrl;
29976 }
29977
29978
29979
29980
29981 public function setDistReference($reference)
29982 {
29983 $this->distReference = $reference;
29984 }
29985
29986
29987
29988
29989 public function getDistReference()
29990 {
29991 return $this->distReference;
29992 }
29993
29994
29995
29996
29997 public function setDistSha1Checksum($sha1checksum)
29998 {
29999 $this->distSha1Checksum = $sha1checksum;
30000 }
30001
30002
30003
30004
30005 public function getDistSha1Checksum()
30006 {
30007 return $this->distSha1Checksum;
30008 }
30009
30010
30011
30012
30013 public function setDistMirrors($mirrors)
30014 {
30015 $this->distMirrors = $mirrors;
30016 }
30017
30018
30019
30020
30021 public function getDistMirrors()
30022 {
30023 return $this->distMirrors;
30024 }
30025
30026
30027
30028
30029 public function getDistUrls()
30030 {
30031 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
30032 }
30033
30034
30035
30036
30037 public function getVersion()
30038 {
30039 return $this->version;
30040 }
30041
30042
30043
30044
30045 public function getPrettyVersion()
30046 {
30047 return $this->prettyVersion;
30048 }
30049
30050
30051
30052
30053
30054
30055 public function setReleaseDate(\DateTime $releaseDate)
30056 {
30057 $this->releaseDate = $releaseDate;
30058 }
30059
30060
30061
30062
30063 public function getReleaseDate()
30064 {
30065 return $this->releaseDate;
30066 }
30067
30068
30069
30070
30071
30072
30073 public function setRequires(array $requires)
30074 {
30075 $this->requires = $requires;
30076 }
30077
30078
30079
30080
30081 public function getRequires()
30082 {
30083 return $this->requires;
30084 }
30085
30086
30087
30088
30089
30090
30091 public function setConflicts(array $conflicts)
30092 {
30093 $this->conflicts = $conflicts;
30094 }
30095
30096
30097
30098
30099 public function getConflicts()
30100 {
30101 return $this->conflicts;
30102 }
30103
30104
30105
30106
30107
30108
30109 public function setProvides(array $provides)
30110 {
30111 $this->provides = $provides;
30112 }
30113
30114
30115
30116
30117 public function getProvides()
30118 {
30119 return $this->provides;
30120 }
30121
30122
30123
30124
30125
30126
30127 public function setReplaces(array $replaces)
30128 {
30129 $this->replaces = $replaces;
30130 }
30131
30132
30133
30134
30135 public function getReplaces()
30136 {
30137 return $this->replaces;
30138 }
30139
30140
30141
30142
30143
30144
30145 public function setDevRequires(array $devRequires)
30146 {
30147 $this->devRequires = $devRequires;
30148 }
30149
30150
30151
30152
30153 public function getDevRequires()
30154 {
30155 return $this->devRequires;
30156 }
30157
30158
30159
30160
30161
30162
30163 public function setSuggests(array $suggests)
30164 {
30165 $this->suggests = $suggests;
30166 }
30167
30168
30169
30170
30171 public function getSuggests()
30172 {
30173 return $this->suggests;
30174 }
30175
30176
30177
30178
30179
30180
30181 public function setAutoload(array $autoload)
30182 {
30183 $this->autoload = $autoload;
30184 }
30185
30186
30187
30188
30189 public function getAutoload()
30190 {
30191 return $this->autoload;
30192 }
30193
30194
30195
30196
30197
30198
30199 public function setDevAutoload(array $devAutoload)
30200 {
30201 $this->devAutoload = $devAutoload;
30202 }
30203
30204
30205
30206
30207 public function getDevAutoload()
30208 {
30209 return $this->devAutoload;
30210 }
30211
30212
30213
30214
30215
30216
30217 public function setIncludePaths(array $includePaths)
30218 {
30219 $this->includePaths = $includePaths;
30220 }
30221
30222
30223
30224
30225 public function getIncludePaths()
30226 {
30227 return $this->includePaths;
30228 }
30229
30230
30231
30232
30233
30234
30235 public function setNotificationUrl($notificationUrl)
30236 {
30237 $this->notificationUrl = $notificationUrl;
30238 }
30239
30240
30241
30242
30243 public function getNotificationUrl()
30244 {
30245 return $this->notificationUrl;
30246 }
30247
30248
30249
30250
30251
30252
30253 public function setArchiveExcludes(array $excludes)
30254 {
30255 $this->archiveExcludes = $excludes;
30256 }
30257
30258
30259
30260
30261 public function getArchiveExcludes()
30262 {
30263 return $this->archiveExcludes;
30264 }
30265
30266
30267
30268
30269
30270
30271
30272
30273 public function replaceVersion($version, $prettyVersion)
30274 {
30275 $this->version = $version;
30276 $this->prettyVersion = $prettyVersion;
30277
30278 $this->stability = VersionParser::parseStability($version);
30279 $this->dev = $this->stability === 'dev';
30280 }
30281
30282 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
30283 {
30284 if (!$url) {
30285 return array();
30286 }
30287 $urls = array($url);
30288 if ($mirrors) {
30289 foreach ($mirrors as $mirror) {
30290 if ($urlType === 'dist') {
30291 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
30292 } elseif ($urlType === 'source' && $type === 'git') {
30293 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
30294 } elseif ($urlType === 'source' && $type === 'hg') {
30295 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
30296 }
30297 if (!in_array($mirrorUrl, $urls)) {
30298 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
30299 $func($urls, $mirrorUrl);
30300 }
30301 }
30302 }
30303
30304 return $urls;
30305 }
30306 }
30307 <?php
30308
30309
30310
30311
30312
30313
30314
30315
30316
30317
30318
30319 namespace Composer\Package;
30320
30321 use Composer\Repository\RepositoryInterface;
30322
30323
30324
30325
30326
30327
30328 interface PackageInterface
30329 {
30330
30331
30332
30333
30334
30335 public function getName();
30336
30337
30338
30339
30340
30341
30342 public function getPrettyName();
30343
30344
30345
30346
30347
30348
30349
30350
30351
30352 public function getNames();
30353
30354
30355
30356
30357
30358
30359 public function setId($id);
30360
30361
30362
30363
30364
30365
30366 public function getId();
30367
30368
30369
30370
30371
30372
30373 public function isDev();
30374
30375
30376
30377
30378
30379
30380 public function getType();
30381
30382
30383
30384
30385
30386
30387 public function getTargetDir();
30388
30389
30390
30391
30392
30393
30394 public function getExtra();
30395
30396
30397
30398
30399
30400
30401 public function setInstallationSource($type);
30402
30403
30404
30405
30406
30407
30408 public function getInstallationSource();
30409
30410
30411
30412
30413
30414
30415 public function getSourceType();
30416
30417
30418
30419
30420
30421
30422 public function getSourceUrl();
30423
30424
30425
30426
30427
30428
30429 public function getSourceUrls();
30430
30431
30432
30433
30434
30435
30436 public function getSourceReference();
30437
30438
30439
30440
30441
30442
30443 public function getSourceMirrors();
30444
30445
30446
30447
30448
30449
30450 public function getDistType();
30451
30452
30453
30454
30455
30456
30457 public function getDistUrl();
30458
30459
30460
30461
30462
30463
30464 public function getDistUrls();
30465
30466
30467
30468
30469
30470
30471 public function getDistReference();
30472
30473
30474
30475
30476
30477
30478 public function getDistSha1Checksum();
30479
30480
30481
30482
30483
30484
30485 public function getDistMirrors();
30486
30487
30488
30489
30490
30491
30492 public function getVersion();
30493
30494
30495
30496
30497
30498
30499 public function getPrettyVersion();
30500
30501
30502
30503
30504
30505
30506
30507
30508
30509 public function getFullPrettyVersion($truncate = true);
30510
30511
30512
30513
30514
30515
30516 public function getReleaseDate();
30517
30518
30519
30520
30521
30522
30523 public function getStability();
30524
30525
30526
30527
30528
30529
30530
30531 public function getRequires();
30532
30533
30534
30535
30536
30537
30538
30539 public function getConflicts();
30540
30541
30542
30543
30544
30545
30546
30547 public function getProvides();
30548
30549
30550
30551
30552
30553
30554
30555 public function getReplaces();
30556
30557
30558
30559
30560
30561
30562
30563 public function getDevRequires();
30564
30565
30566
30567
30568
30569
30570
30571 public function getSuggests();
30572
30573
30574
30575
30576
30577
30578
30579
30580
30581
30582
30583 public function getAutoload();
30584
30585
30586
30587
30588
30589
30590
30591
30592
30593
30594
30595 public function getDevAutoload();
30596
30597
30598
30599
30600
30601
30602
30603 public function getIncludePaths();
30604
30605
30606
30607
30608
30609
30610 public function setRepository(RepositoryInterface $repository);
30611
30612
30613
30614
30615
30616
30617 public function getRepository();
30618
30619
30620
30621
30622
30623
30624 public function getBinaries();
30625
30626
30627
30628
30629
30630
30631 public function getUniqueName();
30632
30633
30634
30635
30636
30637
30638 public function getNotificationUrl();
30639
30640
30641
30642
30643
30644
30645 public function __toString();
30646
30647
30648
30649
30650
30651
30652 public function getPrettyString();
30653
30654
30655
30656
30657
30658
30659 public function getArchiveExcludes();
30660
30661
30662
30663
30664
30665
30666 public function getTransportOptions();
30667
30668
30669
30670
30671
30672
30673 public function setSourceReference($reference);
30674
30675
30676
30677
30678
30679
30680 public function setDistUrl($url);
30681
30682
30683
30684
30685
30686
30687 public function setDistType($type);
30688
30689
30690
30691
30692
30693
30694 public function setDistReference($reference);
30695 }
30696 <?php
30697
30698
30699
30700
30701
30702
30703
30704
30705
30706
30707
30708 namespace Composer\Package;
30709
30710
30711
30712
30713 class RootAliasPackage extends AliasPackage implements RootPackageInterface
30714 {
30715 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
30716 {
30717 parent::__construct($aliasOf, $version, $prettyVersion);
30718 }
30719
30720
30721
30722
30723 public function getAliases()
30724 {
30725 return $this->aliasOf->getAliases();
30726 }
30727
30728
30729
30730
30731 public function getMinimumStability()
30732 {
30733 return $this->aliasOf->getMinimumStability();
30734 }
30735
30736
30737
30738
30739 public function getStabilityFlags()
30740 {
30741 return $this->aliasOf->getStabilityFlags();
30742 }
30743
30744
30745
30746
30747 public function getReferences()
30748 {
30749 return $this->aliasOf->getReferences();
30750 }
30751
30752
30753
30754
30755 public function getPreferStable()
30756 {
30757 return $this->aliasOf->getPreferStable();
30758 }
30759
30760
30761
30762
30763 public function getConfig()
30764 {
30765 return $this->aliasOf->getConfig();
30766 }
30767
30768
30769
30770
30771 public function setRequires(array $require)
30772 {
30773 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
30774
30775 $this->aliasOf->setRequires($require);
30776 }
30777
30778
30779
30780
30781 public function setDevRequires(array $devRequire)
30782 {
30783 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
30784
30785 $this->aliasOf->setDevRequires($devRequire);
30786 }
30787
30788
30789
30790
30791 public function setConflicts(array $conflicts)
30792 {
30793 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
30794 $this->aliasOf->setConflicts($conflicts);
30795 }
30796
30797
30798
30799
30800 public function setProvides(array $provides)
30801 {
30802 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
30803 $this->aliasOf->setProvides($provides);
30804 }
30805
30806
30807
30808
30809 public function setReplaces(array $replaces)
30810 {
30811 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
30812 $this->aliasOf->setReplaces($replaces);
30813 }
30814
30815
30816
30817
30818 public function setRepositories($repositories)
30819 {
30820 $this->aliasOf->setRepositories($repositories);
30821 }
30822
30823
30824
30825
30826 public function setAutoload(array $autoload)
30827 {
30828 $this->aliasOf->setAutoload($autoload);
30829 }
30830
30831
30832
30833
30834 public function setDevAutoload(array $devAutoload)
30835 {
30836 $this->aliasOf->setDevAutoload($devAutoload);
30837 }
30838
30839
30840
30841
30842 public function setStabilityFlags(array $stabilityFlags)
30843 {
30844 $this->aliasOf->setStabilityFlags($stabilityFlags);
30845 }
30846
30847
30848
30849
30850 public function setSuggests(array $suggests)
30851 {
30852 $this->aliasOf->setSuggests($suggests);
30853 }
30854
30855
30856
30857
30858 public function setExtra(array $extra)
30859 {
30860 $this->aliasOf->setExtra($extra);
30861 }
30862
30863 public function __clone()
30864 {
30865 parent::__clone();
30866 $this->aliasOf = clone $this->aliasOf;
30867 }
30868 }
30869 <?php
30870
30871
30872
30873
30874
30875
30876
30877
30878
30879
30880
30881 namespace Composer\Package;
30882
30883
30884
30885
30886
30887
30888 class RootPackage extends CompletePackage implements RootPackageInterface
30889 {
30890 protected $minimumStability = 'stable';
30891 protected $preferStable = false;
30892 protected $stabilityFlags = array();
30893 protected $config = array();
30894 protected $references = array();
30895 protected $aliases = array();
30896
30897
30898
30899
30900
30901
30902 public function setMinimumStability($minimumStability)
30903 {
30904 $this->minimumStability = $minimumStability;
30905 }
30906
30907
30908
30909
30910 public function getMinimumStability()
30911 {
30912 return $this->minimumStability;
30913 }
30914
30915
30916
30917
30918
30919
30920 public function setStabilityFlags(array $stabilityFlags)
30921 {
30922 $this->stabilityFlags = $stabilityFlags;
30923 }
30924
30925
30926
30927
30928 public function getStabilityFlags()
30929 {
30930 return $this->stabilityFlags;
30931 }
30932
30933
30934
30935
30936
30937
30938 public function setPreferStable($preferStable)
30939 {
30940 $this->preferStable = $preferStable;
30941 }
30942
30943
30944
30945
30946 public function getPreferStable()
30947 {
30948 return $this->preferStable;
30949 }
30950
30951
30952
30953
30954
30955
30956 public function setConfig(array $config)
30957 {
30958 $this->config = $config;
30959 }
30960
30961
30962
30963
30964 public function getConfig()
30965 {
30966 return $this->config;
30967 }
30968
30969
30970
30971
30972
30973
30974 public function setReferences(array $references)
30975 {
30976 $this->references = $references;
30977 }
30978
30979
30980
30981
30982 public function getReferences()
30983 {
30984 return $this->references;
30985 }
30986
30987
30988
30989
30990
30991
30992 public function setAliases(array $aliases)
30993 {
30994 $this->aliases = $aliases;
30995 }
30996
30997
30998
30999
31000 public function getAliases()
31001 {
31002 return $this->aliases;
31003 }
31004 }
31005 <?php
31006
31007
31008
31009
31010
31011
31012
31013
31014
31015
31016
31017 namespace Composer\Package;
31018
31019
31020
31021
31022
31023
31024 interface RootPackageInterface extends CompletePackageInterface
31025 {
31026
31027
31028
31029
31030
31031 public function getAliases();
31032
31033
31034
31035
31036
31037
31038 public function getMinimumStability();
31039
31040
31041
31042
31043
31044
31045
31046
31047 public function getStabilityFlags();
31048
31049
31050
31051
31052
31053
31054
31055
31056 public function getReferences();
31057
31058
31059
31060
31061
31062
31063 public function getPreferStable();
31064
31065
31066
31067
31068
31069
31070 public function getConfig();
31071
31072
31073
31074
31075
31076
31077 public function setRequires(array $requires);
31078
31079
31080
31081
31082
31083
31084 public function setDevRequires(array $devRequires);
31085
31086
31087
31088
31089
31090
31091 public function setConflicts(array $conflicts);
31092
31093
31094
31095
31096
31097
31098 public function setProvides(array $provides);
31099
31100
31101
31102
31103
31104
31105 public function setReplaces(array $replaces);
31106
31107
31108
31109
31110
31111
31112 public function setRepositories($repositories);
31113
31114
31115
31116
31117
31118
31119 public function setAutoload(array $autoload);
31120
31121
31122
31123
31124
31125
31126 public function setDevAutoload(array $devAutoload);
31127
31128
31129
31130
31131
31132
31133 public function setStabilityFlags(array $stabilityFlags);
31134
31135
31136
31137
31138
31139
31140 public function setSuggests(array $suggests);
31141
31142
31143
31144
31145 public function setExtra(array $extra);
31146 }
31147 <?php
31148
31149
31150
31151
31152
31153
31154
31155
31156
31157
31158
31159 namespace Composer\Package\Version;
31160
31161 use Composer\Config;
31162 use Composer\Repository\Vcs\HgDriver;
31163 use Composer\IO\NullIO;
31164 use Composer\Semver\VersionParser as SemverVersionParser;
31165 use Composer\Util\Git as GitUtil;
31166 use Composer\Util\ProcessExecutor;
31167 use Composer\Util\Svn as SvnUtil;
31168
31169
31170
31171
31172
31173
31174
31175 class VersionGuesser
31176 {
31177
31178
31179
31180 private $config;
31181
31182
31183
31184
31185 private $process;
31186
31187
31188
31189
31190 private $versionParser;
31191
31192
31193
31194
31195
31196
31197 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
31198 {
31199 $this->config = $config;
31200 $this->process = $process;
31201 $this->versionParser = $versionParser;
31202 }
31203
31204
31205
31206
31207
31208
31209
31210 public function guessVersion(array $packageConfig, $path)
31211 {
31212 if (function_exists('proc_open')) {
31213 $versionData = $this->guessGitVersion($packageConfig, $path);
31214 if (null !== $versionData && null !== $versionData['version']) {
31215 return $this->postprocess($versionData);
31216 }
31217
31218 $versionData = $this->guessHgVersion($packageConfig, $path);
31219 if (null !== $versionData && null !== $versionData['version']) {
31220 return $this->postprocess($versionData);
31221 }
31222
31223 $versionData = $this->guessFossilVersion($packageConfig, $path);
31224 if (null !== $versionData && null !== $versionData['version']) {
31225 return $this->postprocess($versionData);
31226 }
31227
31228 $versionData = $this->guessSvnVersion($packageConfig, $path);
31229 if (null !== $versionData && null !== $versionData['version']) {
31230 return $this->postprocess($versionData);
31231 }
31232 }
31233 }
31234
31235 private function postprocess(array $versionData)
31236 {
31237 if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version'] && $versionData['feature_pretty_version'] === $versionData['feature_pretty_version']) {
31238 unset($versionData['feature_version'], $versionData['feature_pretty_version']);
31239 }
31240
31241 if ('-dev' === substr($versionData['version'], -4) && preg_match('{\.9{7}}', $versionData['version'])) {
31242 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
31243 }
31244
31245 if (!empty($versionData['feature_version']) && '-dev' === substr($versionData['feature_version'], -4) && preg_match('{\.9{7}}', $versionData['feature_version'])) {
31246 $versionData['feature_pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['feature_version']);
31247 }
31248
31249 return $versionData;
31250 }
31251
31252 private function guessGitVersion(array $packageConfig, $path)
31253 {
31254 GitUtil::cleanEnv();
31255 $commit = null;
31256 $version = null;
31257 $prettyVersion = null;
31258 $featureVersion = null;
31259 $featurePrettyVersion = null;
31260 $isDetached = false;
31261
31262
31263  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
31264 $branches = array();
31265 $isFeatureBranch = false;
31266
31267
31268  foreach ($this->process->splitLines($output) as $branch) {
31269 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
31270 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
31271 $version = 'dev-' . $match[2];
31272 $prettyVersion = $version;
31273 $isFeatureBranch = true;
31274 $isDetached = true;
31275 } else {
31276 $version = $this->versionParser->normalizeBranch($match[1]);
31277 $prettyVersion = 'dev-' . $match[1];
31278 $isFeatureBranch = 0 === strpos($version, 'dev-');
31279 }
31280
31281 if ($match[2]) {
31282 $commit = $match[2];
31283 }
31284 }
31285
31286 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
31287 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
31288 $branches[] = $match[1];
31289 }
31290 }
31291 }
31292
31293 if ($isFeatureBranch) {
31294 $featureVersion = $version;
31295 $featurePrettyVersion = $prettyVersion;
31296
31297  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
31298 $version = $result['version'];
31299 $prettyVersion = $result['pretty_version'];
31300 }
31301 }
31302
31303 if (!$version || $isDetached) {
31304 $result = $this->versionFromGitTags($path);
31305 if ($result) {
31306 $version = $result['version'];
31307 $prettyVersion = $result['pretty_version'];
31308 $featureVersion = null;
31309 $featurePrettyVersion = null;
31310 }
31311 }
31312
31313 if (!$commit) {
31314 $command = 'git log --pretty="%H" -n1 HEAD';
31315 if (0 === $this->process->execute($command, $output, $path)) {
31316 $commit = trim($output) ?: null;
31317 }
31318 }
31319
31320 if ($featureVersion) {
31321 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion, 'feature_version' => $featureVersion, 'feature_pretty_version' => $featurePrettyVersion);
31322 }
31323
31324 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
31325 }
31326
31327 private function versionFromGitTags($path)
31328 {
31329
31330  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
31331 try {
31332 $version = $this->versionParser->normalize(trim($output));
31333
31334 return array('version' => $version, 'pretty_version' => trim($output));
31335 } catch (\Exception $e) {
31336 }
31337 }
31338
31339 return null;
31340 }
31341
31342 private function guessHgVersion(array $packageConfig, $path)
31343 {
31344
31345  if (0 === $this->process->execute('hg branch', $output, $path)) {
31346 $branch = trim($output);
31347 $version = $this->versionParser->normalizeBranch($branch);
31348 $isFeatureBranch = 0 === strpos($version, 'dev-');
31349
31350 if ('9999999-dev' === $version) {
31351 return array('version' => $version, 'commit' => null, 'pretty_version' => 'dev-'.$branch);
31352 }
31353
31354 if (!$isFeatureBranch) {
31355 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
31356 }
31357
31358
31359  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
31360 $branches = array_keys($driver->getBranches());
31361
31362
31363  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
31364 $result['commit'] = '';
31365 $result['feature_version'] = $version;
31366 $result['feature_pretty_version'] = $version;
31367
31368 return $result;
31369 }
31370 }
31371
31372 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
31373 {
31374 $prettyVersion = $version;
31375
31376
31377  
31378  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
31379 || strpos(json_encode($packageConfig), '"self.version"')
31380 ) {
31381 $branch = preg_replace('{^dev-}', '', $version);
31382 $length = PHP_INT_MAX;
31383
31384 $nonFeatureBranches = '';
31385 if (!empty($packageConfig['non-feature-branches'])) {
31386 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
31387 }
31388
31389 foreach ($branches as $candidate) {
31390
31391  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
31392 break;
31393 }
31394
31395
31396  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
31397 continue;
31398 }
31399
31400 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
31401 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
31402 continue;
31403 }
31404
31405 if (strlen($output) < $length) {
31406 $length = strlen($output);
31407 $version = $this->versionParser->normalizeBranch($candidate);
31408 $prettyVersion = 'dev-' . $match[1];
31409 }
31410 }
31411 }
31412
31413 return array('version' => $version, 'pretty_version' => $prettyVersion);
31414 }
31415
31416 private function guessFossilVersion(array $packageConfig, $path)
31417 {
31418 $version = null;
31419 $prettyVersion = null;
31420
31421
31422  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
31423 $branch = trim($output);
31424 $version = $this->versionParser->normalizeBranch($branch);
31425 $prettyVersion = 'dev-' . $branch;
31426 }
31427
31428
31429  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
31430 try {
31431 $version = $this->versionParser->normalize(trim($output));
31432 $prettyVersion = trim($output);
31433 } catch (\Exception $e) {
31434 }
31435 }
31436
31437 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
31438 }
31439
31440 private function guessSvnVersion(array $packageConfig, $path)
31441 {
31442 SvnUtil::cleanEnv();
31443
31444
31445  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
31446 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
31447 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
31448 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
31449
31450 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
31451
31452 if (preg_match($urlPattern, $output, $matches)) {
31453 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
31454
31455  $version = $this->versionParser->normalizeBranch($matches[3]);
31456 $prettyVersion = 'dev-' . $matches[3];
31457
31458 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
31459 }
31460
31461 $prettyVersion = trim($matches[1]);
31462 $version = $this->versionParser->normalize($prettyVersion);
31463
31464 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
31465 }
31466 }
31467 }
31468 }
31469 <?php
31470
31471
31472
31473
31474
31475
31476
31477
31478
31479
31480
31481 namespace Composer\Package\Version;
31482
31483 use Composer\Repository\PlatformRepository;
31484 use Composer\Semver\VersionParser as SemverVersionParser;
31485 use Composer\Semver\Semver;
31486
31487 class VersionParser extends SemverVersionParser
31488 {
31489 private static $constraints = array();
31490
31491
31492
31493
31494 public function parseConstraints($constraints)
31495 {
31496 if (!isset(self::$constraints[$constraints])) {
31497 self::$constraints[$constraints] = parent::parseConstraints($constraints);
31498 }
31499
31500 return self::$constraints[$constraints];
31501 }
31502
31503
31504
31505
31506
31507
31508
31509
31510
31511
31512
31513 public function parseNameVersionPairs(array $pairs)
31514 {
31515 $pairs = array_values($pairs);
31516 $result = array();
31517
31518 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
31519 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
31520 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
31521 $pair .= ' '.$pairs[$i + 1];
31522 $i++;
31523 }
31524
31525 if (strpos($pair, ' ')) {
31526 list($name, $version) = explode(' ', $pair, 2);
31527 $result[] = array('name' => $name, 'version' => $version);
31528 } else {
31529 $result[] = array('name' => $pair);
31530 }
31531 }
31532
31533 return $result;
31534 }
31535
31536
31537
31538
31539 public static function isUpgrade($normalizedFrom, $normalizedTo)
31540 {
31541 if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') {
31542 return true;
31543 }
31544
31545 $sorted = Semver::sort(array($normalizedTo, $normalizedFrom));
31546
31547 return $sorted[0] === $normalizedFrom;
31548 }
31549 }
31550 <?php
31551
31552
31553
31554
31555
31556
31557
31558
31559
31560
31561
31562 namespace Composer\Package\Version;
31563
31564 use Composer\DependencyResolver\Pool;
31565 use Composer\Package\BasePackage;
31566 use Composer\Package\PackageInterface;
31567 use Composer\Package\Loader\ArrayLoader;
31568 use Composer\Package\Dumper\ArrayDumper;
31569 use Composer\Semver\Constraint\Constraint;
31570
31571
31572
31573
31574
31575
31576
31577 class VersionSelector
31578 {
31579 private $pool;
31580
31581 private $parser;
31582
31583 public function __construct(Pool $pool)
31584 {
31585 $this->pool = $pool;
31586 }
31587
31588
31589
31590
31591
31592
31593
31594
31595
31596
31597
31598 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
31599 {
31600 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
31601 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
31602
31603 if ($targetPhpVersion) {
31604 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
31605 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
31606 $reqs = $pkg->getRequires();
31607
31608 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
31609 });
31610 }
31611
31612 if (!$candidates) {
31613 return false;
31614 }
31615
31616
31617  $package = reset($candidates);
31618 $minPriority = BasePackage::$stabilities[$preferredStability];
31619 foreach ($candidates as $candidate) {
31620 $candidatePriority = $candidate->getStabilityPriority();
31621 $currentPriority = $package->getStabilityPriority();
31622
31623
31624  
31625  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
31626 continue;
31627 }
31628
31629
31630  
31631  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
31632 $package = $candidate;
31633 continue;
31634 }
31635
31636
31637  
31638  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
31639 $package = $candidate;
31640 continue;
31641 }
31642
31643
31644  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
31645 $package = $candidate;
31646 }
31647 }
31648
31649 return $package;
31650 }
31651
31652
31653
31654
31655
31656
31657
31658
31659
31660
31661
31662
31663
31664
31665
31666
31667 public function findRecommendedRequireVersion(PackageInterface $package)
31668 {
31669 $version = $package->getVersion();
31670 if (!$package->isDev()) {
31671 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
31672 }
31673
31674 $loader = new ArrayLoader($this->getParser());
31675 $dumper = new ArrayDumper();
31676 $extra = $loader->getBranchAlias($dumper->dump($package));
31677 if ($extra) {
31678 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
31679 if ($count) {
31680 $extra = str_replace('.9999999', '.0', $extra);
31681
31682 return $this->transformVersion($extra, $extra, 'dev');
31683 }
31684 }
31685
31686 return $package->getPrettyVersion();
31687 }
31688
31689 private function transformVersion($version, $prettyVersion, $stability)
31690 {
31691
31692  
31693  $semanticVersionParts = explode('.', $version);
31694
31695
31696  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
31697
31698  if ($semanticVersionParts[0] === '0') {
31699 unset($semanticVersionParts[3]);
31700 } else {
31701 unset($semanticVersionParts[2], $semanticVersionParts[3]);
31702 }
31703 $version = implode('.', $semanticVersionParts);
31704 } else {
31705 return $prettyVersion;
31706 }
31707
31708
31709  if ($stability != 'stable') {
31710 $version .= '@'.$stability;
31711 }
31712
31713
31714  return '^' . $version;
31715 }
31716
31717 private function getParser()
31718 {
31719 if ($this->parser === null) {
31720 $this->parser = new VersionParser();
31721 }
31722
31723 return $this->parser;
31724 }
31725 }
31726 <?php
31727
31728
31729
31730
31731
31732
31733
31734
31735
31736
31737
31738 namespace Composer\Plugin\Capability;
31739
31740
31741
31742
31743
31744
31745
31746 interface Capability
31747 {
31748 }
31749 <?php
31750
31751
31752
31753
31754
31755
31756
31757
31758
31759
31760
31761 namespace Composer\Plugin\Capability;
31762
31763
31764
31765
31766
31767
31768
31769
31770
31771
31772
31773 interface CommandProvider extends Capability
31774 {
31775
31776
31777
31778
31779
31780 public function getCommands();
31781 }
31782 <?php
31783
31784
31785
31786
31787
31788
31789
31790
31791
31792
31793
31794 namespace Composer\Plugin;
31795
31796
31797
31798
31799
31800
31801
31802
31803 interface Capable
31804 {
31805
31806
31807
31808
31809
31810
31811
31812
31813
31814
31815
31816
31817
31818
31819
31820
31821
31822
31823 public function getCapabilities();
31824 }
31825 <?php
31826
31827
31828
31829
31830
31831
31832
31833
31834
31835
31836
31837 namespace Composer\Plugin;
31838
31839 use Composer\EventDispatcher\Event;
31840 use Symfony\Component\Console\Input\InputInterface;
31841 use Symfony\Component\Console\Output\OutputInterface;
31842
31843
31844
31845
31846
31847
31848 class CommandEvent extends Event
31849 {
31850
31851
31852
31853 private $commandName;
31854
31855
31856
31857
31858 private $input;
31859
31860
31861
31862
31863 private $output;
31864
31865
31866
31867
31868
31869
31870
31871
31872
31873
31874
31875 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
31876 {
31877 parent::__construct($name, $args, $flags);
31878 $this->commandName = $commandName;
31879 $this->input = $input;
31880 $this->output = $output;
31881 }
31882
31883
31884
31885
31886
31887
31888 public function getInput()
31889 {
31890 return $this->input;
31891 }
31892
31893
31894
31895
31896
31897
31898 public function getOutput()
31899 {
31900 return $this->output;
31901 }
31902
31903
31904
31905
31906
31907
31908 public function getCommandName()
31909 {
31910 return $this->commandName;
31911 }
31912 }
31913 <?php
31914
31915
31916
31917
31918
31919
31920
31921
31922
31923
31924
31925 namespace Composer\Plugin;
31926
31927
31928
31929
31930
31931
31932 class PluginEvents
31933 {
31934
31935
31936
31937
31938
31939
31940
31941
31942 const INIT = 'init';
31943
31944
31945
31946
31947
31948
31949
31950
31951
31952 const COMMAND = 'command';
31953
31954
31955
31956
31957
31958
31959
31960
31961
31962 const PRE_FILE_DOWNLOAD = 'pre-file-download';
31963
31964
31965
31966
31967
31968
31969
31970
31971
31972 const PRE_COMMAND_RUN = 'pre-command-run';
31973 }
31974 <?php
31975
31976
31977
31978
31979
31980
31981
31982
31983
31984
31985
31986 namespace Composer\Plugin;
31987
31988 use Composer\Composer;
31989 use Composer\IO\IOInterface;
31990
31991
31992
31993
31994
31995
31996 interface PluginInterface
31997 {
31998
31999
32000
32001
32002
32003 const PLUGIN_API_VERSION = '1.1.0';
32004
32005
32006
32007
32008
32009
32010
32011 public function activate(Composer $composer, IOInterface $io);
32012 }
32013 <?php
32014
32015
32016
32017
32018
32019
32020
32021
32022
32023
32024
32025 namespace Composer\Plugin;
32026
32027 use Composer\Composer;
32028 use Composer\EventDispatcher\EventSubscriberInterface;
32029 use Composer\IO\IOInterface;
32030 use Composer\Package\CompletePackage;
32031 use Composer\Package\Package;
32032 use Composer\Package\Version\VersionParser;
32033 use Composer\Repository\RepositoryInterface;
32034 use Composer\Package\PackageInterface;
32035 use Composer\Package\Link;
32036 use Composer\Semver\Constraint\Constraint;
32037 use Composer\DependencyResolver\Pool;
32038 use Composer\Plugin\Capability\Capability;
32039 use Composer\Util\PackageSorter;
32040
32041
32042
32043
32044
32045
32046
32047 class PluginManager
32048 {
32049 protected $composer;
32050 protected $io;
32051 protected $globalComposer;
32052 protected $versionParser;
32053 protected $disablePlugins = false;
32054
32055 protected $plugins = array();
32056 protected $registeredPlugins = array();
32057
32058 private static $classCounter = 0;
32059
32060
32061
32062
32063
32064
32065
32066
32067
32068 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
32069 {
32070 $this->io = $io;
32071 $this->composer = $composer;
32072 $this->globalComposer = $globalComposer;
32073 $this->versionParser = new VersionParser();
32074 $this->disablePlugins = $disablePlugins;
32075 }
32076
32077
32078
32079
32080 public function loadInstalledPlugins()
32081 {
32082 if ($this->disablePlugins) {
32083 return;
32084 }
32085
32086 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
32087 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
32088 if ($repo) {
32089 $this->loadRepository($repo);
32090 }
32091 if ($globalRepo) {
32092 $this->loadRepository($globalRepo);
32093 }
32094 }
32095
32096
32097
32098
32099
32100
32101 public function getPlugins()
32102 {
32103 return $this->plugins;
32104 }
32105
32106
32107
32108
32109
32110
32111 public function getGlobalComposer()
32112 {
32113 return $this->globalComposer;
32114 }
32115
32116
32117
32118
32119
32120
32121
32122
32123
32124
32125
32126
32127 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
32128 {
32129 if ($this->disablePlugins) {
32130 return;
32131 }
32132
32133 if ($package->getType() === 'composer-plugin') {
32134 $requiresComposer = null;
32135 foreach ($package->getRequires() as $link) { 
32136 if ('composer-plugin-api' === $link->getTarget()) {
32137 $requiresComposer = $link->getConstraint();
32138 break;
32139 }
32140 }
32141
32142 if (!$requiresComposer) {
32143 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
32144 }
32145
32146 $currentPluginApiVersion = $this->getPluginApiVersion();
32147 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
32148
32149 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
32150 $this->io->writeError('<warning>The "' . $package->getName() . '" plugin requires composer-plugin-api 1.0.0, this *WILL* break in the future and it should be fixed ASAP (require ^1.0 for example).</warning>');
32151 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
32152 $this->io->writeError('<warning>The "' . $package->getName() . '" plugin 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.</warning>');
32153
32154 return;
32155 }
32156 }
32157
32158 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
32159
32160 if (in_array($package->getName(), $this->registeredPlugins)) {
32161 return;
32162 }
32163
32164 $extra = $package->getExtra();
32165 if (empty($extra['class'])) {
32166 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
32167 }
32168 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
32169
32170 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
32171 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
32172
32173 $pool = new Pool('dev');
32174 $pool->addRepository($localRepo);
32175 if ($globalRepo) {
32176 $pool->addRepository($globalRepo);
32177 }
32178
32179 $autoloadPackages = array($package->getName() => $package);
32180 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
32181
32182 $generator = $this->composer->getAutoloadGenerator();
32183 $autoloads = array();
32184 foreach ($autoloadPackages as $autoloadPackage) {
32185 $downloadPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage));
32186 $autoloads[] = array($autoloadPackage, $downloadPath);
32187 }
32188
32189 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
32190 $classLoader = $generator->createLoader($map);
32191 $classLoader->register();
32192
32193 foreach ($classes as $class) {
32194 if (class_exists($class, false)) {
32195 $class = trim($class, '\\');
32196 $path = $classLoader->findFile($class);
32197 $code = file_get_contents($path);
32198 $separatorPos = strrpos($class, '\\');
32199 $className = $class;
32200 if ($separatorPos) {
32201 $className = substr($class, $separatorPos + 1);
32202 }
32203 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
32204 $code = str_replace('__FILE__', var_export($path, true), $code);
32205 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
32206 $code = str_replace('__CLASS__', var_export($class, true), $code);
32207 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
32208 eval($code);
32209 $class .= '_composer_tmp'.self::$classCounter;
32210 self::$classCounter++;
32211 }
32212
32213 if ($oldInstallerPlugin) {
32214 $installer = new $class($this->io, $this->composer);
32215 $this->composer->getInstallationManager()->addInstaller($installer);
32216 } elseif (class_exists($class)) {
32217 $plugin = new $class();
32218 $this->addPlugin($plugin);
32219 $this->registeredPlugins[] = $package->getName();
32220 } elseif ($failOnMissingClasses) {
32221 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
32222 }
32223 }
32224 }
32225
32226
32227
32228
32229
32230
32231 protected function getPluginApiVersion()
32232 {
32233 return PluginInterface::PLUGIN_API_VERSION;
32234 }
32235
32236
32237
32238
32239
32240
32241
32242
32243
32244
32245 public function addPlugin(PluginInterface $plugin)
32246 {
32247 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
32248 $this->plugins[] = $plugin;
32249 $plugin->activate($this->composer, $this->io);
32250
32251 if ($plugin instanceof EventSubscriberInterface) {
32252 $this->composer->getEventDispatcher()->addSubscriber($plugin);
32253 }
32254 }
32255
32256
32257
32258
32259
32260
32261
32262
32263
32264
32265
32266
32267 private function loadRepository(RepositoryInterface $repo)
32268 {
32269 $packages = $repo->getPackages();
32270 $sortedPackages = array_reverse(PackageSorter::sortPackages($packages));
32271 foreach ($sortedPackages as $package) {
32272 if (!($package instanceof CompletePackage)) {
32273 continue;
32274 }
32275 if ('composer-plugin' === $package->getType()) {
32276 $this->registerPackage($package);
32277
32278  } elseif ('composer-installer' === $package->getType()) {
32279 $this->registerPackage($package);
32280 }
32281 }
32282 }
32283
32284
32285
32286
32287
32288
32289
32290
32291
32292
32293 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
32294 {
32295 $requires = array_merge(
32296 $package->getRequires(),
32297 $package->getDevRequires()
32298 );
32299
32300 foreach ($requires as $requireLink) {
32301 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
32302 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
32303 $collected[$requiredPackage->getName()] = $requiredPackage;
32304 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
32305 }
32306 }
32307
32308 return $collected;
32309 }
32310
32311
32312
32313
32314
32315
32316
32317
32318
32319
32320
32321 private function lookupInstalledPackage(Pool $pool, Link $link)
32322 {
32323 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
32324
32325 return !empty($packages) ? $packages[0] : null;
32326 }
32327
32328
32329
32330
32331
32332
32333
32334
32335
32336 private function getInstallPath(PackageInterface $package, $global = false)
32337 {
32338 if (!$global) {
32339 return $this->composer->getInstallationManager()->getInstallPath($package);
32340 }
32341
32342 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
32343 }
32344
32345
32346
32347
32348
32349
32350
32351 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
32352 {
32353 if (!($plugin instanceof Capable)) {
32354 return null;
32355 }
32356
32357 $capabilities = (array) $plugin->getCapabilities();
32358
32359 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
32360 return trim($capabilities[$capability]);
32361 }
32362
32363 if (
32364 array_key_exists($capability, $capabilities)
32365 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
32366 ) {
32367 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
32368 }
32369 }
32370
32371
32372
32373
32374
32375
32376
32377
32378
32379 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
32380 {
32381 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
32382 if (!class_exists($capabilityClass)) {
32383 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
32384 }
32385
32386 $ctorArgs['plugin'] = $plugin;
32387 $capabilityObj = new $capabilityClass($ctorArgs);
32388
32389
32390  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
32391 throw new \RuntimeException(
32392 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
32393 );
32394 }
32395
32396 return $capabilityObj;
32397 }
32398 }
32399
32400
32401
32402
32403
32404
32405
32406
32407 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
32408 {
32409 $capabilities = array();
32410 foreach ($this->getPlugins() as $plugin) {
32411 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
32412 $capabilities[] = $capability;
32413 }
32414 }
32415
32416 return $capabilities;
32417 }
32418 }
32419 <?php
32420
32421
32422
32423
32424
32425
32426
32427
32428
32429
32430
32431 namespace Composer\Plugin;
32432
32433 use Composer\EventDispatcher\Event;
32434 use Symfony\Component\Console\Input\InputInterface;
32435
32436
32437
32438
32439
32440
32441 class PreCommandRunEvent extends Event
32442 {
32443
32444
32445
32446 private $input;
32447
32448
32449
32450
32451 private $command;
32452
32453
32454
32455
32456
32457
32458
32459
32460 public function __construct($name, InputInterface $input, $command)
32461 {
32462 parent::__construct($name);
32463 $this->input = $input;
32464 $this->command = $command;
32465 }
32466
32467
32468
32469
32470
32471
32472 public function getInput()
32473 {
32474 return $this->input;
32475 }
32476
32477
32478
32479
32480
32481
32482 public function getCommand()
32483 {
32484 return $this->command;
32485 }
32486 }
32487 <?php
32488
32489
32490
32491
32492
32493
32494
32495
32496
32497
32498
32499 namespace Composer\Plugin;
32500
32501 use Composer\EventDispatcher\Event;
32502 use Composer\Util\RemoteFilesystem;
32503
32504
32505
32506
32507
32508
32509 class PreFileDownloadEvent extends Event
32510 {
32511
32512
32513
32514 private $rfs;
32515
32516
32517
32518
32519 private $processedUrl;
32520
32521
32522
32523
32524
32525
32526
32527
32528 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
32529 {
32530 parent::__construct($name);
32531 $this->rfs = $rfs;
32532 $this->processedUrl = $processedUrl;
32533 }
32534
32535
32536
32537
32538
32539
32540 public function getRemoteFilesystem()
32541 {
32542 return $this->rfs;
32543 }
32544
32545
32546
32547
32548
32549
32550 public function setRemoteFilesystem(RemoteFilesystem $rfs)
32551 {
32552 $this->rfs = $rfs;
32553 }
32554
32555
32556
32557
32558
32559
32560 public function getProcessedUrl()
32561 {
32562 return $this->processedUrl;
32563 }
32564 }
32565 <?php
32566
32567
32568
32569
32570
32571
32572
32573
32574
32575
32576
32577 namespace Composer\Question;
32578
32579 use Symfony\Component\Console\Exception\InvalidArgumentException;
32580 use Symfony\Component\Console\Question\Question;
32581
32582
32583
32584
32585
32586
32587
32588
32589 class StrictConfirmationQuestion extends Question
32590 {
32591 private $trueAnswerRegex;
32592 private $falseAnswerRegex;
32593
32594
32595
32596
32597
32598
32599
32600
32601
32602 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
32603 {
32604 parent::__construct($question, (bool) $default);
32605
32606 $this->trueAnswerRegex = $trueAnswerRegex;
32607 $this->falseAnswerRegex = $falseAnswerRegex;
32608 $this->setNormalizer($this->getDefaultNormalizer());
32609 $this->setValidator($this->getDefaultValidator());
32610 }
32611
32612
32613
32614
32615
32616
32617 private function getDefaultNormalizer()
32618 {
32619 $default = $this->getDefault();
32620 $trueRegex = $this->trueAnswerRegex;
32621 $falseRegex = $this->falseAnswerRegex;
32622
32623 return function ($answer) use ($default, $trueRegex, $falseRegex) {
32624 if (is_bool($answer)) {
32625 return $answer;
32626 }
32627 if (empty($answer) && !empty($default)) {
32628 return $default;
32629 }
32630
32631 if (preg_match($trueRegex, $answer)) {
32632 return true;
32633 }
32634
32635 if (preg_match($falseRegex, $answer)) {
32636 return false;
32637 }
32638
32639 return null;
32640 };
32641 }
32642
32643
32644
32645
32646
32647
32648 private function getDefaultValidator()
32649 {
32650 return function ($answer) {
32651 if (!is_bool($answer)) {
32652 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
32653 }
32654
32655 return $answer;
32656 };
32657 }
32658 }
32659 <?php
32660
32661
32662
32663
32664
32665
32666
32667
32668
32669
32670
32671 namespace Composer\Repository;
32672
32673 use Composer\Package\AliasPackage;
32674 use Composer\Package\PackageInterface;
32675 use Composer\Package\CompletePackageInterface;
32676 use Composer\Package\Version\VersionParser;
32677 use Composer\Semver\Constraint\ConstraintInterface;
32678 use Composer\Semver\Constraint\Constraint;
32679
32680
32681
32682
32683
32684
32685 class ArrayRepository extends BaseRepository
32686 {
32687
32688 protected $packages;
32689
32690 public function __construct(array $packages = array())
32691 {
32692 foreach ($packages as $package) {
32693 $this->addPackage($package);
32694 }
32695 }
32696
32697
32698
32699
32700 public function findPackage($name, $constraint)
32701 {
32702 $name = strtolower($name);
32703
32704 if (!$constraint instanceof ConstraintInterface) {
32705 $versionParser = new VersionParser();
32706 $constraint = $versionParser->parseConstraints($constraint);
32707 }
32708
32709 foreach ($this->getPackages() as $package) {
32710 if ($name === $package->getName()) {
32711 $pkgConstraint = new Constraint('==', $package->getVersion());
32712 if ($constraint->matches($pkgConstraint)) {
32713 return $package;
32714 }
32715 }
32716 }
32717
32718 return null;
32719 }
32720
32721
32722
32723
32724 public function findPackages($name, $constraint = null)
32725 {
32726
32727  $name = strtolower($name);
32728 $packages = array();
32729
32730 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
32731 $versionParser = new VersionParser();
32732 $constraint = $versionParser->parseConstraints($constraint);
32733 }
32734
32735 foreach ($this->getPackages() as $package) {
32736 if ($name === $package->getName()) {
32737 $pkgConstraint = new Constraint('==', $package->getVersion());
32738 if (null === $constraint || $constraint->matches($pkgConstraint)) {
32739 $packages[] = $package;
32740 }
32741 }
32742 }
32743
32744 return $packages;
32745 }
32746
32747
32748
32749
32750 public function search($query, $mode = 0, $type = null)
32751 {
32752 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
32753
32754 $matches = array();
32755 foreach ($this->getPackages() as $package) {
32756 $name = $package->getName();
32757 if (isset($matches[$name])) {
32758 continue;
32759 }
32760 if (preg_match($regex, $name)
32761 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
32762 ) {
32763 if (null !== $type && $package->getType() !== $type) {
32764 continue;
32765 }
32766
32767 $matches[$name] = array(
32768 'name' => $package->getPrettyName(),
32769 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
32770 );
32771 }
32772 }
32773
32774 return array_values($matches);
32775 }
32776
32777
32778
32779
32780 public function hasPackage(PackageInterface $package)
32781 {
32782 $packageId = $package->getUniqueName();
32783
32784 foreach ($this->getPackages() as $repoPackage) {
32785 if ($packageId === $repoPackage->getUniqueName()) {
32786 return true;
32787 }
32788 }
32789
32790 return false;
32791 }
32792
32793
32794
32795
32796
32797
32798 public function addPackage(PackageInterface $package)
32799 {
32800 if (null === $this->packages) {
32801 $this->initialize();
32802 }
32803 $package->setRepository($this);
32804 $this->packages[] = $package;
32805
32806 if ($package instanceof AliasPackage) {
32807 $aliasedPackage = $package->getAliasOf();
32808 if (null === $aliasedPackage->getRepository()) {
32809 $this->addPackage($aliasedPackage);
32810 }
32811 }
32812 }
32813
32814 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
32815 {
32816 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
32817 }
32818
32819
32820
32821
32822
32823
32824 public function removePackage(PackageInterface $package)
32825 {
32826 $packageId = $package->getUniqueName();
32827
32828 foreach ($this->getPackages() as $key => $repoPackage) {
32829 if ($packageId === $repoPackage->getUniqueName()) {
32830 array_splice($this->packages, $key, 1);
32831
32832 return;
32833 }
32834 }
32835 }
32836
32837
32838
32839
32840 public function getPackages()
32841 {
32842 if (null === $this->packages) {
32843 $this->initialize();
32844 }
32845
32846 return $this->packages;
32847 }
32848
32849
32850
32851
32852
32853
32854 public function count()
32855 {
32856 return count($this->packages);
32857 }
32858
32859
32860
32861
32862 protected function initialize()
32863 {
32864 $this->packages = array();
32865 }
32866 }
32867 <?php
32868
32869
32870
32871
32872
32873
32874
32875
32876
32877
32878
32879 namespace Composer\Repository;
32880
32881 use Composer\IO\IOInterface;
32882 use Composer\Json\JsonFile;
32883 use Composer\Package\Loader\ArrayLoader;
32884 use Composer\Package\Loader\LoaderInterface;
32885 use Composer\Util\Zip;
32886
32887
32888
32889
32890 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
32891 {
32892
32893 protected $loader;
32894
32895 protected $lookup;
32896 protected $repoConfig;
32897 private $io;
32898
32899 public function __construct(array $repoConfig, IOInterface $io)
32900 {
32901 parent::__construct();
32902 if (!extension_loaded('zip')) {
32903 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
32904 }
32905
32906 $this->loader = new ArrayLoader();
32907 $this->lookup = $repoConfig['url'];
32908 $this->io = $io;
32909 $this->repoConfig = $repoConfig;
32910 }
32911
32912 public function getRepoConfig()
32913 {
32914 return $this->repoConfig;
32915 }
32916
32917 protected function initialize()
32918 {
32919 parent::initialize();
32920
32921 $this->scanDirectory($this->lookup);
32922 }
32923
32924 private function scanDirectory($path)
32925 {
32926 $io = $this->io;
32927
32928 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
32929 $iterator = new \RecursiveIteratorIterator($directory);
32930 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
32931 foreach ($regex as $file) {
32932
32933 if (!$file->isFile()) {
32934 continue;
32935 }
32936
32937 $package = $this->getComposerInformation($file);
32938 if (!$package) {
32939 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
32940 continue;
32941 }
32942
32943 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
32944 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
32945
32946 $this->addPackage($package);
32947 }
32948 }
32949
32950 private function getComposerInformation(\SplFileInfo $file)
32951 {
32952 $json = Zip::getComposerJson($file->getPathname());
32953
32954 if (null === $json) {
32955 return false;
32956 }
32957
32958 $package = JsonFile::parseJson($json, $file->getPathname().'#composer.json');
32959 $package['dist'] = array(
32960 'type' => 'zip',
32961 'url' => strtr($file->getPathname(), '\\', '/'),
32962 'shasum' => sha1_file($file->getRealPath()),
32963 );
32964
32965 try {
32966 $package = $this->loader->load($package);
32967 } catch (\UnexpectedValueException $e) {
32968 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
32969 }
32970
32971 return $package;
32972 }
32973 }
32974 <?php
32975
32976
32977
32978
32979
32980
32981
32982
32983
32984
32985
32986 namespace Composer\Repository;
32987
32988 use Composer\Package\RootPackageInterface;
32989 use Composer\Semver\Constraint\ConstraintInterface;
32990 use Composer\Semver\Constraint\Constraint;
32991 use Composer\Package\Link;
32992
32993
32994
32995
32996
32997
32998 abstract class BaseRepository implements RepositoryInterface
32999 {
33000
33001
33002
33003
33004
33005
33006
33007
33008
33009
33010
33011
33012
33013 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
33014 {
33015 $needles = array_map('strtolower', (array) $needle);
33016 $results = array();
33017
33018
33019  if (null === $packagesFound) {
33020 $packagesFound = $needles;
33021 }
33022
33023
33024  $rootPackage = null;
33025 foreach ($this->getPackages() as $package) {
33026 if ($package instanceof RootPackageInterface) {
33027 $rootPackage = $package;
33028 break;
33029 }
33030 }
33031
33032
33033  foreach ($this->getPackages() as $package) {
33034 $links = $package->getRequires();
33035
33036
33037  
33038  $packagesInTree = $packagesFound;
33039
33040
33041  if (!$invert) {
33042 $links += $package->getReplaces();
33043
33044
33045  
33046  
33047  foreach ($package->getReplaces() as $link) {
33048 foreach ($needles as $needle) {
33049 if ($link->getSource() === $needle) {
33050 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
33051
33052  if (in_array($link->getTarget(), $packagesInTree)) {
33053 $results[] = array($package, $link, false);
33054 continue;
33055 }
33056 $packagesInTree[] = $link->getTarget();
33057 $dependents = $recurse ? $this->getDependents($link->getTarget(), null, false, true, $packagesInTree) : array();
33058 $results[] = array($package, $link, $dependents);
33059 $needles[] = $link->getTarget();
33060 }
33061 }
33062 }
33063 }
33064 }
33065
33066
33067  if ($package instanceof RootPackageInterface) {
33068 $links += $package->getDevRequires();
33069 }
33070
33071
33072  foreach ($links as $link) {
33073 foreach ($needles as $needle) {
33074 if ($link->getTarget() === $needle) {
33075 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
33076
33077  if (in_array($link->getSource(), $packagesInTree)) {
33078 $results[] = array($package, $link, false);
33079 continue;
33080 }
33081 $packagesInTree[] = $link->getSource();
33082 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
33083 $results[] = array($package, $link, $dependents);
33084 }
33085 }
33086 }
33087 }
33088
33089
33090  if ($invert && in_array($package->getName(), $needles)) {
33091 foreach ($package->getConflicts() as $link) {
33092 foreach ($this->findPackages($link->getTarget()) as $pkg) {
33093 $version = new Constraint('=', $pkg->getVersion());
33094 if ($link->getConstraint()->matches($version) === $invert) {
33095 $results[] = array($package, $link, false);
33096 }
33097 }
33098 }
33099 }
33100
33101
33102  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
33103 foreach ($package->getRequires() as $link) {
33104 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
33105 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
33106 continue;
33107 }
33108
33109 $platformPkg = $this->findPackage($link->getTarget(), '*');
33110 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
33111 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
33112
33113 continue;
33114 }
33115
33116 foreach ($this->getPackages() as $pkg) {
33117 if (!in_array($link->getTarget(), $pkg->getNames())) {
33118 continue;
33119 }
33120
33121 $version = new Constraint('=', $pkg->getVersion());
33122 if (!$link->getConstraint()->matches($version)) {
33123
33124  
33125  if ($rootPackage) {
33126 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
33127 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
33128 $results[] = array($package, $link, false);
33129 $results[] = array($rootPackage, $rootReq, false);
33130 continue 3;
33131 }
33132 }
33133 $results[] = array($package, $link, false);
33134 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
33135 } else {
33136
33137  $results[] = array($package, $link, false);
33138 }
33139 }
33140
33141 continue 2;
33142 }
33143 }
33144 }
33145 }
33146
33147 ksort($results);
33148
33149 return $results;
33150 }
33151 }
33152 <?php
33153
33154
33155
33156
33157
33158
33159
33160
33161
33162
33163
33164 namespace Composer\Repository;
33165
33166 use Composer\Package\Loader\ArrayLoader;
33167 use Composer\Package\PackageInterface;
33168 use Composer\Package\AliasPackage;
33169 use Composer\Package\Version\VersionParser;
33170 use Composer\DependencyResolver\Pool;
33171 use Composer\Json\JsonFile;
33172 use Composer\Cache;
33173 use Composer\Config;
33174 use Composer\Composer;
33175 use Composer\Factory;
33176 use Composer\IO\IOInterface;
33177 use Composer\Util\RemoteFilesystem;
33178 use Composer\Plugin\PluginEvents;
33179 use Composer\Plugin\PreFileDownloadEvent;
33180 use Composer\EventDispatcher\EventDispatcher;
33181 use Composer\Downloader\TransportException;
33182 use Composer\Semver\Constraint\ConstraintInterface;
33183 use Composer\Semver\Constraint\Constraint;
33184
33185
33186
33187
33188 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33189 {
33190 protected $config;
33191 protected $repoConfig;
33192 protected $options;
33193 protected $url;
33194 protected $baseUrl;
33195 protected $io;
33196 protected $rfs;
33197 protected $cache;
33198 protected $notifyUrl;
33199 protected $searchUrl;
33200 protected $hasProviders = false;
33201 protected $providersUrl;
33202 protected $lazyProvidersUrl;
33203 protected $providerListing;
33204 protected $providers = array();
33205 protected $providersByUid = array();
33206 protected $loader;
33207 protected $rootAliases;
33208 protected $allowSslDowngrade = false;
33209 protected $eventDispatcher;
33210 protected $sourceMirrors;
33211 protected $distMirrors;
33212 private $degradedMode = false;
33213 private $rootData;
33214 private $hasPartialPackages;
33215 private $partialPackagesByName;
33216
33217 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
33218 {
33219 parent::__construct();
33220 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
33221
33222  $repoConfig['url'] = 'http://'.$repoConfig['url'];
33223 }
33224 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
33225
33226 if ('https?' === substr($repoConfig['url'], 0, 6)) {
33227 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
33228 }
33229
33230 $urlBits = parse_url($repoConfig['url']);
33231 if ($urlBits === false || empty($urlBits['scheme'])) {
33232 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
33233 }
33234
33235 if (!isset($repoConfig['options'])) {
33236 $repoConfig['options'] = array();
33237 }
33238 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
33239 $this->allowSslDowngrade = true;
33240 }
33241
33242 $this->config = $config;
33243 $this->options = $repoConfig['options'];
33244 $this->url = $repoConfig['url'];
33245
33246
33247  if (preg_match('{^(?P<proto>https?)://packagist\.org/?$}i', $this->url, $match)) {
33248 $this->url = $match['proto'].'://repo.packagist.org';
33249 }
33250
33251 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
33252 $this->io = $io;
33253 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
33254 $this->loader = new ArrayLoader();
33255 if ($rfs && $this->options) {
33256 $rfs = clone $rfs;
33257 $rfs->setOptions($this->options);
33258 }
33259 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
33260 $this->eventDispatcher = $eventDispatcher;
33261 $this->repoConfig = $repoConfig;
33262 }
33263
33264 public function getRepoConfig()
33265 {
33266 return $this->repoConfig;
33267 }
33268
33269 public function setRootAliases(array $rootAliases)
33270 {
33271 $this->rootAliases = $rootAliases;
33272 }
33273
33274
33275
33276
33277 public function findPackage($name, $constraint)
33278 {
33279 if (!$this->hasProviders()) {
33280 return parent::findPackage($name, $constraint);
33281 }
33282
33283 $name = strtolower($name);
33284 if (!$constraint instanceof ConstraintInterface) {
33285 $versionParser = new VersionParser();
33286 $constraint = $versionParser->parseConstraints($constraint);
33287 }
33288
33289 foreach ($this->getProviderNames() as $providerName) {
33290 if ($name === $providerName) {
33291 $packages = $this->whatProvides(new Pool('dev'), $providerName);
33292 foreach ($packages as $package) {
33293 if ($name === $package->getName()) {
33294 $pkgConstraint = new Constraint('==', $package->getVersion());
33295 if ($constraint->matches($pkgConstraint)) {
33296 return $package;
33297 }
33298 }
33299 }
33300 break;
33301 }
33302 }
33303 }
33304
33305
33306
33307
33308 public function findPackages($name, $constraint = null)
33309 {
33310 if (!$this->hasProviders()) {
33311 return parent::findPackages($name, $constraint);
33312 }
33313
33314  $name = strtolower($name);
33315
33316 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
33317 $versionParser = new VersionParser();
33318 $constraint = $versionParser->parseConstraints($constraint);
33319 }
33320
33321 $packages = array();
33322
33323 foreach ($this->getProviderNames() as $providerName) {
33324 if ($name === $providerName) {
33325 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
33326 foreach ($candidates as $package) {
33327 if ($name === $package->getName()) {
33328 $pkgConstraint = new Constraint('==', $package->getVersion());
33329 if (null === $constraint || $constraint->matches($pkgConstraint)) {
33330 $packages[] = $package;
33331 }
33332 }
33333 }
33334 break;
33335 }
33336 }
33337
33338 return $packages;
33339 }
33340
33341 public function getPackages()
33342 {
33343 if ($this->hasProviders()) {
33344 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
33345 }
33346
33347 return parent::getPackages();
33348 }
33349
33350
33351
33352
33353 public function search($query, $mode = 0, $type = null)
33354 {
33355 $this->loadRootServerFile();
33356
33357 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
33358 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
33359
33360 $origin = RemoteFilesystem::getOrigin($url);
33361 $json = $this->rfs->getContents($origin, $url, false);
33362 $search = JsonFile::parseJson($json, $url);
33363
33364 if (empty($search['results'])) {
33365 return array();
33366 }
33367
33368 $results = array();
33369 foreach ($search['results'] as $result) {
33370
33371  if (empty($result['virtual'])) {
33372 $results[] = $result;
33373 }
33374 }
33375
33376 return $results;
33377 }
33378
33379 if ($this->hasProviders()) {
33380 $results = array();
33381 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
33382
33383 foreach ($this->getProviderNames() as $name) {
33384 if (preg_match($regex, $name)) {
33385 $results[] = array('name' => $name);
33386 }
33387 }
33388
33389 return $results;
33390 }
33391
33392 return parent::search($query, $mode);
33393 }
33394
33395 public function getProviderNames()
33396 {
33397 $this->loadRootServerFile();
33398
33399 if (null === $this->providerListing) {
33400 $this->loadProviderListings($this->loadRootServerFile());
33401 }
33402
33403 if ($this->hasPartialPackages) {
33404 if (null === $this->partialPackagesByName) {
33405 $this->initializePartialPackages();
33406 }
33407
33408 return array_keys($this->partialPackagesByName);
33409 }
33410
33411 if ($this->lazyProvidersUrl) {
33412
33413  return array();
33414 }
33415
33416 if ($this->providersUrl) {
33417 return array_keys($this->providerListing);
33418 }
33419
33420 return array();
33421 }
33422
33423 protected function configurePackageTransportOptions(PackageInterface $package)
33424 {
33425 foreach ($package->getDistUrls() as $url) {
33426 if (strpos($url, $this->baseUrl) === 0) {
33427 $package->setTransportOptions($this->options);
33428
33429 return;
33430 }
33431 }
33432 }
33433
33434 public function hasProviders()
33435 {
33436 $this->loadRootServerFile();
33437
33438 return $this->hasProviders;
33439 }
33440
33441 public function resetPackageIds()
33442 {
33443 foreach ($this->providersByUid as $package) {
33444 if ($package instanceof AliasPackage) {
33445 $package->getAliasOf()->setId(-1);
33446 }
33447 $package->setId(-1);
33448 }
33449 }
33450
33451
33452
33453
33454
33455
33456
33457 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
33458 {
33459 if (isset($this->providers[$name]) && !$bypassFilters) {
33460 return $this->providers[$name];
33461 }
33462
33463 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
33464 $this->initializePartialPackages();
33465 }
33466
33467 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
33468
33469  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
33470 return array();
33471 }
33472
33473 if (null === $this->providerListing) {
33474 $this->loadProviderListings($this->loadRootServerFile());
33475 }
33476
33477 $useLastModifiedCheck = false;
33478 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
33479 $hash = null;
33480 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
33481 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
33482 $useLastModifiedCheck = true;
33483 } elseif ($this->providersUrl) {
33484
33485  if (!isset($this->providerListing[$name])) {
33486 return array();
33487 }
33488
33489 $hash = $this->providerListing[$name]['sha256'];
33490 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
33491 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
33492 } else {
33493 return array();
33494 }
33495
33496 $packages = null;
33497 if ($cacheKey) {
33498 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
33499 $packages = json_decode($this->cache->read($cacheKey), true);
33500 } elseif ($useLastModifiedCheck) {
33501 if ($contents = $this->cache->read($cacheKey)) {
33502 $contents = json_decode($contents, true);
33503 if (isset($contents['last-modified'])) {
33504 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
33505 if (true === $response) {
33506 $packages = $contents;
33507 } elseif ($response) {
33508 $packages = $response;
33509 }
33510 }
33511 }
33512 }
33513 }
33514
33515 if (!$packages) {
33516 try {
33517 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
33518 } catch (TransportException $e) {
33519
33520  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
33521 $packages = array('packages' => array());
33522 } else {
33523 throw $e;
33524 }
33525 }
33526 }
33527
33528 $loadingPartialPackage = false;
33529 } else {
33530 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
33531 $loadingPartialPackage = true;
33532 }
33533
33534 $this->providers[$name] = array();
33535 foreach ($packages['packages'] as $versions) {
33536 foreach ($versions as $version) {
33537 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
33538 continue;
33539 }
33540
33541
33542  if (isset($this->providersByUid[$version['uid']])) {
33543
33544  if (!isset($this->providers[$name][$version['uid']])) {
33545
33546  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
33547 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
33548 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
33549 } else {
33550 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
33551 }
33552
33553  if (isset($this->providersByUid[$version['uid'].'-root'])) {
33554 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
33555 }
33556 }
33557 } else {
33558 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
33559 continue;
33560 }
33561
33562
33563  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
33564 $package->setRepository($this);
33565
33566 if ($package instanceof AliasPackage) {
33567 $aliased = $package->getAliasOf();
33568 $aliased->setRepository($this);
33569
33570 $this->providers[$name][$version['uid']] = $aliased;
33571 $this->providers[$name][$version['uid'].'-alias'] = $package;
33572
33573
33574  $this->providersByUid[$version['uid']] = $package;
33575 } else {
33576 $this->providers[$name][$version['uid']] = $package;
33577 $this->providersByUid[$version['uid']] = $package;
33578 }
33579
33580
33581  unset($rootAliasData);
33582
33583 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
33584 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
33585 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
33586 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
33587 }
33588
33589 if (isset($rootAliasData)) {
33590 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
33591 $alias->setRepository($this);
33592
33593 $this->providers[$name][$version['uid'].'-root'] = $alias;
33594 $this->providersByUid[$version['uid'].'-root'] = $alias;
33595 }
33596 }
33597 }
33598 }
33599
33600 $result = $this->providers[$name];
33601
33602
33603  
33604  if ($bypassFilters) {
33605 foreach ($this->providers[$name] as $uid => $provider) {
33606 unset($this->providersByUid[$uid]);
33607 }
33608 unset($this->providers[$name]);
33609 }
33610
33611 return $result;
33612 }
33613
33614
33615
33616
33617 protected function initialize()
33618 {
33619 parent::initialize();
33620
33621 $repoData = $this->loadDataFromServer();
33622
33623 foreach ($repoData as $package) {
33624 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
33625 }
33626 }
33627
33628
33629
33630
33631
33632
33633 public function addPackage(PackageInterface $package)
33634 {
33635 parent::addPackage($package);
33636 $this->configurePackageTransportOptions($package);
33637 }
33638
33639 protected function loadRootServerFile()
33640 {
33641 if (null !== $this->rootData) {
33642 return $this->rootData;
33643 }
33644
33645 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
33646 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
33647 }
33648
33649 $jsonUrlParts = parse_url($this->url);
33650
33651 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
33652 $jsonUrl = $this->url;
33653 } else {
33654 $jsonUrl = $this->url . '/packages.json';
33655 }
33656
33657 $data = $this->fetchFile($jsonUrl, 'packages.json');
33658
33659 if (!empty($data['notify-batch'])) {
33660 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
33661 } elseif (!empty($data['notify'])) {
33662 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
33663 }
33664
33665 if (!empty($data['search'])) {
33666 $this->searchUrl = $this->canonicalizeUrl($data['search']);
33667 }
33668
33669 if (!empty($data['mirrors'])) {
33670 foreach ($data['mirrors'] as $mirror) {
33671 if (!empty($mirror['git-url'])) {
33672 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
33673 }
33674 if (!empty($mirror['hg-url'])) {
33675 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
33676 }
33677 if (!empty($mirror['dist-url'])) {
33678 $this->distMirrors[] = array(
33679 'url' => $this->canonicalizeUrl($mirror['dist-url']),
33680 'preferred' => !empty($mirror['preferred']),
33681 );
33682 }
33683 }
33684 }
33685
33686 if (!empty($data['providers-lazy-url'])) {
33687 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
33688 $this->hasProviders = true;
33689
33690 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
33691 }
33692
33693 if ($this->allowSslDowngrade) {
33694 $this->url = str_replace('https://', 'http://', $this->url);
33695 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
33696 }
33697
33698 if (!empty($data['providers-url'])) {
33699 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
33700 $this->hasProviders = true;
33701 }
33702
33703 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
33704 $this->hasProviders = true;
33705 }
33706
33707
33708  if (preg_match('{^https?://repo\.packagist\.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
33709 $this->url = 'https://repo.packagist.org';
33710 $this->baseUrl = 'https://repo.packagist.org';
33711 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://repo.packagist.org/p/%package%.json');
33712 $this->providersUrl = null;
33713 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
33714 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
33715 $this->providersUrl = null;
33716 }
33717
33718 return $this->rootData = $data;
33719 }
33720
33721 protected function canonicalizeUrl($url)
33722 {
33723 if ('/' === $url[0]) {
33724 if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) {
33725 return $matches[0] . $url;
33726 }
33727
33728 return $this->url;
33729 }
33730
33731 return $url;
33732 }
33733
33734 protected function loadDataFromServer()
33735 {
33736 $data = $this->loadRootServerFile();
33737
33738 return $this->loadIncludes($data);
33739 }
33740
33741 protected function loadProviderListings($data)
33742 {
33743 if (isset($data['providers'])) {
33744 if (!is_array($this->providerListing)) {
33745 $this->providerListing = array();
33746 }
33747 $this->providerListing = array_merge($this->providerListing, $data['providers']);
33748 }
33749
33750 if ($this->providersUrl && isset($data['provider-includes'])) {
33751 $includes = $data['provider-includes'];
33752 foreach ($includes as $include => $metadata) {
33753 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
33754 $cacheKey = str_replace(array('%hash%','$'), '', $include);
33755 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
33756 $includedData = json_decode($this->cache->read($cacheKey), true);
33757 } else {
33758 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
33759 }
33760
33761 $this->loadProviderListings($includedData);
33762 }
33763 }
33764 }
33765
33766 protected function loadIncludes($data)
33767 {
33768 $packages = array();
33769
33770
33771  if (!isset($data['packages']) && !isset($data['includes'])) {
33772 foreach ($data as $pkg) {
33773 foreach ($pkg['versions'] as $metadata) {
33774 $packages[] = $metadata;
33775 }
33776 }
33777
33778 return $packages;
33779 }
33780
33781 if (isset($data['packages'])) {
33782 foreach ($data['packages'] as $package => $versions) {
33783 foreach ($versions as $version => $metadata) {
33784 $packages[] = $metadata;
33785 }
33786 }
33787 }
33788
33789 if (isset($data['includes'])) {
33790 foreach ($data['includes'] as $include => $metadata) {
33791 if ($this->cache->sha1($include) === $metadata['sha1']) {
33792 $includedData = json_decode($this->cache->read($include), true);
33793 } else {
33794 $includedData = $this->fetchFile($include);
33795 }
33796 $packages = array_merge($packages, $this->loadIncludes($includedData));
33797 }
33798 }
33799
33800 return $packages;
33801 }
33802
33803 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
33804 {
33805 try {
33806 if (!isset($data['notification-url'])) {
33807 $data['notification-url'] = $this->notifyUrl;
33808 }
33809
33810 $package = $this->loader->load($data, $class);
33811 if (isset($this->sourceMirrors[$package->getSourceType()])) {
33812 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
33813 }
33814 $package->setDistMirrors($this->distMirrors);
33815 $this->configurePackageTransportOptions($package);
33816
33817 return $package;
33818 } catch (\Exception $e) {
33819 throw new \RuntimeException('Could not load package '.(isset($data['name']) ? $data['name'] : json_encode($data)).' in '.$this->url.': ['.get_class($e).'] '.$e->getMessage(), 0, $e);
33820 }
33821 }
33822
33823 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
33824 {
33825 if (null === $cacheKey) {
33826 $cacheKey = $filename;
33827 $filename = $this->baseUrl.'/'.$filename;
33828 }
33829
33830
33831  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
33832 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
33833 }
33834
33835 $retries = 3;
33836 while ($retries--) {
33837 try {
33838 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
33839 if ($this->eventDispatcher) {
33840 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
33841 }
33842
33843 $origin = RemoteFilesystem::getOrigin($filename);
33844 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
33845
33846 $json = $rfs->getContents($origin, $filename, false);
33847 if ($sha256 && $sha256 !== hash('sha256', $json)) {
33848
33849  if ($this->allowSslDowngrade) {
33850 $this->url = str_replace('http://', 'https://', $this->url);
33851 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
33852 $filename = str_replace('http://', 'https://', $filename);
33853 }
33854
33855 if ($retries) {
33856 usleep(100000);
33857
33858 continue;
33859 }
33860
33861
33862  throw new 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.');
33863 }
33864
33865 $data = JsonFile::parseJson($json, $filename);
33866 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
33867
33868 if ($cacheKey) {
33869 if ($storeLastModifiedTime) {
33870 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
33871 if ($lastModifiedDate) {
33872 $data['last-modified'] = $lastModifiedDate;
33873 $json = json_encode($data);
33874 }
33875 }
33876 $this->cache->write($cacheKey, $json);
33877 }
33878
33879 break;
33880 } catch (\Exception $e) {
33881 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
33882 throw $e;
33883 }
33884
33885 if ($retries) {
33886 usleep(100000);
33887 continue;
33888 }
33889
33890 if ($e instanceof RepositorySecurityException) {
33891 throw $e;
33892 }
33893
33894 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
33895 if (!$this->degradedMode) {
33896 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
33897 $this->io->writeError('<warning>'.$this->url.' could not be fully loaded, package information was loaded from the local cache and may be out of date</warning>');
33898 }
33899 $this->degradedMode = true;
33900 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
33901
33902 break;
33903 }
33904
33905 throw $e;
33906 }
33907 }
33908
33909 return $data;
33910 }
33911
33912 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
33913 {
33914 $retries = 3;
33915 while ($retries--) {
33916 try {
33917 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
33918 if ($this->eventDispatcher) {
33919 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
33920 }
33921
33922 $origin = RemoteFilesystem::getOrigin($filename);
33923 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
33924 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
33925 $json = $rfs->getContents($origin, $filename, false, $options);
33926 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
33927 return true;
33928 }
33929
33930 $data = JsonFile::parseJson($json, $filename);
33931 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
33932
33933 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
33934 if ($lastModifiedDate) {
33935 $data['last-modified'] = $lastModifiedDate;
33936 $json = json_encode($data);
33937 }
33938 $this->cache->write($cacheKey, $json);
33939
33940 return $data;
33941 } catch (\Exception $e) {
33942 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
33943 throw $e;
33944 }
33945
33946 if ($retries) {
33947 usleep(100000);
33948 continue;
33949 }
33950
33951 if (!$this->degradedMode) {
33952 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
33953 $this->io->writeError('<warning>'.$this->url.' could not be fully loaded, package information was loaded from the local cache and may be out of date</warning>');
33954 }
33955 $this->degradedMode = true;
33956
33957 return true;
33958 }
33959 }
33960 }
33961
33962
33963
33964
33965
33966
33967 private function initializePartialPackages()
33968 {
33969 $rootData = $this->loadRootServerFile();
33970
33971 $this->partialPackagesByName = array();
33972 foreach ($rootData['packages'] as $package => $versions) {
33973 $package = strtolower($package);
33974 foreach ($versions as $version) {
33975 $this->partialPackagesByName[$package][] = $version;
33976 if (!empty($version['provide']) && is_array($version['provide'])) {
33977 foreach ($version['provide'] as $provided => $providedVersion) {
33978 $this->partialPackagesByName[strtolower($provided)][] = $version;
33979 }
33980 }
33981 if (!empty($version['replace']) && is_array($version['replace'])) {
33982 foreach ($version['replace'] as $provided => $providedVersion) {
33983 $this->partialPackagesByName[strtolower($provided)][] = $version;
33984 }
33985 }
33986 }
33987 }
33988
33989
33990  $this->rootData = true;
33991 }
33992 }
33993 <?php
33994
33995
33996
33997
33998
33999
34000
34001
34002
34003
34004
34005 namespace Composer\Repository;
34006
34007 use Composer\Package\PackageInterface;
34008
34009
34010
34011
34012
34013
34014 class CompositeRepository extends BaseRepository
34015 {
34016
34017
34018
34019
34020 private $repositories;
34021
34022
34023
34024
34025
34026 public function __construct(array $repositories)
34027 {
34028 $this->repositories = array();
34029 foreach ($repositories as $repo) {
34030 $this->addRepository($repo);
34031 }
34032 }
34033
34034
34035
34036
34037
34038
34039 public function getRepositories()
34040 {
34041 return $this->repositories;
34042 }
34043
34044
34045
34046
34047 public function hasPackage(PackageInterface $package)
34048 {
34049 foreach ($this->repositories as $repository) {
34050
34051 if ($repository->hasPackage($package)) {
34052 return true;
34053 }
34054 }
34055
34056 return false;
34057 }
34058
34059
34060
34061
34062 public function findPackage($name, $constraint)
34063 {
34064 foreach ($this->repositories as $repository) {
34065
34066 $package = $repository->findPackage($name, $constraint);
34067 if (null !== $package) {
34068 return $package;
34069 }
34070 }
34071
34072 return null;
34073 }
34074
34075
34076
34077
34078 public function findPackages($name, $constraint = null)
34079 {
34080 $packages = array();
34081 foreach ($this->repositories as $repository) {
34082
34083 $packages[] = $repository->findPackages($name, $constraint);
34084 }
34085
34086 return $packages ? call_user_func_array('array_merge', $packages) : array();
34087 }
34088
34089
34090
34091
34092 public function search($query, $mode = 0, $type = null)
34093 {
34094 $matches = array();
34095 foreach ($this->repositories as $repository) {
34096
34097 $matches[] = $repository->search($query, $mode, $type);
34098 }
34099
34100 return $matches ? call_user_func_array('array_merge', $matches) : array();
34101 }
34102
34103
34104
34105
34106 public function getPackages()
34107 {
34108 $packages = array();
34109 foreach ($this->repositories as $repository) {
34110
34111 $packages[] = $repository->getPackages();
34112 }
34113
34114 return $packages ? call_user_func_array('array_merge', $packages) : array();
34115 }
34116
34117
34118
34119
34120 public function removePackage(PackageInterface $package)
34121 {
34122 foreach ($this->repositories as $repository) {
34123
34124 $repository->removePackage($package);
34125 }
34126 }
34127
34128
34129
34130
34131 public function count()
34132 {
34133 $total = 0;
34134 foreach ($this->repositories as $repository) {
34135
34136 $total += $repository->count();
34137 }
34138
34139 return $total;
34140 }
34141
34142
34143
34144
34145
34146 public function addRepository(RepositoryInterface $repository)
34147 {
34148 if ($repository instanceof self) {
34149 foreach ($repository->getRepositories() as $repo) {
34150 $this->addRepository($repo);
34151 }
34152 } else {
34153 $this->repositories[] = $repository;
34154 }
34155 }
34156 }
34157 <?php
34158
34159
34160
34161
34162
34163
34164
34165
34166
34167
34168
34169 namespace Composer\Repository;
34170
34171
34172
34173
34174
34175
34176 interface ConfigurableRepositoryInterface
34177 {
34178 public function getRepoConfig();
34179 }
34180 <?php
34181
34182
34183
34184
34185
34186
34187
34188
34189
34190
34191
34192 namespace Composer\Repository;
34193
34194 use Composer\Json\JsonFile;
34195 use Composer\Package\Loader\ArrayLoader;
34196 use Composer\Package\Dumper\ArrayDumper;
34197
34198
34199
34200
34201
34202
34203
34204 class FilesystemRepository extends WritableArrayRepository
34205 {
34206 private $file;
34207
34208
34209
34210
34211
34212
34213 public function __construct(JsonFile $repositoryFile)
34214 {
34215 parent::__construct();
34216 $this->file = $repositoryFile;
34217 }
34218
34219
34220
34221
34222 protected function initialize()
34223 {
34224 parent::initialize();
34225
34226 if (!$this->file->exists()) {
34227 return;
34228 }
34229
34230 try {
34231 $packages = $this->file->read();
34232
34233
34234  if (isset($packages['packages'])) {
34235 $packages = $packages['packages'];
34236 }
34237
34238 if (!is_array($packages)) {
34239 throw new \UnexpectedValueException('Could not parse package list from the repository');
34240 }
34241 } catch (\Exception $e) {
34242 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
34243 }
34244
34245 $loader = new ArrayLoader(null, true);
34246 foreach ($packages as $packageData) {
34247 $package = $loader->load($packageData);
34248 $this->addPackage($package);
34249 }
34250 }
34251
34252 public function reload()
34253 {
34254 $this->packages = null;
34255 $this->initialize();
34256 }
34257
34258
34259
34260
34261 public function write()
34262 {
34263 $data = array();
34264 $dumper = new ArrayDumper();
34265
34266 foreach ($this->getCanonicalPackages() as $package) {
34267 $data[] = $dumper->dump($package);
34268 }
34269
34270 usort($data, function ($a, $b) {
34271 return strcmp($a['name'], $b['name']);
34272 });
34273
34274 $this->file->write($data);
34275 }
34276 }
34277 <?php
34278
34279
34280
34281
34282
34283
34284
34285
34286
34287
34288
34289 namespace Composer\Repository;
34290
34291
34292
34293
34294
34295
34296
34297
34298 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
34299 {
34300 }
34301 <?php
34302
34303
34304
34305
34306
34307
34308
34309
34310
34311
34312
34313 namespace Composer\Repository;
34314
34315
34316
34317
34318
34319
34320 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
34321 {
34322 }
34323 <?php
34324
34325
34326
34327
34328
34329
34330
34331
34332
34333
34334
34335 namespace Composer\Repository;
34336
34337
34338
34339
34340
34341
34342
34343
34344 interface InstalledRepositoryInterface extends WritableRepositoryInterface
34345 {
34346 }
34347 <?php
34348
34349
34350
34351
34352
34353
34354
34355
34356
34357
34358
34359 namespace Composer\Repository;
34360
34361
34362
34363
34364
34365
34366 class InvalidRepositoryException extends \Exception
34367 {
34368 }
34369 <?php
34370
34371
34372
34373
34374
34375
34376
34377
34378
34379
34380
34381 namespace Composer\Repository;
34382
34383 use Composer\Package\Loader\ArrayLoader;
34384 use Composer\Package\Loader\ValidatingArrayLoader;
34385
34386
34387
34388
34389
34390
34391 class PackageRepository extends ArrayRepository
34392 {
34393 private $config;
34394
34395
34396
34397
34398
34399
34400 public function __construct(array $config)
34401 {
34402 parent::__construct();
34403 $this->config = $config['package'];
34404
34405
34406  if (!is_numeric(key($this->config))) {
34407 $this->config = array($this->config);
34408 }
34409 }
34410
34411
34412
34413
34414 protected function initialize()
34415 {
34416 parent::initialize();
34417
34418 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
34419 foreach ($this->config as $package) {
34420 try {
34421 $package = $loader->load($package);
34422 } catch (\Exception $e) {
34423 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
34424 }
34425
34426 $this->addPackage($package);
34427 }
34428 }
34429 }
34430 <?php
34431
34432
34433
34434
34435
34436
34437
34438
34439
34440
34441
34442 namespace Composer\Repository;
34443
34444 use Composer\Config;
34445 use Composer\IO\IOInterface;
34446 use Composer\Json\JsonFile;
34447 use Composer\Package\Loader\ArrayLoader;
34448 use Composer\Package\Version\VersionGuesser;
34449 use Composer\Package\Version\VersionParser;
34450 use Composer\Util\Platform;
34451 use Composer\Util\ProcessExecutor;
34452
34453
34454
34455
34456
34457
34458
34459
34460
34461
34462
34463
34464
34465
34466
34467
34468
34469
34470
34471
34472
34473
34474
34475
34476
34477
34478
34479
34480
34481
34482
34483
34484
34485
34486
34487
34488 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
34489 {
34490
34491
34492
34493 private $loader;
34494
34495
34496
34497
34498 private $versionGuesser;
34499
34500
34501
34502
34503 private $url;
34504
34505
34506
34507
34508 private $repoConfig;
34509
34510
34511
34512
34513 private $process;
34514
34515
34516
34517
34518 private $options;
34519
34520
34521
34522
34523
34524
34525
34526
34527 public function __construct(array $repoConfig, IOInterface $io, Config $config)
34528 {
34529 if (!isset($repoConfig['url'])) {
34530 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
34531 }
34532
34533 $this->loader = new ArrayLoader(null, true);
34534 $this->url = Platform::expandPath($repoConfig['url']);
34535 $this->process = new ProcessExecutor($io);
34536 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
34537 $this->repoConfig = $repoConfig;
34538 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
34539
34540 parent::__construct();
34541 }
34542
34543 public function getRepoConfig()
34544 {
34545 return $this->repoConfig;
34546 }
34547
34548
34549
34550
34551
34552
34553 protected function initialize()
34554 {
34555 parent::initialize();
34556
34557 foreach ($this->getUrlMatches() as $url) {
34558 $path = realpath($url) . DIRECTORY_SEPARATOR;
34559 $composerFilePath = $path.'composer.json';
34560
34561 if (!file_exists($composerFilePath)) {
34562 continue;
34563 }
34564
34565 $json = file_get_contents($composerFilePath);
34566 $package = JsonFile::parseJson($json, $composerFilePath);
34567 $package['dist'] = array(
34568 'type' => 'path',
34569 'url' => $url,
34570 'reference' => sha1($json . serialize($this->options)),
34571 );
34572 $package['transport-options'] = $this->options;
34573
34574
34575  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
34576 if (
34577 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
34578 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
34579 && $ref1 === $ref2
34580 ) {
34581 $package['version'] = $rootVersion;
34582 }
34583 }
34584
34585 $output = '';
34586 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
34587 $package['dist']['reference'] = trim($output);
34588 }
34589
34590 if (!isset($package['version'])) {
34591 $versionData = $this->versionGuesser->guessVersion($package, $path);
34592 if (is_array($versionData) && $versionData['pretty_version']) {
34593
34594  if (!empty($versionData['feature_pretty_version'])) {
34595 $package['version'] = $versionData['feature_pretty_version'];
34596 $this->addPackage($this->loader->load($package));
34597 }
34598
34599 $package['version'] = $versionData['pretty_version'];
34600 } else {
34601 $package['version'] = 'dev-master';
34602 }
34603 }
34604
34605 $package = $this->loader->load($package);
34606 $this->addPackage($package);
34607 }
34608 }
34609
34610
34611
34612
34613
34614
34615 private function getUrlMatches()
34616 {
34617 $flags = GLOB_MARK | GLOB_ONLYDIR;
34618
34619 if (defined('GLOB_BRACE')) {
34620 $flags |= GLOB_BRACE;
34621 } elseif (strpos($this->url, '{') !== false || strpos($this->url, '}') !== false) {
34622 throw new \RuntimeException('The operating system does not support GLOB_BRACE which is required for the url '. $this->url);
34623 }
34624
34625
34626  return array_map(function ($val) {
34627 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
34628 }, glob($this->url, $flags));
34629 }
34630 }
34631 <?php
34632
34633
34634
34635
34636
34637
34638
34639
34640
34641
34642
34643 namespace Composer\Repository\Pear;
34644
34645 use Composer\Util\RemoteFilesystem;
34646
34647
34648
34649
34650
34651
34652
34653
34654 abstract class BaseChannelReader
34655 {
34656
34657
34658
34659 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
34660 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
34661 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
34662 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
34663 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
34664 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
34665
34666
34667 private $rfs;
34668
34669 protected function __construct(RemoteFilesystem $rfs)
34670 {
34671 $this->rfs = $rfs;
34672 }
34673
34674
34675
34676
34677
34678
34679
34680
34681
34682 protected function requestContent($origin, $path)
34683 {
34684 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
34685 $content = $this->rfs->getContents($origin, $url, false);
34686 if (!$content) {
34687 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
34688 }
34689
34690 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
34691 }
34692
34693
34694
34695
34696
34697
34698
34699
34700
34701 protected function requestXml($origin, $path)
34702 {
34703
34704  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
34705
34706 if (false === $xml) {
34707 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
34708 }
34709
34710 return $xml;
34711 }
34712 }
34713 <?php
34714
34715
34716
34717
34718
34719
34720
34721
34722
34723
34724
34725 namespace Composer\Repository\Pear;
34726
34727
34728
34729
34730
34731
34732 class ChannelInfo
34733 {
34734 private $name;
34735 private $alias;
34736 private $packages;
34737
34738
34739
34740
34741
34742
34743 public function __construct($name, $alias, array $packages)
34744 {
34745 $this->name = $name;
34746 $this->alias = $alias;
34747 $this->packages = $packages;
34748 }
34749
34750
34751
34752
34753
34754
34755 public function getName()
34756 {
34757 return $this->name;
34758 }
34759
34760
34761
34762
34763
34764
34765 public function getAlias()
34766 {
34767 return $this->alias;
34768 }
34769
34770
34771
34772
34773
34774
34775 public function getPackages()
34776 {
34777 return $this->packages;
34778 }
34779 }
34780 <?php
34781
34782
34783
34784
34785
34786
34787
34788
34789
34790
34791
34792 namespace Composer\Repository\Pear;
34793
34794 use Composer\Util\RemoteFilesystem;
34795
34796
34797
34798
34799
34800
34801
34802
34803 class ChannelReader extends BaseChannelReader
34804 {
34805
34806 private $readerMap;
34807
34808 public function __construct(RemoteFilesystem $rfs)
34809 {
34810 parent::__construct($rfs);
34811
34812 $rest10reader = new ChannelRest10Reader($rfs);
34813 $rest11reader = new ChannelRest11Reader($rfs);
34814
34815 $this->readerMap = array(
34816 'REST1.3' => $rest11reader,
34817 'REST1.2' => $rest11reader,
34818 'REST1.1' => $rest11reader,
34819 'REST1.0' => $rest10reader,
34820 );
34821 }
34822
34823
34824
34825
34826
34827
34828
34829
34830 public function read($url)
34831 {
34832 $xml = $this->requestXml($url, "/channel.xml");
34833
34834 $channelName = (string) $xml->name;
34835 $channelAlias = (string) $xml->suggestedalias;
34836
34837 $supportedVersions = array_keys($this->readerMap);
34838 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
34839 if (!$selectedRestVersion) {
34840 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
34841 }
34842
34843 $reader = $this->readerMap[$selectedRestVersion['version']];
34844 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
34845
34846 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
34847 }
34848
34849
34850
34851
34852
34853
34854
34855
34856 private function selectRestVersion($channelXml, $supportedVersions)
34857 {
34858 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
34859
34860 foreach ($supportedVersions as $version) {
34861 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
34862 $testResult = $channelXml->xpath($xpathTest);
34863
34864 foreach ($testResult as $result) {
34865
34866  $result = (string) $result;
34867 if (preg_match('{^https://}i', $result)) {
34868 return array('version' => $version, 'baseUrl' => $result);
34869 }
34870 }
34871
34872
34873  if (count($testResult) > 0) {
34874 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
34875 }
34876 }
34877
34878 return null;
34879 }
34880 }
34881 <?php
34882
34883
34884
34885
34886
34887
34888
34889
34890
34891
34892
34893 namespace Composer\Repository\Pear;
34894
34895 use Composer\Downloader\TransportException;
34896
34897
34898
34899
34900
34901
34902
34903
34904
34905
34906
34907
34908 class ChannelRest10Reader extends BaseChannelReader
34909 {
34910 private $dependencyReader;
34911
34912 public function __construct($rfs)
34913 {
34914 parent::__construct($rfs);
34915
34916 $this->dependencyReader = new PackageDependencyParser();
34917 }
34918
34919
34920
34921
34922
34923
34924
34925
34926 public function read($baseUrl)
34927 {
34928 return $this->readPackages($baseUrl);
34929 }
34930
34931
34932
34933
34934
34935
34936
34937
34938 private function readPackages($baseUrl)
34939 {
34940 $result = array();
34941
34942 $xmlPath = '/p/packages.xml';
34943 $xml = $this->requestXml($baseUrl, $xmlPath);
34944 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
34945 foreach ($xml->xpath('ns:p') as $node) {
34946 $packageName = (string) $node;
34947 $packageInfo = $this->readPackage($baseUrl, $packageName);
34948 $result[] = $packageInfo;
34949 }
34950
34951 return $result;
34952 }
34953
34954
34955
34956
34957
34958
34959
34960
34961
34962 private function readPackage($baseUrl, $packageName)
34963 {
34964 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
34965 $xml = $this->requestXml($baseUrl, $xmlPath);
34966 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
34967
34968 $channelName = (string) $xml->c;
34969 $packageName = (string) $xml->n;
34970 $license = (string) $xml->l;
34971 $shortDescription = (string) $xml->s;
34972 $description = (string) $xml->d;
34973
34974 return new PackageInfo(
34975 $channelName,
34976 $packageName,
34977 $license,
34978 $shortDescription,
34979 $description,
34980 $this->readPackageReleases($baseUrl, $packageName)
34981 );
34982 }
34983
34984
34985
34986
34987
34988
34989
34990
34991
34992
34993 private function readPackageReleases($baseUrl, $packageName)
34994 {
34995 $result = array();
34996
34997 try {
34998 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
34999 $xml = $this->requestXml($baseUrl, $xmlPath);
35000 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
35001 foreach ($xml->xpath('ns:r') as $node) {
35002 $releaseVersion = (string) $node->v;
35003 $releaseStability = (string) $node->s;
35004
35005 try {
35006 $result[$releaseVersion] = new ReleaseInfo(
35007 $releaseStability,
35008 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
35009 );
35010 } catch (TransportException $exception) {
35011 if ($exception->getCode() != 404) {
35012 throw $exception;
35013 }
35014 }
35015 }
35016 } catch (TransportException $exception) {
35017 if ($exception->getCode() != 404) {
35018 throw $exception;
35019 }
35020 }
35021
35022 return $result;
35023 }
35024
35025
35026
35027
35028
35029
35030
35031
35032
35033
35034 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
35035 {
35036 $dependencyReader = new PackageDependencyParser();
35037
35038 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
35039 $content = $this->requestContent($baseUrl, $depthPath);
35040 $dependencyArray = unserialize($content);
35041
35042 return $dependencyReader->buildDependencyInfo($dependencyArray);
35043 }
35044 }
35045 <?php
35046
35047
35048
35049
35050
35051
35052
35053
35054
35055
35056
35057 namespace Composer\Repository\Pear;
35058
35059
35060
35061
35062
35063
35064
35065
35066
35067
35068 class ChannelRest11Reader extends BaseChannelReader
35069 {
35070 private $dependencyReader;
35071
35072 public function __construct($rfs)
35073 {
35074 parent::__construct($rfs);
35075
35076 $this->dependencyReader = new PackageDependencyParser();
35077 }
35078
35079
35080
35081
35082
35083
35084
35085
35086 public function read($baseUrl)
35087 {
35088 return $this->readChannelPackages($baseUrl);
35089 }
35090
35091
35092
35093
35094
35095
35096
35097
35098 private function readChannelPackages($baseUrl)
35099 {
35100 $result = array();
35101
35102 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
35103 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
35104 foreach ($xml->xpath('ns:c') as $node) {
35105 $categoryName = (string) $node;
35106 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
35107 $result = array_merge($result, $categoryPackages);
35108 }
35109
35110 return $result;
35111 }
35112
35113
35114
35115
35116
35117
35118
35119
35120
35121 private function readCategoryPackages($baseUrl, $categoryName)
35122 {
35123 $result = array();
35124
35125 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
35126 $xml = $this->requestXml($baseUrl, $categoryPath);
35127 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
35128 foreach ($xml->xpath('ns:pi') as $node) {
35129 $packageInfo = $this->parsePackage($node);
35130 $result[] = $packageInfo;
35131 }
35132
35133 return $result;
35134 }
35135
35136
35137
35138
35139
35140
35141
35142 private function parsePackage($packageInfo)
35143 {
35144 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
35145 $channelName = (string) $packageInfo->p->c;
35146 $packageName = (string) $packageInfo->p->n;
35147 $license = (string) $packageInfo->p->l;
35148 $shortDescription = (string) $packageInfo->p->s;
35149 $description = (string) $packageInfo->p->d;
35150
35151 $dependencies = array();
35152 foreach ($packageInfo->xpath('ns:deps') as $node) {
35153 $dependencyVersion = (string) $node->v;
35154 $dependencyArray = unserialize((string) $node->d);
35155
35156 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
35157
35158 $dependencies[$dependencyVersion] = $dependencyInfo;
35159 }
35160
35161 $releases = array();
35162 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
35163 if ($releasesInfo) {
35164 foreach ($releasesInfo as $node) {
35165 $releaseVersion = (string) $node->v;
35166 $releaseStability = (string) $node->s;
35167 $releases[$releaseVersion] = new ReleaseInfo(
35168 $releaseStability,
35169 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
35170 );
35171 }
35172 }
35173
35174 return new PackageInfo(
35175 $channelName,
35176 $packageName,
35177 $license,
35178 $shortDescription,
35179 $description,
35180 $releases
35181 );
35182 }
35183 }
35184 <?php
35185
35186
35187
35188
35189
35190
35191
35192
35193
35194
35195
35196 namespace Composer\Repository\Pear;
35197
35198
35199
35200
35201
35202
35203 class DependencyConstraint
35204 {
35205 private $type;
35206 private $constraint;
35207 private $channelName;
35208 private $packageName;
35209
35210
35211
35212
35213
35214
35215
35216 public function __construct($type, $constraint, $channelName, $packageName)
35217 {
35218 $this->type = $type;
35219 $this->constraint = $constraint;
35220 $this->channelName = $channelName;
35221 $this->packageName = $packageName;
35222 }
35223
35224 public function getChannelName()
35225 {
35226 return $this->channelName;
35227 }
35228
35229 public function getConstraint()
35230 {
35231 return $this->constraint;
35232 }
35233
35234 public function getPackageName()
35235 {
35236 return $this->packageName;
35237 }
35238
35239 public function getType()
35240 {
35241 return $this->type;
35242 }
35243 }
35244 <?php
35245
35246
35247
35248
35249
35250
35251
35252
35253
35254
35255
35256 namespace Composer\Repository\Pear;
35257
35258
35259
35260
35261
35262
35263 class DependencyInfo
35264 {
35265 private $requires;
35266 private $optionals;
35267
35268
35269
35270
35271
35272 public function __construct($requires, $optionals)
35273 {
35274 $this->requires = $requires;
35275 $this->optionals = $optionals;
35276 }
35277
35278
35279
35280
35281 public function getRequires()
35282 {
35283 return $this->requires;
35284 }
35285
35286
35287
35288
35289 public function getOptionals()
35290 {
35291 return $this->optionals;
35292 }
35293 }
35294 <?php
35295
35296
35297
35298
35299
35300
35301
35302
35303
35304
35305
35306 namespace Composer\Repository\Pear;
35307
35308
35309
35310
35311
35312
35313 class PackageDependencyParser
35314 {
35315
35316
35317
35318
35319
35320
35321 public function buildDependencyInfo($depArray)
35322 {
35323 if (!is_array($depArray)) {
35324 return new DependencyInfo(array(), array());
35325 }
35326 if (!$this->isHash($depArray)) {
35327 return new DependencyInfo($this->buildDependency10Info($depArray), array());
35328 }
35329
35330 return $this->buildDependency20Info($depArray);
35331 }
35332
35333
35334
35335
35336
35337
35338
35339
35340
35341
35342
35343
35344
35345 private function buildDependency10Info($depArray)
35346 {
35347 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
35348
35349 $result = array();
35350
35351 foreach ($depArray as $depItem) {
35352 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
35353
35354  continue;
35355 }
35356
35357 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
35358 ? 'optional'
35359 : 'required';
35360 $depType = 'not' == $depItem['rel']
35361 ? 'conflicts'
35362 : $depType;
35363
35364 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
35365
35366
35367  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
35368 ? '*'
35369 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
35370
35371 switch ($depItem['type']) {
35372 case 'php':
35373 $depChannelName = 'php';
35374 $depPackageName = '';
35375 break;
35376 case 'pkg':
35377 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
35378 $depPackageName = $depItem['name'];
35379 break;
35380 case 'ext':
35381 $depChannelName = 'ext';
35382 $depPackageName = $depItem['name'];
35383 break;
35384 case 'os':
35385 case 'sapi':
35386 $depChannelName = '';
35387 $depPackageName = '';
35388 break;
35389 default:
35390 $depChannelName = '';
35391 $depPackageName = '';
35392 break;
35393 }
35394
35395 if ('' != $depChannelName) {
35396 $result[] = new DependencyConstraint(
35397 $depType,
35398 $depVersionConstraint,
35399 $depChannelName,
35400 $depPackageName
35401 );
35402 }
35403 }
35404
35405 return $result;
35406 }
35407
35408
35409
35410
35411
35412
35413
35414 private function buildDependency20Info($depArray)
35415 {
35416 $result = array();
35417 $optionals = array();
35418 $defaultOptionals = array();
35419 foreach ($depArray as $depType => $depTypeGroup) {
35420 if (!is_array($depTypeGroup)) {
35421 continue;
35422 }
35423 if ('required' == $depType || 'optional' == $depType) {
35424 foreach ($depTypeGroup as $depItemType => $depItem) {
35425 switch ($depItemType) {
35426 case 'php':
35427 $result[] = new DependencyConstraint(
35428 $depType,
35429 $this->parse20VersionConstraint($depItem),
35430 'php',
35431 ''
35432 );
35433 break;
35434 case 'package':
35435 $deps = $this->buildDepPackageConstraints($depItem, $depType);
35436 $result = array_merge($result, $deps);
35437 break;
35438 case 'extension':
35439 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
35440 $result = array_merge($result, $deps);
35441 break;
35442 case 'subpackage':
35443 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
35444 $defaultOptionals += $deps;
35445 break;
35446 case 'os':
35447 case 'pearinstaller':
35448 break;
35449 default:
35450 break;
35451 }
35452 }
35453 } elseif ('group' == $depType) {
35454 if ($this->isHash($depTypeGroup)) {
35455 $depTypeGroup = array($depTypeGroup);
35456 }
35457
35458 foreach ($depTypeGroup as $depItem) {
35459 $groupName = $depItem['attribs']['name'];
35460 if (!isset($optionals[$groupName])) {
35461 $optionals[$groupName] = array();
35462 }
35463
35464 if (isset($depItem['subpackage'])) {
35465 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
35466 } else {
35467 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
35468 }
35469 }
35470 }
35471 }
35472
35473 if (count($defaultOptionals) > 0) {
35474 $optionals['*'] = $defaultOptionals;
35475 }
35476
35477 return new DependencyInfo($result, $optionals);
35478 }
35479
35480
35481
35482
35483
35484
35485
35486
35487 private function buildDepExtensionConstraints($depItem, $depType)
35488 {
35489 if ($this->isHash($depItem)) {
35490 $depItem = array($depItem);
35491 }
35492
35493 $result = array();
35494 foreach ($depItem as $subDepItem) {
35495 $depChannelName = 'ext';
35496 $depPackageName = $subDepItem['name'];
35497 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
35498
35499 $result[] = new DependencyConstraint(
35500 $depType,
35501 $depVersionConstraint,
35502 $depChannelName,
35503 $depPackageName
35504 );
35505 }
35506
35507 return $result;
35508 }
35509
35510
35511
35512
35513
35514
35515
35516
35517 private function buildDepPackageConstraints($depItem, $depType)
35518 {
35519 if ($this->isHash($depItem)) {
35520 $depItem = array($depItem);
35521 }
35522
35523 $result = array();
35524 foreach ($depItem as $subDepItem) {
35525 if (!array_key_exists('channel', $subDepItem)) {
35526 $subDepItem['channel'] = $subDepItem['uri'];
35527 }
35528 $depChannelName = $subDepItem['channel'];
35529 $depPackageName = $subDepItem['name'];
35530 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
35531 if (isset($subDepItem['conflicts'])) {
35532 $depType = 'conflicts';
35533 }
35534
35535 $result[] = new DependencyConstraint(
35536 $depType,
35537 $depVersionConstraint,
35538 $depChannelName,
35539 $depPackageName
35540 );
35541 }
35542
35543 return $result;
35544 }
35545
35546
35547
35548
35549
35550
35551
35552 private function parse20VersionConstraint(array $data)
35553 {
35554 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
35555
35556 $versions = array();
35557 $values = array_intersect_key($data, $dep20toOperatorMap);
35558 if (0 == count($values)) {
35559 return '*';
35560 }
35561 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
35562 $versions[] = '>' . $this->parseVersion($values['min']);
35563 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
35564 $versions[] = '<' . $this->parseVersion($values['max']);
35565 } else {
35566 foreach ($values as $op => $version) {
35567 if ('exclude' == $op && is_array($version)) {
35568 foreach ($version as $versionPart) {
35569 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
35570 }
35571 } else {
35572 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
35573 }
35574 }
35575 }
35576
35577 return implode(',', $versions);
35578 }
35579
35580
35581
35582
35583
35584
35585
35586 private function parseVersion($version)
35587 {
35588 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
35589 $version = $matches[1]
35590 .(!empty($matches[2]) ? $matches[2] : '.0')
35591 .(!empty($matches[3]) ? $matches[3] : '.0')
35592 .(!empty($matches[4]) ? $matches[4] : '.0');
35593
35594 return $version;
35595 }
35596
35597 return null;
35598 }
35599
35600
35601
35602
35603
35604
35605
35606 private function isHash(array $array)
35607 {
35608 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
35609 }
35610 }
35611 <?php
35612
35613
35614
35615
35616
35617
35618
35619
35620
35621
35622
35623 namespace Composer\Repository\Pear;
35624
35625
35626
35627
35628
35629
35630 class PackageInfo
35631 {
35632 private $channelName;
35633 private $packageName;
35634 private $license;
35635 private $shortDescription;
35636 private $description;
35637 private $releases;
35638
35639
35640
35641
35642
35643
35644
35645
35646
35647 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
35648 {
35649 $this->channelName = $channelName;
35650 $this->packageName = $packageName;
35651 $this->license = $license;
35652 $this->shortDescription = $shortDescription;
35653 $this->description = $description;
35654 $this->releases = $releases;
35655 }
35656
35657
35658
35659
35660 public function getChannelName()
35661 {
35662 return $this->channelName;
35663 }
35664
35665
35666
35667
35668 public function getPackageName()
35669 {
35670 return $this->packageName;
35671 }
35672
35673
35674
35675
35676 public function getDescription()
35677 {
35678 return $this->description;
35679 }
35680
35681
35682
35683
35684 public function getShortDescription()
35685 {
35686 return $this->shortDescription;
35687 }
35688
35689
35690
35691
35692 public function getLicense()
35693 {
35694 return $this->license;
35695 }
35696
35697
35698
35699
35700 public function getReleases()
35701 {
35702 return $this->releases;
35703 }
35704 }
35705 <?php
35706
35707
35708
35709
35710
35711
35712
35713
35714
35715
35716
35717 namespace Composer\Repository\Pear;
35718
35719
35720
35721
35722
35723
35724 class ReleaseInfo
35725 {
35726 private $stability;
35727 private $dependencyInfo;
35728
35729
35730
35731
35732
35733 public function __construct($stability, $dependencyInfo)
35734 {
35735 $this->stability = $stability;
35736 $this->dependencyInfo = $dependencyInfo;
35737 }
35738
35739
35740
35741
35742 public function getDependencyInfo()
35743 {
35744 return $this->dependencyInfo;
35745 }
35746
35747
35748
35749
35750 public function getStability()
35751 {
35752 return $this->stability;
35753 }
35754 }
35755 <?php
35756
35757
35758
35759
35760
35761
35762
35763
35764
35765
35766
35767 namespace Composer\Repository;
35768
35769 use Composer\IO\IOInterface;
35770 use Composer\Semver\VersionParser as SemverVersionParser;
35771 use Composer\Package\Version\VersionParser;
35772 use Composer\Repository\Pear\ChannelReader;
35773 use Composer\Package\CompletePackage;
35774 use Composer\Repository\Pear\ChannelInfo;
35775 use Composer\EventDispatcher\EventDispatcher;
35776 use Composer\Package\Link;
35777 use Composer\Semver\Constraint\Constraint;
35778 use Composer\Util\RemoteFilesystem;
35779 use Composer\Config;
35780 use Composer\Factory;
35781
35782
35783
35784
35785
35786
35787
35788
35789
35790
35791 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
35792 {
35793 private $url;
35794 private $io;
35795 private $rfs;
35796 private $versionParser;
35797 private $repoConfig;
35798
35799
35800
35801
35802 private $vendorAlias;
35803
35804 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
35805 {
35806 parent::__construct();
35807 if (!preg_match('{^https?://}', $repoConfig['url'])) {
35808 $repoConfig['url'] = 'http://'.$repoConfig['url'];
35809 }
35810
35811 $urlBits = parse_url($repoConfig['url']);
35812 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
35813 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
35814 }
35815
35816 $this->url = rtrim($repoConfig['url'], '/');
35817 $this->io = $io;
35818 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
35819 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
35820 $this->versionParser = new VersionParser();
35821 $this->repoConfig = $repoConfig;
35822 }
35823
35824 public function getRepoConfig()
35825 {
35826 return $this->repoConfig;
35827 }
35828
35829 protected function initialize()
35830 {
35831 parent::initialize();
35832
35833 $this->io->writeError('Initializing PEAR repository '.$this->url);
35834
35835 $reader = new ChannelReader($this->rfs);
35836 try {
35837 $channelInfo = $reader->read($this->url);
35838 } catch (\Exception $e) {
35839 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
35840
35841 return;
35842 }
35843 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
35844 foreach ($packages as $package) {
35845 $this->addPackage($package);
35846 }
35847 }
35848
35849
35850
35851
35852
35853
35854
35855
35856 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
35857 {
35858 $result = array();
35859 foreach ($channelInfo->getPackages() as $packageDefinition) {
35860 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
35861 try {
35862 $normalizedVersion = $versionParser->normalize($version);
35863 } catch (\UnexpectedValueException $e) {
35864 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
35865 continue;
35866 }
35867
35868 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
35869
35870
35871  
35872  $urlBits = parse_url($this->url);
35873 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
35874 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
35875
35876 $requires = array();
35877 $suggests = array();
35878 $conflicts = array();
35879 $replaces = array();
35880
35881
35882  
35883  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
35884 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
35885 $aliasConstraint = new Constraint('==', $normalizedVersion);
35886 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
35887 }
35888
35889
35890  if (!empty($this->vendorAlias)
35891 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
35892 ) {
35893 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
35894 $aliasConstraint = new Constraint('==', $normalizedVersion);
35895 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
35896 }
35897
35898 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
35899 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
35900 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
35901 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
35902 switch ($dependencyConstraint->getType()) {
35903 case 'required':
35904 $requires[] = $link;
35905 break;
35906 case 'conflicts':
35907 $conflicts[] = $link;
35908 break;
35909 case 'replaces':
35910 $replaces[] = $link;
35911 break;
35912 }
35913 }
35914
35915 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
35916 foreach ($dependencyConstraints as $dependencyConstraint) {
35917 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
35918 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
35919 }
35920 }
35921
35922 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
35923 $package->setType('pear-library');
35924 $package->setDescription($packageDefinition->getDescription());
35925 $package->setLicense(array($packageDefinition->getLicense()));
35926 $package->setDistType('file');
35927 $package->setDistUrl($distUrl);
35928 $package->setAutoload(array('classmap' => array('')));
35929 $package->setIncludePaths(array('/'));
35930 $package->setRequires($requires);
35931 $package->setConflicts($conflicts);
35932 $package->setSuggests($suggests);
35933 $package->setReplaces($replaces);
35934 $result[] = $package;
35935 }
35936 }
35937
35938 return $result;
35939 }
35940
35941 private function buildComposerPackageName($channelName, $packageName)
35942 {
35943 if ('php' === $channelName) {
35944 return "php";
35945 }
35946 if ('ext' === $channelName) {
35947 return "ext-{$packageName}";
35948 }
35949
35950 return "pear-{$channelName}/{$packageName}";
35951 }
35952 }
35953 <?php
35954
35955
35956
35957
35958
35959
35960
35961
35962
35963
35964
35965 namespace Composer\Repository;
35966
35967 use Composer\Package\CompletePackage;
35968 use Composer\Package\PackageInterface;
35969 use Composer\Package\Version\VersionParser;
35970 use Composer\Plugin\PluginInterface;
35971 use Composer\Util\ProcessExecutor;
35972 use Composer\Util\Silencer;
35973 use Composer\Util\Platform;
35974 use Composer\XdebugHandler\XdebugHandler;
35975 use Symfony\Component\Process\ExecutableFinder;
35976
35977
35978
35979
35980 class PlatformRepository extends ArrayRepository
35981 {
35982 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-plugin-api)$}iD';
35983
35984 private $versionParser;
35985
35986
35987
35988
35989
35990
35991
35992
35993 private $overrides = array();
35994
35995 private $process;
35996
35997 public function __construct(array $packages = array(), array $overrides = array(), ProcessExecutor $process = null)
35998 {
35999 $this->process = $process === null ? (new ProcessExecutor()) : $process;
36000 foreach ($overrides as $name => $version) {
36001 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
36002 }
36003 parent::__construct($packages);
36004 }
36005
36006 protected function initialize()
36007 {
36008 parent::initialize();
36009
36010 $this->versionParser = new VersionParser();
36011
36012
36013  
36014  foreach ($this->overrides as $override) {
36015
36016  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
36017 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
36018 }
36019
36020 $this->addOverriddenPackage($override);
36021 }
36022
36023 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
36024 $version = $this->versionParser->normalize($prettyVersion);
36025 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
36026 $composerPluginApi->setDescription('The Composer Plugin API');
36027 $this->addPackage($composerPluginApi);
36028
36029 try {
36030 $prettyVersion = PHP_VERSION;
36031 $version = $this->versionParser->normalize($prettyVersion);
36032 } catch (\UnexpectedValueException $e) {
36033 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
36034 $version = $this->versionParser->normalize($prettyVersion);
36035 }
36036
36037 $php = new CompletePackage('php', $version, $prettyVersion);
36038 $php->setDescription('The PHP interpreter');
36039 $this->addPackage($php);
36040
36041 if (PHP_DEBUG) {
36042 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
36043 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
36044 $this->addPackage($phpdebug);
36045 }
36046
36047 if (defined('PHP_ZTS') && PHP_ZTS) {
36048 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
36049 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
36050 $this->addPackage($phpzts);
36051 }
36052
36053 if (PHP_INT_SIZE === 8) {
36054 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
36055 $php64->setDescription('The PHP interpreter, 64bit');
36056 $this->addPackage($php64);
36057 }
36058
36059
36060  
36061  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
36062 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
36063 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
36064 $this->addPackage($phpIpv6);
36065 }
36066
36067 $loadedExtensions = get_loaded_extensions();
36068
36069
36070  foreach ($loadedExtensions as $name) {
36071 if (in_array($name, array('standard', 'Core'))) {
36072 continue;
36073 }
36074
36075 $reflExt = new \ReflectionExtension($name);
36076 $prettyVersion = $reflExt->getVersion();
36077 $this->addExtension($name, $prettyVersion);
36078 }
36079
36080
36081  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = XdebugHandler::getSkippedVersion())) {
36082 $this->addExtension('xdebug', $prettyVersion);
36083 }
36084
36085
36086  
36087  
36088  foreach ($loadedExtensions as $name) {
36089 $prettyVersion = null;
36090 $description = 'The '.$name.' PHP library';
36091 switch ($name) {
36092 case 'curl':
36093 $curlVersion = curl_version();
36094 $prettyVersion = $curlVersion['version'];
36095 break;
36096
36097 case 'iconv':
36098 $prettyVersion = ICONV_VERSION;
36099 break;
36100
36101 case 'intl':
36102 $name = 'ICU';
36103 if (defined('INTL_ICU_VERSION')) {
36104 $prettyVersion = INTL_ICU_VERSION;
36105 } else {
36106 $reflector = new \ReflectionExtension('intl');
36107
36108 ob_start();
36109 $reflector->info();
36110 $output = ob_get_clean();
36111
36112 preg_match('/^ICU version => (.*)$/m', $output, $matches);
36113 $prettyVersion = $matches[1];
36114 }
36115
36116 break;
36117
36118 case 'imagick':
36119 $imagick = new \Imagick();
36120 $imageMagickVersion = $imagick->getVersion();
36121
36122  
36123  preg_match('/^ImageMagick ([\d.]+)(?:-(\d+))?/', $imageMagickVersion['versionString'], $matches);
36124 if (isset($matches[2])) {
36125 $prettyVersion = "{$matches[1]}.{$matches[2]}";
36126 } else {
36127 $prettyVersion = $matches[1];
36128 }
36129 break;
36130
36131 case 'libxml':
36132 $prettyVersion = LIBXML_DOTTED_VERSION;
36133 break;
36134
36135 case 'openssl':
36136 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
36137 if (empty($match[2])) {
36138 return $match[1];
36139 }
36140
36141
36142  
36143
36144 if (!preg_match('{^z*[a-z]$}', $match[2])) {
36145
36146  return 0;
36147 }
36148
36149 $len = strlen($match[2]);
36150 $patchVersion = ($len - 1) * 26; 
36151  $patchVersion += ord($match[2][$len - 1]) - 96;
36152
36153 return $match[1].'.'.$patchVersion;
36154 }, OPENSSL_VERSION_TEXT);
36155
36156 $description = OPENSSL_VERSION_TEXT;
36157 break;
36158
36159 case 'pcre':
36160 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
36161 break;
36162
36163 case 'uuid':
36164 $prettyVersion = phpversion('uuid');
36165 break;
36166
36167 case 'xsl':
36168 $prettyVersion = LIBXSLT_DOTTED_VERSION;
36169 break;
36170
36171 default:
36172
36173  continue 2;
36174 }
36175
36176 try {
36177 $version = $this->versionParser->normalize($prettyVersion);
36178 } catch (\UnexpectedValueException $e) {
36179 continue;
36180 }
36181
36182 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
36183 $lib->setDescription($description);
36184 $this->addPackage($lib);
36185 }
36186
36187 $hhvmVersion = defined('HHVM_VERSION') ? HHVM_VERSION : null;
36188 if ($hhvmVersion === null && !Platform::isWindows()) {
36189 $finder = new ExecutableFinder();
36190 $hhvm = $finder->find('hhvm');
36191 if ($hhvm !== null) {
36192 $exitCode = $this->process->execute(
36193 ProcessExecutor::escape($hhvm).
36194 ' --php -d hhvm.jit=0 -r "echo HHVM_VERSION;" 2>/dev/null',
36195 $hhvmVersion
36196 );
36197 if ($exitCode !== 0) {
36198 $hhvmVersion = null;
36199 }
36200 }
36201 }
36202 if ($hhvmVersion) {
36203 try {
36204 $prettyVersion = $hhvmVersion;
36205 $version = $this->versionParser->normalize($prettyVersion);
36206 } catch (\UnexpectedValueException $e) {
36207 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $hhvmVersion);
36208 $version = $this->versionParser->normalize($prettyVersion);
36209 }
36210
36211 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
36212 $hhvm->setDescription('The HHVM Runtime (64bit)');
36213 $this->addPackage($hhvm);
36214 }
36215 }
36216
36217
36218
36219
36220 public function addPackage(PackageInterface $package)
36221 {
36222
36223  if (isset($this->overrides[$package->getName()])) {
36224 $overrider = $this->findPackage($package->getName(), '*');
36225 if ($package->getVersion() === $overrider->getVersion()) {
36226 $actualText = 'same as actual';
36227 } else {
36228 $actualText = 'actual: '.$package->getPrettyVersion();
36229 }
36230 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
36231
36232 return;
36233 }
36234
36235
36236  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
36237 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
36238 if ($package->getVersion() === $overrider->getVersion()) {
36239 $actualText = 'same as actual';
36240 } else {
36241 $actualText = 'actual: '.$package->getPrettyVersion();
36242 }
36243 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
36244
36245 return;
36246 }
36247
36248 parent::addPackage($package);
36249 }
36250
36251 private function addOverriddenPackage(array $override, $name = null)
36252 {
36253 $version = $this->versionParser->normalize($override['version']);
36254 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
36255 $package->setDescription('Package overridden via config.platform');
36256 $package->setExtra(array('config.platform' => true));
36257 parent::addPackage($package);
36258
36259 return $package;
36260 }
36261
36262
36263
36264
36265
36266
36267
36268 private function addExtension($name, $prettyVersion)
36269 {
36270 $extraDescription = null;
36271
36272 try {
36273 $version = $this->versionParser->normalize($prettyVersion);
36274 } catch (\UnexpectedValueException $e) {
36275 $extraDescription = ' (actual version: '.$prettyVersion.')';
36276 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
36277 $prettyVersion = $match[1];
36278 } else {
36279 $prettyVersion = '0';
36280 }
36281 $version = $this->versionParser->normalize($prettyVersion);
36282 }
36283
36284 $packageName = $this->buildPackageName($name);
36285 $ext = new CompletePackage($packageName, $version, $prettyVersion);
36286 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
36287 $this->addPackage($ext);
36288 }
36289
36290 private function buildPackageName($name)
36291 {
36292 return 'ext-' . str_replace(' ', '-', $name);
36293 }
36294 }
36295 <?php
36296
36297
36298
36299
36300
36301
36302
36303
36304
36305
36306
36307 namespace Composer\Repository;
36308
36309 use Composer\Factory;
36310 use Composer\IO\IOInterface;
36311 use Composer\Config;
36312 use Composer\EventDispatcher\EventDispatcher;
36313 use Composer\Util\RemoteFilesystem;
36314 use Composer\Json\JsonFile;
36315
36316
36317
36318
36319 class RepositoryFactory
36320 {
36321
36322
36323
36324
36325
36326
36327
36328 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
36329 {
36330 if (0 === strpos($repository, 'http')) {
36331 $repoConfig = array('type' => 'composer', 'url' => $repository);
36332 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
36333 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
36334 $data = $json->read();
36335 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
36336 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
36337 } elseif ($allowFilesystem) {
36338 $repoConfig = array('type' => 'filesystem', 'json' => $json);
36339 } else {
36340 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
36341 }
36342 } elseif ('{' === substr($repository, 0, 1)) {
36343
36344  $repoConfig = JsonFile::parseJson($repository);
36345 } else {
36346 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
36347 }
36348
36349 return $repoConfig;
36350 }
36351
36352
36353
36354
36355
36356
36357
36358
36359 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
36360 {
36361 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
36362
36363 return static::createRepo($io, $config, $repoConfig);
36364 }
36365
36366
36367
36368
36369
36370
36371
36372 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
36373 {
36374 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
36375 $repos = static::createRepos($rm, array($repoConfig));
36376
36377 return reset($repos);
36378 }
36379
36380
36381
36382
36383
36384
36385
36386 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
36387 {
36388 if (!$config) {
36389 $config = Factory::createConfig($io);
36390 }
36391 if ($io) {
36392 $io->loadConfiguration($config);
36393 }
36394 if (!$rm) {
36395 if (!$io) {
36396 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
36397 }
36398 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
36399 }
36400
36401 return static::createRepos($rm, $config->getRepositories());
36402 }
36403
36404
36405
36406
36407
36408
36409
36410
36411 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
36412 {
36413 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
36414 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
36415 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
36416 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
36417 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
36418 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
36419 $rm->setRepositoryClass('git-bitbucket', 'Composer\Repository\VcsRepository');
36420 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
36421 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
36422 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
36423 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
36424 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
36425 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
36426 $rm->setRepositoryClass('hg-bitbucket', 'Composer\Repository\VcsRepository');
36427 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
36428 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
36429
36430 return $rm;
36431 }
36432
36433
36434
36435
36436 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
36437 {
36438 $repos = array();
36439
36440 foreach ($repoConfigs as $index => $repo) {
36441 if (is_string($repo)) {
36442 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
36443 }
36444 if (!is_array($repo)) {
36445 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
36446 }
36447 if (!isset($repo['type'])) {
36448 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
36449 }
36450 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
36451 while (isset($repos[$name])) {
36452 $name .= '2';
36453 }
36454 if ($repo['type'] === 'filesystem') {
36455 $repos[$name] = new FilesystemRepository($repo['json']);
36456 } else {
36457 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
36458 }
36459 }
36460
36461 return $repos;
36462 }
36463 }
36464 <?php
36465
36466
36467
36468
36469
36470
36471
36472
36473
36474
36475
36476 namespace Composer\Repository;
36477
36478 use Composer\Package\PackageInterface;
36479
36480
36481
36482
36483
36484
36485
36486
36487 interface RepositoryInterface extends \Countable
36488 {
36489 const SEARCH_FULLTEXT = 0;
36490 const SEARCH_NAME = 1;
36491
36492
36493
36494
36495
36496
36497
36498
36499 public function hasPackage(PackageInterface $package);
36500
36501
36502
36503
36504
36505
36506
36507
36508
36509 public function findPackage($name, $constraint);
36510
36511
36512
36513
36514
36515
36516
36517
36518
36519 public function findPackages($name, $constraint = null);
36520
36521
36522
36523
36524
36525
36526 public function getPackages();
36527
36528
36529
36530
36531
36532
36533
36534
36535
36536 public function search($query, $mode = 0);
36537 }
36538 <?php
36539
36540
36541
36542
36543
36544
36545
36546
36547
36548
36549
36550 namespace Composer\Repository;
36551
36552 use Composer\IO\IOInterface;
36553 use Composer\Config;
36554 use Composer\EventDispatcher\EventDispatcher;
36555 use Composer\Package\PackageInterface;
36556 use Composer\Util\RemoteFilesystem;
36557
36558
36559
36560
36561
36562
36563
36564
36565 class RepositoryManager
36566 {
36567 private $localRepository;
36568 private $repositories = array();
36569 private $repositoryClasses = array();
36570 private $io;
36571 private $config;
36572 private $eventDispatcher;
36573 private $rfs;
36574
36575 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
36576 {
36577 $this->io = $io;
36578 $this->config = $config;
36579 $this->eventDispatcher = $eventDispatcher;
36580 $this->rfs = $rfs;
36581 }
36582
36583
36584
36585
36586
36587
36588
36589
36590
36591 public function findPackage($name, $constraint)
36592 {
36593 foreach ($this->repositories as $repository) {
36594
36595 if ($package = $repository->findPackage($name, $constraint)) {
36596 return $package;
36597 }
36598 }
36599
36600 return null;
36601 }
36602
36603
36604
36605
36606
36607
36608
36609
36610
36611 public function findPackages($name, $constraint)
36612 {
36613 $packages = array();
36614
36615 foreach ($this->getRepositories() as $repository) {
36616 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
36617 }
36618
36619 return $packages;
36620 }
36621
36622
36623
36624
36625
36626
36627 public function addRepository(RepositoryInterface $repository)
36628 {
36629 $this->repositories[] = $repository;
36630 }
36631
36632
36633
36634
36635
36636
36637
36638
36639 public function prependRepository(RepositoryInterface $repository)
36640 {
36641 array_unshift($this->repositories, $repository);
36642 }
36643
36644
36645
36646
36647
36648
36649
36650
36651
36652
36653 public function createRepository($type, $config, $name = null)
36654 {
36655 if (!isset($this->repositoryClasses[$type])) {
36656 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
36657 }
36658
36659 if (isset($config['packagist']) && false === $config['packagist']) {
36660 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
36661 }
36662
36663 $class = $this->repositoryClasses[$type];
36664
36665 $reflMethod = new \ReflectionMethod($class, '__construct');
36666 $params = $reflMethod->getParameters();
36667 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
36668 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
36669 }
36670
36671 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
36672 }
36673
36674
36675
36676
36677
36678
36679
36680 public function setRepositoryClass($type, $class)
36681 {
36682 $this->repositoryClasses[$type] = $class;
36683 }
36684
36685
36686
36687
36688
36689
36690 public function getRepositories()
36691 {
36692 return $this->repositories;
36693 }
36694
36695
36696
36697
36698
36699
36700 public function setLocalRepository(WritableRepositoryInterface $repository)
36701 {
36702 $this->localRepository = $repository;
36703 }
36704
36705
36706
36707
36708
36709
36710 public function getLocalRepository()
36711 {
36712 return $this->localRepository;
36713 }
36714 }
36715 <?php
36716
36717
36718
36719
36720
36721
36722
36723
36724
36725
36726
36727 namespace Composer\Repository;
36728
36729
36730
36731
36732
36733
36734 class RepositorySecurityException extends \Exception
36735 {
36736 }
36737 <?php
36738
36739
36740
36741
36742
36743
36744
36745
36746
36747
36748
36749 namespace Composer\Repository\Vcs;
36750
36751 use Composer\Cache;
36752 use Composer\Downloader\TransportException;
36753 use Composer\Json\JsonFile;
36754 use Composer\Util\Bitbucket;
36755
36756 abstract class BitbucketDriver extends VcsDriver
36757 {
36758
36759 protected $cache;
36760 protected $owner;
36761 protected $repository;
36762 protected $hasIssues;
36763 protected $rootIdentifier;
36764 protected $tags;
36765 protected $branches;
36766 protected $infoCache = array();
36767 protected $branchesUrl = '';
36768 protected $tagsUrl = '';
36769 protected $homeUrl = '';
36770 protected $website = '';
36771 protected $cloneHttpsUrl = '';
36772
36773
36774
36775
36776 protected $fallbackDriver;
36777
36778 protected $vcsType;
36779
36780
36781
36782
36783 public function initialize()
36784 {
36785 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#i', $this->url, $match);
36786 $this->owner = $match[1];
36787 $this->repository = $match[2];
36788 $this->originUrl = 'bitbucket.org';
36789 $this->cache = new Cache(
36790 $this->io,
36791 implode('/', array(
36792 $this->config->get('cache-repo-dir'),
36793 $this->originUrl,
36794 $this->owner,
36795 $this->repository,
36796 ))
36797 );
36798 }
36799
36800
36801
36802
36803 public function getUrl()
36804 {
36805 if ($this->fallbackDriver) {
36806 return $this->fallbackDriver->getUrl();
36807 }
36808
36809 return $this->cloneHttpsUrl;
36810 }
36811
36812
36813
36814
36815
36816
36817
36818 protected function getRepoData()
36819 {
36820 $resource = sprintf(
36821 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
36822 $this->owner,
36823 $this->repository,
36824 http_build_query(
36825 array('fields' => '-project,-owner'),
36826 null,
36827 '&'
36828 )
36829 );
36830
36831 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
36832 if ($this->fallbackDriver) {
36833 return false;
36834 }
36835 $this->parseCloneUrls($repoData['links']['clone']);
36836
36837 $this->hasIssues = !empty($repoData['has_issues']);
36838 $this->branchesUrl = $repoData['links']['branches']['href'];
36839 $this->tagsUrl = $repoData['links']['tags']['href'];
36840 $this->homeUrl = $repoData['links']['html']['href'];
36841 $this->website = $repoData['website'];
36842 $this->vcsType = $repoData['scm'];
36843
36844 return true;
36845 }
36846
36847
36848
36849
36850 public function getComposerInformation($identifier)
36851 {
36852 if ($this->fallbackDriver) {
36853 return $this->fallbackDriver->getComposerInformation($identifier);
36854 }
36855
36856 if (!isset($this->infoCache[$identifier])) {
36857 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
36858 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
36859 }
36860
36861 $composer = $this->getBaseComposerInformation($identifier);
36862
36863 if ($composer) {
36864
36865  if (!isset($composer['support']['source'])) {
36866 $label = array_search(
36867 $identifier,
36868 $this->getTags()
36869 ) ?: array_search(
36870 $identifier,
36871 $this->getBranches()
36872 ) ?: $identifier;
36873
36874 if (array_key_exists($label, $tags = $this->getTags())) {
36875 $hash = $tags[$label];
36876 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
36877 $hash = $branches[$label];
36878 }
36879
36880 if (! isset($hash)) {
36881 $composer['support']['source'] = sprintf(
36882 'https://%s/%s/%s/src',
36883 $this->originUrl,
36884 $this->owner,
36885 $this->repository
36886 );
36887 } else {
36888 $composer['support']['source'] = sprintf(
36889 'https://%s/%s/%s/src/%s/?at=%s',
36890 $this->originUrl,
36891 $this->owner,
36892 $this->repository,
36893 $hash,
36894 $label
36895 );
36896 }
36897 }
36898 if (!isset($composer['support']['issues']) && $this->hasIssues) {
36899 $composer['support']['issues'] = sprintf(
36900 'https://%s/%s/%s/issues',
36901 $this->originUrl,
36902 $this->owner,
36903 $this->repository
36904 );
36905 }
36906 if (!isset($composer['homepage'])) {
36907 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
36908 }
36909 }
36910
36911 $this->infoCache[$identifier] = $composer;
36912
36913 if ($this->shouldCache($identifier)) {
36914 $this->cache->write($identifier, json_encode($composer));
36915 }
36916 }
36917
36918 return $this->infoCache[$identifier];
36919 }
36920
36921
36922
36923
36924 public function getFileContent($file, $identifier)
36925 {
36926 if ($this->fallbackDriver) {
36927 return $this->fallbackDriver->getFileContent($file, $identifier);
36928 }
36929
36930 if (strpos($identifier, '/') !== false) {
36931 $branches = $this->getBranches();
36932 if (isset($branches[$identifier])) {
36933 $identifier = $branches[$identifier];
36934 }
36935 }
36936
36937 $resource = sprintf(
36938 'https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s',
36939 $this->owner,
36940 $this->repository,
36941 $identifier,
36942 $file
36943 );
36944
36945 return $this->getContentsWithOAuthCredentials($resource);
36946 }
36947
36948
36949
36950
36951 public function getChangeDate($identifier)
36952 {
36953 if ($this->fallbackDriver) {
36954 return $this->fallbackDriver->getChangeDate($identifier);
36955 }
36956
36957 if (strpos($identifier, '/') !== false) {
36958 $branches = $this->getBranches();
36959 if (isset($branches[$identifier])) {
36960 $identifier = $branches[$identifier];
36961 }
36962 }
36963
36964 $resource = sprintf(
36965 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
36966 $this->owner,
36967 $this->repository,
36968 $identifier
36969 );
36970 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
36971
36972 return new \DateTime($commit['date']);
36973 }
36974
36975
36976
36977
36978 public function getSource($identifier)
36979 {
36980 if ($this->fallbackDriver) {
36981 return $this->fallbackDriver->getSource($identifier);
36982 }
36983
36984 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
36985 }
36986
36987
36988
36989
36990 public function getDist($identifier)
36991 {
36992 if ($this->fallbackDriver) {
36993 return $this->fallbackDriver->getDist($identifier);
36994 }
36995
36996 $url = sprintf(
36997 'https://bitbucket.org/%s/%s/get/%s.zip',
36998 $this->owner,
36999 $this->repository,
37000 $identifier
37001 );
37002
37003 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
37004 }
37005
37006
37007
37008
37009 public function getTags()
37010 {
37011 if ($this->fallbackDriver) {
37012 return $this->fallbackDriver->getTags();
37013 }
37014
37015 if (null === $this->tags) {
37016 $this->tags = array();
37017 $resource = sprintf(
37018 '%s?%s',
37019 $this->tagsUrl,
37020 http_build_query(
37021 array(
37022 'pagelen' => 100,
37023 'fields' => 'values.name,values.target.hash,next',
37024 'sort' => '-target.date',
37025 ),
37026 null,
37027 '&'
37028 )
37029 );
37030 $hasNext = true;
37031 while ($hasNext) {
37032 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
37033 foreach ($tagsData['values'] as $data) {
37034 $this->tags[$data['name']] = $data['target']['hash'];
37035 }
37036 if (empty($tagsData['next'])) {
37037 $hasNext = false;
37038 } else {
37039 $resource = $tagsData['next'];
37040 }
37041 }
37042 if ($this->vcsType === 'hg') {
37043 unset($this->tags['tip']);
37044 }
37045 }
37046
37047 return $this->tags;
37048 }
37049
37050
37051
37052
37053 public function getBranches()
37054 {
37055 if ($this->fallbackDriver) {
37056 return $this->fallbackDriver->getBranches();
37057 }
37058
37059 if (null === $this->branches) {
37060 $this->branches = array();
37061 $resource = sprintf(
37062 '%s?%s',
37063 $this->branchesUrl,
37064 http_build_query(
37065 array(
37066 'pagelen' => 100,
37067 'fields' => 'values.name,values.target.hash,values.heads,next',
37068 'sort' => '-target.date',
37069 ),
37070 null,
37071 '&'
37072 )
37073 );
37074 $hasNext = true;
37075 while ($hasNext) {
37076 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
37077 foreach ($branchData['values'] as $data) {
37078
37079  if ($this->vcsType === 'hg' && empty($data['heads'])) {
37080 continue;
37081 }
37082
37083 $this->branches[$data['name']] = $data['target']['hash'];
37084 }
37085 if (empty($branchData['next'])) {
37086 $hasNext = false;
37087 } else {
37088 $resource = $branchData['next'];
37089 }
37090 }
37091 }
37092
37093 return $this->branches;
37094 }
37095
37096
37097
37098
37099
37100
37101
37102
37103
37104 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
37105 {
37106 try {
37107 return parent::getContents($url);
37108 } catch (TransportException $e) {
37109 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
37110
37111 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
37112 if (!$this->io->hasAuthentication($this->originUrl)
37113 && $bitbucketUtil->authorizeOAuth($this->originUrl)
37114 ) {
37115 return parent::getContents($url);
37116 }
37117
37118 if (!$this->io->isInteractive() && $fetchingRepoData) {
37119 return $this->attemptCloneFallback();
37120 }
37121 }
37122
37123 throw $e;
37124 }
37125 }
37126
37127
37128
37129
37130
37131
37132 abstract protected function generateSshUrl();
37133
37134 protected function attemptCloneFallback()
37135 {
37136 try {
37137 $this->setupFallbackDriver($this->generateSshUrl());
37138 } catch (\RuntimeException $e) {
37139 $this->fallbackDriver = null;
37140
37141 $this->io->writeError(
37142 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
37143 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
37144 );
37145 throw $e;
37146 }
37147 }
37148
37149
37150
37151
37152
37153 abstract protected function setupFallbackDriver($url);
37154
37155
37156
37157
37158
37159 protected function parseCloneUrls(array $cloneLinks)
37160 {
37161 foreach ($cloneLinks as $cloneLink) {
37162 if ($cloneLink['name'] === 'https') {
37163
37164  
37165  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
37166 }
37167 }
37168 }
37169
37170
37171
37172
37173 protected function getMainBranchData()
37174 {
37175 $resource = sprintf(
37176 'https://api.bitbucket.org/2.0/repositories/%s/%s?fields=mainbranch',
37177 $this->owner,
37178 $this->repository
37179 );
37180
37181 $data = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
37182 if (isset($data['mainbranch'])) {
37183 return $data['mainbranch'];
37184 }
37185
37186 return null;
37187 }
37188 }
37189 <?php
37190
37191
37192
37193
37194
37195
37196
37197
37198
37199
37200
37201 namespace Composer\Repository\Vcs;
37202
37203 use Composer\Cache;
37204 use Composer\Config;
37205 use Composer\Util\ProcessExecutor;
37206 use Composer\Util\Filesystem;
37207 use Composer\IO\IOInterface;
37208
37209
37210
37211
37212 class FossilDriver extends VcsDriver
37213 {
37214 protected $tags;
37215 protected $branches;
37216 protected $rootIdentifier;
37217 protected $repoFile;
37218 protected $checkoutDir;
37219 protected $infoCache = array();
37220
37221
37222
37223
37224 public function initialize()
37225 {
37226
37227  $this->checkFossil();
37228
37229
37230  $this->config->prohibitUrlByConfig($this->url, $this->io);
37231
37232
37233  
37234  if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
37235 $this->checkoutDir = $this->url;
37236 } else {
37237 if (!Cache::isUsable($this->config->get('cache-repo-dir')) || !Cache::isUsable($this->config->get('cache-vcs-dir'))) {
37238 throw new \RuntimeException('FossilDriver requires a usable cache directory, and it looks like you set it to be disabled');
37239 }
37240
37241 $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url);
37242 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
37243 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
37244
37245 $this->updateLocalRepo();
37246 }
37247
37248 $this->getTags();
37249 $this->getBranches();
37250 }
37251
37252
37253
37254
37255 protected function checkFossil()
37256 {
37257 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
37258 throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
37259 }
37260 }
37261
37262
37263
37264
37265 protected function updateLocalRepo()
37266 {
37267 $fs = new Filesystem();
37268 $fs->ensureDirectoryExists($this->checkoutDir);
37269
37270 if (!is_writable(dirname($this->checkoutDir))) {
37271 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
37272 }
37273
37274
37275  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
37276 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
37277 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
37278 }
37279 } else {
37280
37281  $fs->removeDirectory($this->checkoutDir);
37282 $fs->remove($this->repoFile);
37283
37284 $fs->ensureDirectoryExists($this->checkoutDir);
37285
37286 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
37287 $output = $this->process->getErrorOutput();
37288
37289 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
37290 }
37291
37292 if (0 !== $this->process->execute(sprintf('fossil open %s --nested', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
37293 $output = $this->process->getErrorOutput();
37294
37295 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
37296 }
37297 }
37298 }
37299
37300
37301
37302
37303 public function getRootIdentifier()
37304 {
37305 if (null === $this->rootIdentifier) {
37306 $this->rootIdentifier = 'trunk';
37307 }
37308
37309 return $this->rootIdentifier;
37310 }
37311
37312
37313
37314
37315 public function getUrl()
37316 {
37317 return $this->url;
37318 }
37319
37320
37321
37322
37323 public function getSource($identifier)
37324 {
37325 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
37326 }
37327
37328
37329
37330
37331 public function getDist($identifier)
37332 {
37333 return null;
37334 }
37335
37336
37337
37338
37339 public function getFileContent($file, $identifier)
37340 {
37341 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37342 $this->process->execute($command, $content, $this->checkoutDir);
37343
37344 if (!trim($content)) {
37345 return null;
37346 }
37347
37348 return $content;
37349 }
37350
37351
37352
37353
37354 public function getChangeDate($identifier)
37355 {
37356 $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir);
37357 list($ckout, $date, $message) = explode(' ', trim($output), 3);
37358
37359 return new \DateTime($date, new \DateTimeZone('UTC'));
37360 }
37361
37362
37363
37364
37365 public function getTags()
37366 {
37367 if (null === $this->tags) {
37368 $tags = array();
37369
37370 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
37371 foreach ($this->process->splitLines($output) as $tag) {
37372 $tags[$tag] = $tag;
37373 }
37374
37375 $this->tags = $tags;
37376 }
37377
37378 return $this->tags;
37379 }
37380
37381
37382
37383
37384 public function getBranches()
37385 {
37386 if (null === $this->branches) {
37387 $branches = array();
37388 $bookmarks = array();
37389
37390 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
37391 foreach ($this->process->splitLines($output) as $branch) {
37392 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
37393 $branches[$branch] = $branch;
37394 }
37395
37396 $this->branches = $branches;
37397 }
37398
37399 return $this->branches;
37400 }
37401
37402
37403
37404
37405 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37406 {
37407 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
37408 return true;
37409 }
37410
37411 if (preg_match('!/fossil/|\.fossil!', $url)) {
37412 return true;
37413 }
37414
37415
37416  if (Filesystem::isLocalPath($url)) {
37417 $url = Filesystem::getPlatformPath($url);
37418 if (!is_dir($url)) {
37419 return false;
37420 }
37421
37422 $process = new ProcessExecutor($io);
37423
37424  if ($process->execute('fossil info', $output, $url) === 0) {
37425 return true;
37426 }
37427 }
37428
37429 return false;
37430 }
37431 }
37432 <?php
37433
37434
37435
37436
37437
37438
37439
37440
37441
37442
37443
37444 namespace Composer\Repository\Vcs;
37445
37446 use Composer\Config;
37447 use Composer\IO\IOInterface;
37448
37449
37450
37451
37452 class GitBitbucketDriver extends BitbucketDriver
37453 {
37454
37455
37456
37457 public function getRootIdentifier()
37458 {
37459 if ($this->fallbackDriver) {
37460 return $this->fallbackDriver->getRootIdentifier();
37461 }
37462
37463 if (null === $this->rootIdentifier) {
37464 if (! $this->getRepoData()) {
37465 return $this->fallbackDriver->getRootIdentifier();
37466 }
37467
37468 if ($this->vcsType !== 'git') {
37469 throw new \RuntimeException(
37470 $this->url.' does not appear to be a git repository, use '.
37471 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
37472 );
37473 }
37474
37475 $mainBranchData = $this->getMainBranchData();
37476 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
37477 }
37478
37479 return $this->rootIdentifier;
37480 }
37481
37482
37483
37484
37485 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37486 {
37487 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#i', $url)) {
37488 return false;
37489 }
37490
37491 if (!extension_loaded('openssl')) {
37492 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37493
37494 return false;
37495 }
37496
37497 return true;
37498 }
37499
37500
37501
37502
37503 protected function setupFallbackDriver($url)
37504 {
37505 $this->fallbackDriver = new GitDriver(
37506 array('url' => $url),
37507 $this->io,
37508 $this->config,
37509 $this->process,
37510 $this->remoteFilesystem
37511 );
37512 $this->fallbackDriver->initialize();
37513 }
37514
37515
37516
37517
37518 protected function generateSshUrl()
37519 {
37520 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
37521 }
37522 }
37523 <?php
37524
37525
37526
37527
37528
37529
37530
37531
37532
37533
37534
37535 namespace Composer\Repository\Vcs;
37536
37537 use Composer\Util\ProcessExecutor;
37538 use Composer\Util\Filesystem;
37539 use Composer\Util\Git as GitUtil;
37540 use Composer\IO\IOInterface;
37541 use Composer\Cache;
37542 use Composer\Config;
37543
37544
37545
37546
37547 class GitDriver extends VcsDriver
37548 {
37549 protected $cache;
37550 protected $tags;
37551 protected $branches;
37552 protected $rootIdentifier;
37553 protected $repoDir;
37554 protected $infoCache = array();
37555
37556
37557
37558
37559 public function initialize()
37560 {
37561 if (Filesystem::isLocalPath($this->url)) {
37562 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
37563 $this->repoDir = $this->url;
37564 $cacheUrl = realpath($this->url);
37565 } else {
37566 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
37567 throw new \RuntimeException('GitDriver requires a usable cache directory, and it looks like you set it to be disabled');
37568 }
37569
37570 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
37571
37572 GitUtil::cleanEnv();
37573
37574 $fs = new Filesystem();
37575 $fs->ensureDirectoryExists(dirname($this->repoDir));
37576
37577 if (!is_writable(dirname($this->repoDir))) {
37578 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
37579 }
37580
37581 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
37582 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.');
37583 }
37584
37585 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
37586 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
37587 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
37588 }
37589
37590 $cacheUrl = $this->url;
37591 }
37592
37593 $this->getTags();
37594 $this->getBranches();
37595
37596 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
37597 }
37598
37599
37600
37601
37602 public function getRootIdentifier()
37603 {
37604 if (null === $this->rootIdentifier) {
37605 $this->rootIdentifier = 'master';
37606
37607
37608  $this->process->execute('git branch --no-color', $output, $this->repoDir);
37609 $branches = $this->process->splitLines($output);
37610 if (!in_array('* master', $branches)) {
37611 foreach ($branches as $branch) {
37612 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
37613 $this->rootIdentifier = $match[1];
37614 break;
37615 }
37616 }
37617 }
37618 }
37619
37620 return $this->rootIdentifier;
37621 }
37622
37623
37624
37625
37626 public function getUrl()
37627 {
37628 return $this->url;
37629 }
37630
37631
37632
37633
37634 public function getSource($identifier)
37635 {
37636 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
37637 }
37638
37639
37640
37641
37642 public function getDist($identifier)
37643 {
37644 return null;
37645 }
37646
37647
37648
37649
37650 public function getFileContent($file, $identifier)
37651 {
37652 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37653 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
37654
37655 if (!trim($content)) {
37656 return null;
37657 }
37658
37659 return $content;
37660 }
37661
37662
37663
37664
37665 public function getChangeDate($identifier)
37666 {
37667 $this->process->execute(sprintf(
37668 'git -c log.showSignature=false log -1 --format=%%at %s',
37669 ProcessExecutor::escape($identifier)
37670 ), $output, $this->repoDir);
37671
37672 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
37673 }
37674
37675
37676
37677
37678 public function getTags()
37679 {
37680 if (null === $this->tags) {
37681 $this->tags = array();
37682
37683 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
37684 foreach ($output = $this->process->splitLines($output) as $tag) {
37685 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
37686 $this->tags[$match[2]] = $match[1];
37687 }
37688 }
37689 }
37690
37691 return $this->tags;
37692 }
37693
37694
37695
37696
37697 public function getBranches()
37698 {
37699 if (null === $this->branches) {
37700 $branches = array();
37701
37702 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
37703 foreach ($this->process->splitLines($output) as $branch) {
37704 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
37705 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
37706 $branches[$match[1]] = $match[2];
37707 }
37708 }
37709 }
37710
37711 $this->branches = $branches;
37712 }
37713
37714 return $this->branches;
37715 }
37716
37717
37718
37719
37720 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37721 {
37722 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
37723 return true;
37724 }
37725
37726
37727  if (Filesystem::isLocalPath($url)) {
37728 $url = Filesystem::getPlatformPath($url);
37729 if (!is_dir($url)) {
37730 return false;
37731 }
37732
37733 $process = new ProcessExecutor($io);
37734
37735  if ($process->execute('git tag', $output, $url) === 0) {
37736 return true;
37737 }
37738 }
37739
37740 if (!$deep) {
37741 return false;
37742 }
37743
37744 $process = new ProcessExecutor($io);
37745
37746 return $process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0;
37747 }
37748 }
37749 <?php
37750
37751
37752
37753
37754
37755
37756
37757
37758
37759
37760
37761 namespace Composer\Repository\Vcs;
37762
37763 use Composer\Config;
37764 use Composer\Downloader\TransportException;
37765 use Composer\Json\JsonFile;
37766 use Composer\Cache;
37767 use Composer\IO\IOInterface;
37768 use Composer\Util\GitHub;
37769
37770
37771
37772
37773 class GitHubDriver extends VcsDriver
37774 {
37775 protected $cache;
37776 protected $owner;
37777 protected $repository;
37778 protected $tags;
37779 protected $branches;
37780 protected $rootIdentifier;
37781 protected $repoData;
37782 protected $hasIssues;
37783 protected $infoCache = array();
37784 protected $isPrivate = false;
37785
37786
37787
37788
37789
37790
37791 protected $gitDriver;
37792
37793
37794
37795
37796 public function initialize()
37797 {
37798 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
37799 $this->owner = $match[3];
37800 $this->repository = $match[4];
37801 $this->originUrl = strtolower(!empty($match[1]) ? $match[1] : $match[2]);
37802 if ($this->originUrl === 'www.github.com') {
37803 $this->originUrl = 'github.com';
37804 }
37805 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
37806
37807 if ( $this->config->get('use-github-api') === false || (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api'] ) ){
37808 $this->setupGitDriver($this->url);
37809
37810 return;
37811 }
37812
37813 $this->fetchRootIdentifier();
37814 }
37815
37816 public function getRepositoryUrl()
37817 {
37818 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
37819 }
37820
37821
37822
37823
37824 public function getRootIdentifier()
37825 {
37826 if ($this->gitDriver) {
37827 return $this->gitDriver->getRootIdentifier();
37828 }
37829
37830 return $this->rootIdentifier;
37831 }
37832
37833
37834
37835
37836 public function getUrl()
37837 {
37838 if ($this->gitDriver) {
37839 return $this->gitDriver->getUrl();
37840 }
37841
37842 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
37843 }
37844
37845
37846
37847
37848 protected function getApiUrl()
37849 {
37850 if ('github.com' === $this->originUrl) {
37851 $apiUrl = 'api.github.com';
37852 } else {
37853 $apiUrl = $this->originUrl . '/api/v3';
37854 }
37855
37856 return 'https://' . $apiUrl;
37857 }
37858
37859
37860
37861
37862 public function getSource($identifier)
37863 {
37864 if ($this->gitDriver) {
37865 return $this->gitDriver->getSource($identifier);
37866 }
37867 if ($this->isPrivate) {
37868
37869  
37870  $url = $this->generateSshUrl();
37871 } else {
37872 $url = $this->getUrl();
37873 }
37874
37875 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
37876 }
37877
37878
37879
37880
37881 public function getDist($identifier)
37882 {
37883 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
37884
37885 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
37886 }
37887
37888
37889
37890
37891 public function getComposerInformation($identifier)
37892 {
37893 if ($this->gitDriver) {
37894 return $this->gitDriver->getComposerInformation($identifier);
37895 }
37896
37897 if (!isset($this->infoCache[$identifier])) {
37898 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
37899 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37900 }
37901
37902 $composer = $this->getBaseComposerInformation($identifier);
37903
37904 if ($composer) {
37905
37906  if (!isset($composer['support']['source'])) {
37907 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
37908 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
37909 }
37910 if (!isset($composer['support']['issues']) && $this->hasIssues) {
37911 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
37912 }
37913 }
37914
37915 if ($this->shouldCache($identifier)) {
37916 $this->cache->write($identifier, json_encode($composer));
37917 }
37918
37919 $this->infoCache[$identifier] = $composer;
37920 }
37921
37922 return $this->infoCache[$identifier];
37923 }
37924
37925
37926
37927
37928 public function getFileContent($file, $identifier)
37929 {
37930 if ($this->gitDriver) {
37931 return $this->gitDriver->getFileContent($file, $identifier);
37932 }
37933
37934 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
37935 $resource = JsonFile::parseJson($this->getContents($resource));
37936 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
37937 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
37938 }
37939
37940 return $content;
37941 }
37942
37943
37944
37945
37946 public function getChangeDate($identifier)
37947 {
37948 if ($this->gitDriver) {
37949 return $this->gitDriver->getChangeDate($identifier);
37950 }
37951
37952 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
37953 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
37954
37955 return new \DateTime($commit['commit']['committer']['date']);
37956 }
37957
37958
37959
37960
37961 public function getTags()
37962 {
37963 if ($this->gitDriver) {
37964 return $this->gitDriver->getTags();
37965 }
37966 if (null === $this->tags) {
37967 $this->tags = array();
37968 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
37969
37970 do {
37971 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
37972 foreach ($tagsData as $tag) {
37973 $this->tags[$tag['name']] = $tag['commit']['sha'];
37974 }
37975
37976 $resource = $this->getNextPage();
37977 } while ($resource);
37978 }
37979
37980 return $this->tags;
37981 }
37982
37983
37984
37985
37986 public function getBranches()
37987 {
37988 if ($this->gitDriver) {
37989 return $this->gitDriver->getBranches();
37990 }
37991 if (null === $this->branches) {
37992 $this->branches = array();
37993 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
37994
37995 $branchBlacklist = array('gh-pages');
37996
37997 do {
37998 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
37999 foreach ($branchData as $branch) {
38000 $name = substr($branch['ref'], 11);
38001 if (!in_array($name, $branchBlacklist)) {
38002 $this->branches[$name] = $branch['object']['sha'];
38003 }
38004 }
38005
38006 $resource = $this->getNextPage();
38007 } while ($resource);
38008 }
38009
38010 return $this->branches;
38011 }
38012
38013
38014
38015
38016 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38017 {
38018 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
38019 return false;
38020 }
38021
38022 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
38023 if (!in_array(strtolower(preg_replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) {
38024 return false;
38025 }
38026
38027 if (!extension_loaded('openssl')) {
38028 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
38029
38030 return false;
38031 }
38032
38033 return true;
38034 }
38035
38036
38037
38038
38039
38040
38041 public function getRepoData()
38042 {
38043 $this->fetchRootIdentifier();
38044
38045 return $this->repoData;
38046 }
38047
38048
38049
38050
38051
38052
38053 protected function generateSshUrl()
38054 {
38055 if (false !== strpos($this->originUrl, ':')) {
38056 return 'ssh://git@' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
38057 }
38058
38059 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
38060 }
38061
38062
38063
38064
38065 protected function getContents($url, $fetchingRepoData = false)
38066 {
38067 try {
38068 return parent::getContents($url);
38069 } catch (TransportException $e) {
38070 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
38071
38072 switch ($e->getCode()) {
38073 case 401:
38074 case 404:
38075
38076  if (!$fetchingRepoData) {
38077 throw $e;
38078 }
38079
38080 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
38081 return parent::getContents($url);
38082 }
38083
38084 if (!$this->io->isInteractive()) {
38085 return $this->attemptCloneFallback();
38086 }
38087
38088 $scopesIssued = array();
38089 $scopesNeeded = array();
38090 if ($headers = $e->getHeaders()) {
38091 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
38092 $scopesIssued = explode(' ', $scopes);
38093 }
38094 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
38095 $scopesNeeded = explode(' ', $scopes);
38096 }
38097 }
38098 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
38099
38100  
38101  if (!$headers || !count($scopesNeeded) || count($scopesFailed)) {
38102 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
38103 }
38104
38105 return parent::getContents($url);
38106
38107 case 403:
38108 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
38109 return parent::getContents($url);
38110 }
38111
38112 if (!$this->io->isInteractive() && $fetchingRepoData) {
38113 return $this->attemptCloneFallback();
38114 }
38115
38116 $rateLimited = $gitHubUtil->isRateLimited($e->getHeaders());
38117
38118 if (!$this->io->hasAuthentication($this->originUrl)) {
38119 if (!$this->io->isInteractive()) {
38120 $this->io->writeError('<error>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</error>');
38121 throw $e;
38122 }
38123
38124 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
38125
38126 return parent::getContents($url);
38127 }
38128
38129 if ($rateLimited) {
38130 $rateLimit = $gitHubUtil->getRateLimit($e->getHeaders());
38131 $this->io->writeError(sprintf(
38132 '<error>GitHub API limit (%d calls/hr) is exhausted. You are already authorized so you have to wait until %s before doing more requests</error>',
38133 $rateLimit['limit'],
38134 $rateLimit['reset']
38135 ));
38136 }
38137
38138 throw $e;
38139
38140 default:
38141 throw $e;
38142 }
38143 }
38144 }
38145
38146
38147
38148
38149
38150
38151 protected function fetchRootIdentifier()
38152 {
38153 if ($this->repoData) {
38154 return;
38155 }
38156
38157 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
38158
38159 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
38160 if (null === $this->repoData && null !== $this->gitDriver) {
38161 return;
38162 }
38163
38164 $this->owner = $this->repoData['owner']['login'];
38165 $this->repository = $this->repoData['name'];
38166
38167 $this->isPrivate = !empty($this->repoData['private']);
38168 if (isset($this->repoData['default_branch'])) {
38169 $this->rootIdentifier = $this->repoData['default_branch'];
38170 } elseif (isset($this->repoData['master_branch'])) {
38171 $this->rootIdentifier = $this->repoData['master_branch'];
38172 } else {
38173 $this->rootIdentifier = 'master';
38174 }
38175 $this->hasIssues = !empty($this->repoData['has_issues']);
38176 }
38177
38178 protected function attemptCloneFallback()
38179 {
38180 $this->isPrivate = true;
38181
38182 try {
38183
38184  
38185  
38186  
38187  $this->setupGitDriver($this->generateSshUrl());
38188
38189 return;
38190 } catch (\RuntimeException $e) {
38191 $this->gitDriver = null;
38192
38193 $this->io->writeError('<error>Failed to clone the '.$this->generateSshUrl().' repository, try running in interactive mode so that you can enter your GitHub credentials</error>');
38194 throw $e;
38195 }
38196 }
38197
38198 protected function setupGitDriver($url)
38199 {
38200 $this->gitDriver = new GitDriver(
38201 array('url' => $url),
38202 $this->io,
38203 $this->config,
38204 $this->process,
38205 $this->remoteFilesystem
38206 );
38207 $this->gitDriver->initialize();
38208 }
38209
38210 protected function getNextPage()
38211 {
38212 $headers = $this->remoteFilesystem->getLastHeaders();
38213 foreach ($headers as $header) {
38214 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
38215 $links = explode(',', $match[1]);
38216 foreach ($links as $link) {
38217 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
38218 return $match[1];
38219 }
38220 }
38221 }
38222 }
38223 }
38224 }
38225 <?php
38226
38227
38228
38229
38230
38231
38232
38233
38234
38235
38236
38237 namespace Composer\Repository\Vcs;
38238
38239 use Composer\Config;
38240 use Composer\Cache;
38241 use Composer\IO\IOInterface;
38242 use Composer\Json\JsonFile;
38243 use Composer\Downloader\TransportException;
38244 use Composer\Util\RemoteFilesystem;
38245 use Composer\Util\GitLab;
38246
38247
38248
38249
38250
38251
38252
38253 class GitLabDriver extends VcsDriver
38254 {
38255 private $scheme;
38256 private $namespace;
38257 private $repository;
38258
38259
38260
38261
38262 private $project;
38263
38264
38265
38266
38267 private $commits = array();
38268
38269
38270
38271
38272 private $tags;
38273
38274
38275
38276
38277 private $branches;
38278
38279
38280
38281
38282
38283
38284 protected $gitDriver;
38285
38286
38287
38288
38289
38290
38291 private $isPrivate = true;
38292
38293
38294
38295
38296 private $hasNonstandardOrigin = false;
38297
38298 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
38299
38300
38301
38302
38303
38304
38305
38306
38307 public function initialize()
38308 {
38309 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
38310 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
38311 }
38312
38313 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
38314 $configuredDomains = $this->config->get('gitlab-domains');
38315 $urlParts = explode('/', $match['parts']);
38316
38317 $this->scheme = !empty($match['scheme'])
38318 ? $match['scheme']
38319 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
38320 ;
38321 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts, $match['port']);
38322
38323 if (false !== strpos($this->originUrl, ':') || false !== strpos($this->originUrl, '/')) {
38324 $this->hasNonstandardOrigin = true;
38325 }
38326
38327 $this->namespace = implode('/', $urlParts);
38328 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
38329
38330 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
38331
38332 $this->fetchProject();
38333 }
38334
38335
38336
38337
38338
38339
38340
38341 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
38342 {
38343 $this->remoteFilesystem = $remoteFilesystem;
38344 }
38345
38346
38347
38348
38349 public function getFileContent($file, $identifier)
38350 {
38351 if ($this->gitDriver) {
38352 return $this->gitDriver->getFileContent($file, $identifier);
38353 }
38354
38355
38356  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
38357 $branches = $this->getBranches();
38358 if (isset($branches[$identifier])) {
38359 $identifier = $branches[$identifier];
38360 }
38361 }
38362
38363 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
38364
38365 try {
38366 $content = $this->getContents($resource);
38367 } catch (TransportException $e) {
38368 if ($e->getCode() !== 404) {
38369 throw $e;
38370 }
38371
38372 return null;
38373 }
38374
38375 return $content;
38376 }
38377
38378
38379
38380
38381 public function getChangeDate($identifier)
38382 {
38383 if ($this->gitDriver) {
38384 return $this->gitDriver->getChangeDate($identifier);
38385 }
38386
38387 if (isset($this->commits[$identifier])) {
38388 return new \DateTime($this->commits[$identifier]['committed_date']);
38389 }
38390
38391 return new \DateTime();
38392 }
38393
38394
38395
38396
38397 public function getRepositoryUrl()
38398 {
38399 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
38400 }
38401
38402
38403
38404
38405 public function getUrl()
38406 {
38407 if ($this->gitDriver) {
38408 return $this->gitDriver->getUrl();
38409 }
38410
38411 return $this->project['web_url'];
38412 }
38413
38414
38415
38416
38417 public function getDist($identifier)
38418 {
38419 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
38420
38421 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
38422 }
38423
38424
38425
38426
38427 public function getSource($identifier)
38428 {
38429 if ($this->gitDriver) {
38430 return $this->gitDriver->getSource($identifier);
38431 }
38432
38433 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
38434 }
38435
38436
38437
38438
38439 public function getRootIdentifier()
38440 {
38441 if ($this->gitDriver) {
38442 return $this->gitDriver->getRootIdentifier();
38443 }
38444
38445 return $this->project['default_branch'];
38446 }
38447
38448
38449
38450
38451 public function getBranches()
38452 {
38453 if ($this->gitDriver) {
38454 return $this->gitDriver->getBranches();
38455 }
38456
38457 if (!$this->branches) {
38458 $this->branches = $this->getReferences('branches');
38459 }
38460
38461 return $this->branches;
38462 }
38463
38464
38465
38466
38467 public function getTags()
38468 {
38469 if ($this->gitDriver) {
38470 return $this->gitDriver->getTags();
38471 }
38472
38473 if (!$this->tags) {
38474 $this->tags = $this->getReferences('tags');
38475 }
38476
38477 return $this->tags;
38478 }
38479
38480
38481
38482
38483 public function getApiUrl()
38484 {
38485 return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
38486 }
38487
38488
38489
38490
38491
38492
38493
38494 private function urlEncodeAll($string)
38495 {
38496 $encoded = '';
38497 for ($i = 0; isset($string[$i]); $i++) {
38498 $character = $string[$i];
38499 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
38500 $character = '%' . sprintf('%02X', ord($character));
38501 }
38502 $encoded .= $character;
38503 }
38504
38505 return $encoded;
38506 }
38507
38508
38509
38510
38511
38512
38513 protected function getReferences($type)
38514 {
38515 $perPage = 100;
38516 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
38517
38518 $references = array();
38519 do {
38520 $data = JsonFile::parseJson($this->getContents($resource), $resource);
38521
38522 foreach ($data as $datum) {
38523 $references[$datum['name']] = $datum['commit']['id'];
38524
38525
38526  
38527  $this->commits[$datum['commit']['id']] = $datum['commit'];
38528 }
38529
38530 if (count($data) >= $perPage) {
38531 $resource = $this->getNextPage();
38532 } else {
38533 $resource = false;
38534 }
38535 } while ($resource);
38536
38537 return $references;
38538 }
38539
38540 protected function fetchProject()
38541 {
38542
38543  $resource = $this->getApiUrl();
38544 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
38545 if (isset($this->project['visibility'])) {
38546 $this->isPrivate = $this->project['visibility'] !== 'public';
38547 } else {
38548
38549  $this->isPrivate = false;
38550 }
38551 }
38552
38553 protected function attemptCloneFallback()
38554 {
38555 try {
38556 if ($this->isPrivate === false) {
38557 $url = $this->generatePublicUrl();
38558 } else {
38559 $url = $this->generateSshUrl();
38560 }
38561
38562
38563  
38564  
38565  $this->setupGitDriver($url);
38566
38567 return;
38568 } catch (\RuntimeException $e) {
38569 $this->gitDriver = null;
38570
38571 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
38572 throw $e;
38573 }
38574 }
38575
38576
38577
38578
38579
38580
38581 protected function generateSshUrl()
38582 {
38583 if ($this->hasNonstandardOrigin) {
38584 return 'ssh://git@'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository.'.git';
38585 }
38586
38587 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
38588 }
38589
38590 protected function generatePublicUrl()
38591 {
38592 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
38593 }
38594
38595 protected function setupGitDriver($url)
38596 {
38597 $this->gitDriver = new GitDriver(
38598 array('url' => $url),
38599 $this->io,
38600 $this->config,
38601 $this->process,
38602 $this->remoteFilesystem
38603 );
38604 $this->gitDriver->initialize();
38605 }
38606
38607
38608
38609
38610 protected function getContents($url, $fetchingRepoData = false)
38611 {
38612 try {
38613 $res = parent::getContents($url);
38614
38615 if ($fetchingRepoData) {
38616 $json = JsonFile::parseJson($res, $url);
38617
38618
38619  if (!isset($json['default_branch'])) {
38620 if (!empty($json['id'])) {
38621 $this->isPrivate = false;
38622 }
38623
38624 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
38625 }
38626 }
38627
38628 return $res;
38629 } catch (TransportException $e) {
38630 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
38631
38632 switch ($e->getCode()) {
38633 case 401:
38634 case 404:
38635
38636  if (!$fetchingRepoData) {
38637 throw $e;
38638 }
38639
38640 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
38641 return parent::getContents($url);
38642 }
38643
38644 if (!$this->io->isInteractive()) {
38645 return $this->attemptCloneFallback();
38646 }
38647 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
38648 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
38649
38650 return parent::getContents($url);
38651
38652 case 403:
38653 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
38654 return parent::getContents($url);
38655 }
38656
38657 if (!$this->io->isInteractive() && $fetchingRepoData) {
38658 return $this->attemptCloneFallback();
38659 }
38660
38661 throw $e;
38662
38663 default:
38664 throw $e;
38665 }
38666 }
38667 }
38668
38669
38670
38671
38672
38673
38674
38675 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38676 {
38677 if (!preg_match(self::URL_REGEX, $url, $match)) {
38678 return false;
38679 }
38680
38681 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
38682 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
38683 $urlParts = explode('/', $match['parts']);
38684
38685 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts, $match['port'])) {
38686 return false;
38687 }
38688
38689 if ('https' === $scheme && !extension_loaded('openssl')) {
38690 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
38691
38692 return false;
38693 }
38694
38695 return true;
38696 }
38697
38698 private function getNextPage()
38699 {
38700 $headers = $this->remoteFilesystem->getLastHeaders();
38701 foreach ($headers as $header) {
38702 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
38703 $links = explode(',', $match[1]);
38704 foreach ($links as $link) {
38705 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
38706 return $match[1];
38707 }
38708 }
38709 }
38710 }
38711 }
38712
38713
38714
38715
38716
38717
38718
38719 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts, $portNumber)
38720 {
38721 $guessedDomain = strtolower($guessedDomain);
38722
38723 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array($guessedDomain.':'.$portNumber, $configuredDomains))) {
38724 if ($portNumber) {
38725 return $guessedDomain.':'.$portNumber;
38726 }
38727 return $guessedDomain;
38728 }
38729
38730 if ($portNumber) {
38731 $guessedDomain .= ':'.$portNumber;
38732 }
38733
38734 while (null !== ($part = array_shift($urlParts))) {
38735 $guessedDomain .= '/' . $part;
38736
38737 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array(preg_replace('{:\d+}', '', $guessedDomain), $configuredDomains))) {
38738 return $guessedDomain;
38739 }
38740 }
38741
38742 return false;
38743 }
38744 }
38745 <?php
38746
38747
38748
38749
38750
38751
38752
38753
38754
38755
38756
38757 namespace Composer\Repository\Vcs;
38758
38759 use Composer\Config;
38760 use Composer\IO\IOInterface;
38761
38762
38763
38764
38765 class HgBitbucketDriver extends BitbucketDriver
38766 {
38767
38768
38769
38770 public function getRootIdentifier()
38771 {
38772 if ($this->fallbackDriver) {
38773 return $this->fallbackDriver->getRootIdentifier();
38774 }
38775
38776 if (null === $this->rootIdentifier) {
38777 if (! $this->getRepoData()) {
38778 return $this->fallbackDriver->getRootIdentifier();
38779 }
38780
38781 if ($this->vcsType !== 'hg') {
38782 throw new \RuntimeException(
38783 $this->url.' does not appear to be a mercurial repository, use '.
38784 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
38785 );
38786 }
38787
38788 $mainBranchData = $this->getMainBranchData();
38789 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
38790 }
38791
38792 return $this->rootIdentifier;
38793 }
38794
38795
38796
38797
38798 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38799 {
38800 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#i', $url)) {
38801 return false;
38802 }
38803
38804 if (!extension_loaded('openssl')) {
38805 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
38806
38807 return false;
38808 }
38809
38810 return true;
38811 }
38812
38813
38814
38815
38816 protected function setupFallbackDriver($url)
38817 {
38818 $this->fallbackDriver = new HgDriver(
38819 array('url' => $url),
38820 $this->io,
38821 $this->config,
38822 $this->process,
38823 $this->remoteFilesystem
38824 );
38825 $this->fallbackDriver->initialize();
38826 }
38827
38828
38829
38830
38831 protected function generateSshUrl()
38832 {
38833 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
38834 }
38835 }
38836 <?php
38837
38838
38839
38840
38841
38842
38843
38844
38845
38846
38847
38848 namespace Composer\Repository\Vcs;
38849
38850 use Composer\Config;
38851 use Composer\Cache;
38852 use Composer\Util\Hg as HgUtils;
38853 use Composer\Util\ProcessExecutor;
38854 use Composer\Util\Filesystem;
38855 use Composer\IO\IOInterface;
38856
38857
38858
38859
38860 class HgDriver extends VcsDriver
38861 {
38862 protected $tags;
38863 protected $branches;
38864 protected $rootIdentifier;
38865 protected $repoDir;
38866 protected $infoCache = array();
38867
38868
38869
38870
38871 public function initialize()
38872 {
38873 if (Filesystem::isLocalPath($this->url)) {
38874 $this->repoDir = $this->url;
38875 } else {
38876 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
38877 throw new \RuntimeException('HgDriver requires a usable cache directory, and it looks like you set it to be disabled');
38878 }
38879
38880 $cacheDir = $this->config->get('cache-vcs-dir');
38881 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
38882
38883 $fs = new Filesystem();
38884 $fs->ensureDirectoryExists($cacheDir);
38885
38886 if (!is_writable(dirname($this->repoDir))) {
38887 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
38888 }
38889
38890
38891  $this->config->prohibitUrlByConfig($this->url, $this->io);
38892
38893 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
38894
38895
38896  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
38897 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
38898 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
38899 }
38900 } else {
38901
38902  $fs->removeDirectory($this->repoDir);
38903
38904 $repoDir = $this->repoDir;
38905 $command = function ($url) use ($repoDir) {
38906 return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
38907 };
38908
38909 $hgUtils->runCommand($command, $this->url, null);
38910 }
38911 }
38912
38913 $this->getTags();
38914 $this->getBranches();
38915 }
38916
38917
38918
38919
38920 public function getRootIdentifier()
38921 {
38922 if (null === $this->rootIdentifier) {
38923 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
38924 $output = $this->process->splitLines($output);
38925 $this->rootIdentifier = $output[0];
38926 }
38927
38928 return $this->rootIdentifier;
38929 }
38930
38931
38932
38933
38934 public function getUrl()
38935 {
38936 return $this->url;
38937 }
38938
38939
38940
38941
38942 public function getSource($identifier)
38943 {
38944 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
38945 }
38946
38947
38948
38949
38950 public function getDist($identifier)
38951 {
38952 return null;
38953 }
38954
38955
38956
38957
38958 public function getFileContent($file, $identifier)
38959 {
38960 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
38961 $this->process->execute($resource, $content, $this->repoDir);
38962
38963 if (!trim($content)) {
38964 return;
38965 }
38966
38967 return $content;
38968 }
38969
38970
38971
38972
38973 public function getChangeDate($identifier)
38974 {
38975 $this->process->execute(
38976 sprintf(
38977 'hg log --template "{date|rfc3339date}" -r %s',
38978 ProcessExecutor::escape($identifier)
38979 ),
38980 $output,
38981 $this->repoDir
38982 );
38983
38984 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
38985 }
38986
38987
38988
38989
38990 public function getTags()
38991 {
38992 if (null === $this->tags) {
38993 $tags = array();
38994
38995 $this->process->execute('hg tags', $output, $this->repoDir);
38996 foreach ($this->process->splitLines($output) as $tag) {
38997 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
38998 $tags[$match[1]] = $match[2];
38999 }
39000 }
39001 unset($tags['tip']);
39002
39003 $this->tags = $tags;
39004 }
39005
39006 return $this->tags;
39007 }
39008
39009
39010
39011
39012 public function getBranches()
39013 {
39014 if (null === $this->branches) {
39015 $branches = array();
39016 $bookmarks = array();
39017
39018 $this->process->execute('hg branches', $output, $this->repoDir);
39019 foreach ($this->process->splitLines($output) as $branch) {
39020 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
39021 $branches[$match[1]] = $match[2];
39022 }
39023 }
39024
39025 $this->process->execute('hg bookmarks', $output, $this->repoDir);
39026 foreach ($this->process->splitLines($output) as $branch) {
39027 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
39028 $bookmarks[$match[1]] = $match[2];
39029 }
39030 }
39031
39032
39033  $this->branches = array_merge($bookmarks, $branches);
39034 }
39035
39036 return $this->branches;
39037 }
39038
39039
39040
39041
39042 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39043 {
39044 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
39045 return true;
39046 }
39047
39048
39049  if (Filesystem::isLocalPath($url)) {
39050 $url = Filesystem::getPlatformPath($url);
39051 if (!is_dir($url)) {
39052 return false;
39053 }
39054
39055 $process = new ProcessExecutor($io);
39056
39057  if ($process->execute('hg summary', $output, $url) === 0) {
39058 return true;
39059 }
39060 }
39061
39062 if (!$deep) {
39063 return false;
39064 }
39065
39066 $processExecutor = new ProcessExecutor($io);
39067 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
39068
39069 return $exit === 0;
39070 }
39071 }
39072 <?php
39073
39074
39075
39076
39077
39078
39079
39080
39081
39082
39083
39084 namespace Composer\Repository\Vcs;
39085
39086 use Composer\Config;
39087 use Composer\Cache;
39088 use Composer\IO\IOInterface;
39089 use Composer\Util\ProcessExecutor;
39090 use Composer\Util\Perforce;
39091
39092
39093
39094
39095 class PerforceDriver extends VcsDriver
39096 {
39097 protected $depot;
39098 protected $branch;
39099
39100 protected $perforce;
39101
39102
39103
39104
39105 public function initialize()
39106 {
39107 $this->depot = $this->repoConfig['depot'];
39108 $this->branch = '';
39109 if (!empty($this->repoConfig['branch'])) {
39110 $this->branch = $this->repoConfig['branch'];
39111 }
39112
39113 $this->initPerforce($this->repoConfig);
39114 $this->perforce->p4Login();
39115 $this->perforce->checkStream();
39116
39117 $this->perforce->writeP4ClientSpec();
39118 $this->perforce->connectClient();
39119
39120 return true;
39121 }
39122
39123 private function initPerforce($repoConfig)
39124 {
39125 if (!empty($this->perforce)) {
39126 return;
39127 }
39128
39129 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
39130 throw new \RuntimeException('PerforceDriver requires a usable cache directory, and it looks like you set it to be disabled');
39131 }
39132
39133 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
39134 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
39135 }
39136
39137
39138
39139
39140 public function getFileContent($file, $identifier)
39141 {
39142 return $this->perforce->getFileContent($file, $identifier);
39143 }
39144
39145
39146
39147
39148 public function getChangeDate($identifier)
39149 {
39150 return null;
39151 }
39152
39153
39154
39155
39156 public function getRootIdentifier()
39157 {
39158 return $this->branch;
39159 }
39160
39161
39162
39163
39164 public function getBranches()
39165 {
39166 return $this->perforce->getBranches();
39167 }
39168
39169
39170
39171
39172 public function getTags()
39173 {
39174 return $this->perforce->getTags();
39175 }
39176
39177
39178
39179
39180 public function getDist($identifier)
39181 {
39182 return null;
39183 }
39184
39185
39186
39187
39188 public function getSource($identifier)
39189 {
39190 $source = array(
39191 'type' => 'perforce',
39192 'url' => $this->repoConfig['url'],
39193 'reference' => $identifier,
39194 'p4user' => $this->perforce->getUser(),
39195 );
39196
39197 return $source;
39198 }
39199
39200
39201
39202
39203 public function getUrl()
39204 {
39205 return $this->url;
39206 }
39207
39208
39209
39210
39211 public function hasComposerFile($identifier)
39212 {
39213 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
39214 $composerInfoIdentifier = $identifier;
39215
39216 return !empty($composerInfo);
39217 }
39218
39219
39220
39221
39222 public function getContents($url)
39223 {
39224 return false;
39225 }
39226
39227
39228
39229
39230 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39231 {
39232 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
39233 return Perforce::checkServerExists($url, new ProcessExecutor($io));
39234 }
39235
39236 return false;
39237 }
39238
39239
39240
39241
39242 public function cleanup()
39243 {
39244 $this->perforce->cleanupClientSpec();
39245 $this->perforce = null;
39246 }
39247
39248 public function getDepot()
39249 {
39250 return $this->depot;
39251 }
39252
39253 public function getBranch()
39254 {
39255 return $this->branch;
39256 }
39257 }
39258 <?php
39259
39260
39261
39262
39263
39264
39265
39266
39267
39268
39269
39270 namespace Composer\Repository\Vcs;
39271
39272 use Composer\Cache;
39273 use Composer\Config;
39274 use Composer\Json\JsonFile;
39275 use Composer\Util\ProcessExecutor;
39276 use Composer\Util\Filesystem;
39277 use Composer\Util\Svn as SvnUtil;
39278 use Composer\IO\IOInterface;
39279 use Composer\Downloader\TransportException;
39280
39281
39282
39283
39284
39285 class SvnDriver extends VcsDriver
39286 {
39287
39288
39289
39290 protected $cache;
39291 protected $baseUrl;
39292 protected $tags;
39293 protected $branches;
39294 protected $rootIdentifier;
39295 protected $infoCache = array();
39296
39297 protected $trunkPath = 'trunk';
39298 protected $branchesPath = 'branches';
39299 protected $tagsPath = 'tags';
39300 protected $packagePath = '';
39301 protected $cacheCredentials = true;
39302
39303
39304
39305
39306 private $util;
39307
39308
39309
39310
39311 public function initialize()
39312 {
39313 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
39314
39315 SvnUtil::cleanEnv();
39316
39317 if (isset($this->repoConfig['trunk-path'])) {
39318 $this->trunkPath = $this->repoConfig['trunk-path'];
39319 }
39320 if (isset($this->repoConfig['branches-path'])) {
39321 $this->branchesPath = $this->repoConfig['branches-path'];
39322 }
39323 if (isset($this->repoConfig['tags-path'])) {
39324 $this->tagsPath = $this->repoConfig['tags-path'];
39325 }
39326 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
39327 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
39328 }
39329 if (isset($this->repoConfig['package-path'])) {
39330 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
39331 }
39332
39333 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
39334 $this->baseUrl = substr($this->url, 0, $pos);
39335 }
39336
39337 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
39338
39339 $this->getBranches();
39340 $this->getTags();
39341 }
39342
39343
39344
39345
39346 public function getRootIdentifier()
39347 {
39348 return $this->rootIdentifier ?: $this->trunkPath;
39349 }
39350
39351
39352
39353
39354 public function getUrl()
39355 {
39356 return $this->url;
39357 }
39358
39359
39360
39361
39362 public function getSource($identifier)
39363 {
39364 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
39365 }
39366
39367
39368
39369
39370 public function getDist($identifier)
39371 {
39372 return null;
39373 }
39374
39375
39376
39377
39378 protected function shouldCache($identifier)
39379 {
39380 return $this->cache && preg_match('{@\d+$}', $identifier);
39381 }
39382
39383
39384
39385
39386 public function getComposerInformation($identifier)
39387 {
39388 if (!isset($this->infoCache[$identifier])) {
39389 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier.'.json')) {
39390 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
39391 }
39392
39393 try {
39394 $composer = $this->getBaseComposerInformation($identifier);
39395 } catch (TransportException $e) {
39396 $message = $e->getMessage();
39397 if (stripos($message, 'path not found') === false && stripos($message, 'svn: warning: W160013') === false) {
39398 throw $e;
39399 }
39400
39401  $composer = '';
39402 }
39403
39404 if ($this->shouldCache($identifier)) {
39405 $this->cache->write($identifier.'.json', json_encode($composer));
39406 }
39407
39408 $this->infoCache[$identifier] = $composer;
39409 }
39410
39411 return $this->infoCache[$identifier];
39412 }
39413
39414
39415
39416
39417
39418 public function getFileContent($file, $identifier)
39419 {
39420 $identifier = '/' . trim($identifier, '/') . '/';
39421
39422 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
39423 if (!empty($match[2])) {
39424 $path = $match[1];
39425 $rev = $match[2];
39426 } else {
39427 $path = $identifier;
39428 $rev = '';
39429 }
39430
39431 try {
39432 $resource = $path.$file;
39433 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
39434 if (!trim($output)) {
39435 return null;
39436 }
39437 } catch (\RuntimeException $e) {
39438 throw new TransportException($e->getMessage());
39439 }
39440
39441 return $output;
39442 }
39443
39444
39445
39446
39447 public function getChangeDate($identifier)
39448 {
39449 $identifier = '/' . trim($identifier, '/') . '/';
39450
39451 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
39452 if (!empty($match[2])) {
39453 $path = $match[1];
39454 $rev = $match[2];
39455 } else {
39456 $path = $identifier;
39457 $rev = '';
39458 }
39459
39460 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
39461 foreach ($this->process->splitLines($output) as $line) {
39462 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
39463 return new \DateTime($match[1], new \DateTimeZone('UTC'));
39464 }
39465 }
39466
39467 return null;
39468 }
39469
39470
39471
39472
39473 public function getTags()
39474 {
39475 if (null === $this->tags) {
39476 $this->tags = array();
39477
39478 if ($this->tagsPath !== false) {
39479 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
39480 if ($output) {
39481 foreach ($this->process->splitLines($output) as $line) {
39482 $line = trim($line);
39483 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
39484 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
39485 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
39486 '/' . $this->tagsPath . '/' . $match[2],
39487 $match[1]
39488 );
39489 }
39490 }
39491 }
39492 }
39493 }
39494 }
39495
39496 return $this->tags;
39497 }
39498
39499
39500
39501
39502 public function getBranches()
39503 {
39504 if (null === $this->branches) {
39505 $this->branches = array();
39506
39507 if (false === $this->trunkPath) {
39508 $trunkParent = $this->baseUrl . '/';
39509 } else {
39510 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
39511 }
39512
39513 $output = $this->execute('svn ls --verbose', $trunkParent);
39514 if ($output) {
39515 foreach ($this->process->splitLines($output) as $line) {
39516 $line = trim($line);
39517 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
39518 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
39519 $this->branches['trunk'] = $this->buildIdentifier(
39520 '/' . $this->trunkPath,
39521 $match[1]
39522 );
39523 $this->rootIdentifier = $this->branches['trunk'];
39524 break;
39525 }
39526 }
39527 }
39528 }
39529 unset($output);
39530
39531 if ($this->branchesPath !== false) {
39532 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
39533 if ($output) {
39534 foreach ($this->process->splitLines(trim($output)) as $line) {
39535 $line = trim($line);
39536 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
39537 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
39538 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
39539 '/' . $this->branchesPath . '/' . $match[2],
39540 $match[1]
39541 );
39542 }
39543 }
39544 }
39545 }
39546 }
39547 }
39548
39549 return $this->branches;
39550 }
39551
39552
39553
39554
39555 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39556 {
39557 $url = self::normalizeUrl($url);
39558 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
39559 return true;
39560 }
39561
39562
39563  if (!$deep && !Filesystem::isLocalPath($url)) {
39564 return false;
39565 }
39566
39567 $processExecutor = new ProcessExecutor($io);
39568
39569 $exit = $processExecutor->execute(
39570 "svn info --non-interactive ".ProcessExecutor::escape($url),
39571 $ignoredOutput
39572 );
39573
39574 if ($exit === 0) {
39575
39576  return true;
39577 }
39578
39579
39580  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
39581
39582  
39583  return true;
39584 }
39585
39586
39587  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
39588
39589  
39590  return true;
39591 }
39592
39593 return false;
39594 }
39595
39596
39597
39598
39599
39600
39601
39602
39603 protected static function normalizeUrl($url)
39604 {
39605 $fs = new Filesystem();
39606 if ($fs->isAbsolutePath($url)) {
39607 return 'file://' . strtr($url, '\\', '/');
39608 }
39609
39610 return $url;
39611 }
39612
39613
39614
39615
39616
39617
39618
39619
39620
39621
39622 protected function execute($command, $url)
39623 {
39624 if (null === $this->util) {
39625 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
39626 $this->util->setCacheCredentials($this->cacheCredentials);
39627 }
39628
39629 try {
39630 return $this->util->execute($command, $url);
39631 } catch (\RuntimeException $e) {
39632 if (null === $this->util->binaryVersion()) {
39633 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());
39634 }
39635
39636 throw new \RuntimeException(
39637 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
39638 );
39639 }
39640 }
39641
39642
39643
39644
39645
39646
39647
39648
39649
39650 protected function buildIdentifier($baseDir, $revision)
39651 {
39652 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
39653 }
39654 }
39655 <?php
39656
39657
39658
39659
39660
39661
39662
39663
39664
39665
39666
39667 namespace Composer\Repository\Vcs;
39668
39669 use Composer\Cache;
39670 use Composer\Downloader\TransportException;
39671 use Composer\Config;
39672 use Composer\Factory;
39673 use Composer\IO\IOInterface;
39674 use Composer\Json\JsonFile;
39675 use Composer\Util\ProcessExecutor;
39676 use Composer\Util\RemoteFilesystem;
39677 use Composer\Util\Filesystem;
39678
39679
39680
39681
39682
39683
39684 abstract class VcsDriver implements VcsDriverInterface
39685 {
39686
39687 protected $url;
39688
39689 protected $originUrl;
39690
39691 protected $repoConfig;
39692
39693 protected $io;
39694
39695 protected $config;
39696
39697 protected $process;
39698
39699 protected $remoteFilesystem;
39700
39701 protected $infoCache = array();
39702
39703 protected $cache;
39704
39705
39706
39707
39708
39709
39710
39711
39712
39713
39714 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
39715 {
39716 if (Filesystem::isLocalPath($repoConfig['url'])) {
39717 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
39718 }
39719
39720 $this->url = $repoConfig['url'];
39721 $this->originUrl = $repoConfig['url'];
39722 $this->repoConfig = $repoConfig;
39723 $this->io = $io;
39724 $this->config = $config;
39725 $this->process = $process ?: new ProcessExecutor($io);
39726 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
39727 }
39728
39729
39730
39731
39732
39733
39734
39735 protected function shouldCache($identifier)
39736 {
39737 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
39738 }
39739
39740
39741
39742
39743 public function getComposerInformation($identifier)
39744 {
39745 if (!isset($this->infoCache[$identifier])) {
39746 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
39747 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
39748 }
39749
39750 $composer = $this->getBaseComposerInformation($identifier);
39751
39752 if ($this->shouldCache($identifier)) {
39753 $this->cache->write($identifier, json_encode($composer));
39754 }
39755
39756 $this->infoCache[$identifier] = $composer;
39757 }
39758
39759 return $this->infoCache[$identifier];
39760 }
39761
39762 protected function getBaseComposerInformation($identifier)
39763 {
39764 $composerFileContent = $this->getFileContent('composer.json', $identifier);
39765
39766 if (!$composerFileContent) {
39767 return null;
39768 }
39769
39770 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
39771
39772 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
39773 $composer['time'] = $changeDate->format(DATE_RFC3339);
39774 }
39775
39776 return $composer;
39777 }
39778
39779
39780
39781
39782 public function hasComposerFile($identifier)
39783 {
39784 try {
39785 return (bool) $this->getComposerInformation($identifier);
39786 } catch (TransportException $e) {
39787 }
39788
39789 return false;
39790 }
39791
39792
39793
39794
39795
39796
39797
39798
39799 protected function getScheme()
39800 {
39801 if (extension_loaded('openssl')) {
39802 return 'https';
39803 }
39804
39805 return 'http';
39806 }
39807
39808
39809
39810
39811
39812
39813
39814
39815 protected function getContents($url)
39816 {
39817 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
39818
39819 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
39820 }
39821
39822
39823
39824
39825 public function cleanup()
39826 {
39827 return;
39828 }
39829 }
39830 <?php
39831
39832
39833
39834
39835
39836
39837
39838
39839
39840
39841
39842 namespace Composer\Repository\Vcs;
39843
39844 use Composer\Config;
39845 use Composer\IO\IOInterface;
39846
39847
39848
39849
39850 interface VcsDriverInterface
39851 {
39852
39853
39854
39855 public function initialize();
39856
39857
39858
39859
39860
39861
39862
39863 public function getComposerInformation($identifier);
39864
39865
39866
39867
39868
39869
39870
39871
39872 public function getFileContent($file, $identifier);
39873
39874
39875
39876
39877
39878
39879
39880 public function getChangeDate($identifier);
39881
39882
39883
39884
39885
39886
39887 public function getRootIdentifier();
39888
39889
39890
39891
39892
39893
39894 public function getBranches();
39895
39896
39897
39898
39899
39900
39901 public function getTags();
39902
39903
39904
39905
39906
39907 public function getDist($identifier);
39908
39909
39910
39911
39912
39913 public function getSource($identifier);
39914
39915
39916
39917
39918
39919
39920 public function getUrl();
39921
39922
39923
39924
39925
39926
39927
39928
39929 public function hasComposerFile($identifier);
39930
39931
39932
39933
39934 public function cleanup();
39935
39936
39937
39938
39939
39940
39941
39942
39943
39944
39945 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
39946 }
39947 <?php
39948
39949
39950
39951
39952
39953
39954
39955
39956
39957
39958
39959 namespace Composer\Repository;
39960
39961 use Composer\Downloader\TransportException;
39962 use Composer\Repository\Vcs\VcsDriverInterface;
39963 use Composer\Package\Version\VersionParser;
39964 use Composer\Package\Loader\ArrayLoader;
39965 use Composer\Package\Loader\ValidatingArrayLoader;
39966 use Composer\Package\Loader\InvalidPackageException;
39967 use Composer\Package\Loader\LoaderInterface;
39968 use Composer\EventDispatcher\EventDispatcher;
39969 use Composer\IO\IOInterface;
39970 use Composer\Config;
39971
39972
39973
39974
39975 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
39976 {
39977 protected $url;
39978 protected $packageName;
39979 protected $isVerbose;
39980 protected $isVeryVerbose;
39981 protected $io;
39982 protected $config;
39983 protected $versionParser;
39984 protected $type;
39985 protected $loader;
39986 protected $repoConfig;
39987 protected $branchErrorOccurred = false;
39988 private $drivers;
39989
39990 private $driver;
39991
39992 private $versionCache;
39993 private $emptyReferences = array();
39994
39995 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null, VersionCacheInterface $versionCache = null)
39996 {
39997 parent::__construct();
39998 $this->drivers = $drivers ?: array(
39999 'github' => 'Composer\Repository\Vcs\GitHubDriver',
40000 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
40001 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
40002 'git' => 'Composer\Repository\Vcs\GitDriver',
40003 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
40004 'hg' => 'Composer\Repository\Vcs\HgDriver',
40005 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
40006 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
40007
40008  'svn' => 'Composer\Repository\Vcs\SvnDriver',
40009 );
40010
40011 $this->url = $repoConfig['url'];
40012 $this->io = $io;
40013 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
40014 $this->isVerbose = $io->isVerbose();
40015 $this->isVeryVerbose = $io->isVeryVerbose();
40016 $this->config = $config;
40017 $this->repoConfig = $repoConfig;
40018 $this->versionCache = $versionCache;
40019 }
40020
40021 public function getRepoConfig()
40022 {
40023 return $this->repoConfig;
40024 }
40025
40026 public function setLoader(LoaderInterface $loader)
40027 {
40028 $this->loader = $loader;
40029 }
40030
40031 public function getDriver()
40032 {
40033 if ($this->driver) {
40034 return $this->driver;
40035 }
40036
40037 if (isset($this->drivers[$this->type])) {
40038 $class = $this->drivers[$this->type];
40039 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
40040 $this->driver->initialize();
40041
40042 return $this->driver;
40043 }
40044
40045 foreach ($this->drivers as $driver) {
40046 if ($driver::supports($this->io, $this->config, $this->url)) {
40047 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
40048 $this->driver->initialize();
40049
40050 return $this->driver;
40051 }
40052 }
40053
40054 foreach ($this->drivers as $driver) {
40055 if ($driver::supports($this->io, $this->config, $this->url, true)) {
40056 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
40057 $this->driver->initialize();
40058
40059 return $this->driver;
40060 }
40061 }
40062 }
40063
40064 public function hadInvalidBranches()
40065 {
40066 return $this->branchErrorOccurred;
40067 }
40068
40069 public function getEmptyReferences()
40070 {
40071 return $this->emptyReferences;
40072 }
40073
40074 protected function initialize()
40075 {
40076 parent::initialize();
40077
40078 $isVerbose = $this->isVerbose;
40079 $isVeryVerbose = $this->isVeryVerbose;
40080
40081 $driver = $this->getDriver();
40082 if (!$driver) {
40083 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
40084 }
40085
40086 $this->versionParser = new VersionParser;
40087 if (!$this->loader) {
40088 $this->loader = new ArrayLoader($this->versionParser);
40089 }
40090
40091 try {
40092 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
40093 $data = $driver->getComposerInformation($driver->getRootIdentifier());
40094 $this->packageName = !empty($data['name']) ? $data['name'] : null;
40095 }
40096 } catch (\Exception $e) {
40097 if ($isVeryVerbose) {
40098 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
40099 }
40100 }
40101
40102 foreach ($driver->getTags() as $tag => $identifier) {
40103 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
40104 if ($isVeryVerbose) {
40105 $this->io->writeError($msg);
40106 } elseif ($isVerbose) {
40107 $this->io->overwriteError($msg, false);
40108 }
40109
40110
40111  $tag = str_replace('release-', '', $tag);
40112
40113 $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose);
40114 if ($cachedPackage) {
40115 $this->addPackage($cachedPackage);
40116
40117 continue;
40118 } elseif ($cachedPackage === false) {
40119 $this->emptyReferences[] = $identifier;
40120
40121 continue;
40122 }
40123
40124 if (!$parsedTag = $this->validateTag($tag)) {
40125 if ($isVeryVerbose) {
40126 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
40127 }
40128 continue;
40129 }
40130
40131 try {
40132 if (!$data = $driver->getComposerInformation($identifier)) {
40133 if ($isVeryVerbose) {
40134 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
40135 }
40136 $this->emptyReferences[] = $identifier;
40137 continue;
40138 }
40139
40140
40141  if (isset($data['version'])) {
40142 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
40143 } else {
40144
40145  $data['version'] = $tag;
40146 $data['version_normalized'] = $parsedTag;
40147 }
40148
40149
40150  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
40151 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
40152
40153
40154  if ($data['version_normalized'] !== $parsedTag) {
40155 if ($isVeryVerbose) {
40156 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
40157 }
40158 continue;
40159 }
40160
40161 $tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
40162 if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
40163 if ($isVeryVerbose) {
40164 $this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
40165 }
40166 continue;
40167 }
40168
40169 if ($isVeryVerbose) {
40170 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
40171 }
40172
40173 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
40174 } catch (\Exception $e) {
40175 if ($e instanceof TransportException && $e->getCode() === 404) {
40176 $this->emptyReferences[] = $identifier;
40177 }
40178 if ($isVeryVerbose) {
40179 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
40180 }
40181 continue;
40182 }
40183 }
40184
40185 if (!$isVeryVerbose) {
40186 $this->io->overwriteError('', false);
40187 }
40188
40189 $branches = $driver->getBranches();
40190 foreach ($branches as $branch => $identifier) {
40191 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
40192 if ($isVeryVerbose) {
40193 $this->io->writeError($msg);
40194 } elseif ($isVerbose) {
40195 $this->io->overwriteError($msg, false);
40196 }
40197
40198 if ($branch === 'trunk' && isset($branches['master'])) {
40199 if ($isVeryVerbose) {
40200 $this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
40201 }
40202 continue;
40203 }
40204
40205 if (!$parsedBranch = $this->validateBranch($branch)) {
40206 if ($isVeryVerbose) {
40207 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
40208 }
40209 continue;
40210 }
40211
40212
40213  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
40214 $version = 'dev-' . $branch;
40215 } else {
40216 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
40217 $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
40218 }
40219
40220 $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose);
40221 if ($cachedPackage) {
40222 $this->addPackage($cachedPackage);
40223
40224 continue;
40225 } elseif ($cachedPackage === false) {
40226 $this->emptyReferences[] = $identifier;
40227
40228 continue;
40229 }
40230
40231 try {
40232 if (!$data = $driver->getComposerInformation($identifier)) {
40233 if ($isVeryVerbose) {
40234 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
40235 }
40236 $this->emptyReferences[] = $identifier;
40237 continue;
40238 }
40239
40240
40241  $data['version'] = $version;
40242 $data['version_normalized'] = $parsedBranch;
40243
40244 if ($isVeryVerbose) {
40245 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
40246 }
40247
40248 $packageData = $this->preProcess($driver, $data, $identifier);
40249 $package = $this->loader->load($packageData);
40250 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
40251 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
40252 }
40253 $this->addPackage($package);
40254 } catch (TransportException $e) {
40255 if ($e->getCode() === 404) {
40256 $this->emptyReferences[] = $identifier;
40257 }
40258 if ($isVeryVerbose) {
40259 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
40260 }
40261 continue;
40262 } catch (\Exception $e) {
40263 if (!$isVeryVerbose) {
40264 $this->io->writeError('');
40265 }
40266 $this->branchErrorOccurred = true;
40267 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
40268 $this->io->writeError('');
40269 continue;
40270 }
40271 }
40272 $driver->cleanup();
40273
40274 if (!$isVeryVerbose) {
40275 $this->io->overwriteError('', false);
40276 }
40277
40278 if (!$this->getPackages()) {
40279 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
40280 }
40281 }
40282
40283 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
40284 {
40285
40286  $dataPackageName = isset($data['name']) ? $data['name'] : null;
40287 $data['name'] = $this->packageName ?: $dataPackageName;
40288
40289 if (!isset($data['dist'])) {
40290 $data['dist'] = $driver->getDist($identifier);
40291 }
40292 if (!isset($data['source'])) {
40293 $data['source'] = $driver->getSource($identifier);
40294 }
40295
40296 return $data;
40297 }
40298
40299 private function validateBranch($branch)
40300 {
40301 try {
40302 return $this->versionParser->normalizeBranch($branch);
40303 } catch (\Exception $e) {
40304 }
40305
40306 return false;
40307 }
40308
40309 private function validateTag($version)
40310 {
40311 try {
40312 return $this->versionParser->normalize($version);
40313 } catch (\Exception $e) {
40314 }
40315
40316 return false;
40317 }
40318
40319 private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose)
40320 {
40321 if (!$this->versionCache) {
40322 return;
40323 }
40324
40325 $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
40326 if ($cachedPackage === false) {
40327 if ($isVeryVerbose) {
40328 $this->io->writeError('<warning>Skipped '.$version.', no composer file (cached from ref '.$identifier.')</warning>');
40329 }
40330
40331 return false;
40332 }
40333
40334 if ($cachedPackage) {
40335 $msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
40336 if ($isVeryVerbose) {
40337 $this->io->writeError($msg);
40338 } elseif ($isVerbose) {
40339 $this->io->overwriteError($msg, false);
40340 }
40341
40342 if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) {
40343 if ($isVeryVerbose) {
40344 $this->io->writeError('<warning>Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally</warning>');
40345 }
40346 $cachedPackage = null;
40347 }
40348 }
40349
40350 if ($cachedPackage) {
40351 return $this->loader->load($cachedPackage);
40352 }
40353
40354 return null;
40355 }
40356 }
40357 <?php
40358
40359
40360
40361
40362
40363
40364
40365
40366
40367
40368
40369 namespace Composer\Repository;
40370
40371 interface VersionCacheInterface
40372 {
40373
40374
40375
40376
40377
40378 public function getVersionPackage($version, $identifier);
40379 }
40380 <?php
40381
40382
40383
40384
40385
40386
40387
40388
40389
40390
40391
40392 namespace Composer\Repository;
40393
40394 use Composer\Package\AliasPackage;
40395
40396
40397
40398
40399
40400
40401 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
40402 {
40403
40404
40405
40406 public function write()
40407 {
40408 }
40409
40410
40411
40412
40413 public function reload()
40414 {
40415 }
40416
40417
40418
40419
40420 public function getCanonicalPackages()
40421 {
40422 $packages = $this->getPackages();
40423
40424
40425  $packagesByName = array();
40426 foreach ($packages as $package) {
40427 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
40428 $packagesByName[$package->getName()] = $package;
40429 }
40430 }
40431
40432 $canonicalPackages = array();
40433
40434
40435  foreach ($packagesByName as $package) {
40436 while ($package instanceof AliasPackage) {
40437 $package = $package->getAliasOf();
40438 }
40439
40440 $canonicalPackages[] = $package;
40441 }
40442
40443 return $canonicalPackages;
40444 }
40445 }
40446 <?php
40447
40448
40449
40450
40451
40452
40453
40454
40455
40456
40457
40458 namespace Composer\Repository;
40459
40460 use Composer\Package\PackageInterface;
40461
40462
40463
40464
40465
40466
40467 interface WritableRepositoryInterface extends RepositoryInterface
40468 {
40469
40470
40471
40472 public function write();
40473
40474
40475
40476
40477
40478
40479 public function addPackage(PackageInterface $package);
40480
40481
40482
40483
40484
40485
40486 public function removePackage(PackageInterface $package);
40487
40488
40489
40490
40491
40492
40493 public function getCanonicalPackages();
40494
40495
40496
40497
40498 public function reload();
40499 }
40500 <?php
40501
40502
40503
40504
40505
40506
40507
40508
40509
40510
40511
40512 namespace Composer\Script;
40513
40514
40515
40516
40517
40518
40519 class CommandEvent extends Event
40520 {
40521 }
40522 <?php
40523
40524
40525
40526
40527
40528
40529
40530
40531
40532
40533
40534 namespace Composer\Script;
40535
40536 use Composer\Composer;
40537 use Composer\IO\IOInterface;
40538 use Composer\EventDispatcher\Event as BaseEvent;
40539
40540
40541
40542
40543
40544
40545
40546 class Event extends BaseEvent
40547 {
40548
40549
40550
40551 private $composer;
40552
40553
40554
40555
40556 private $io;
40557
40558
40559
40560
40561 private $devMode;
40562
40563
40564
40565
40566 private $originatingEvent;
40567
40568
40569
40570
40571
40572
40573
40574
40575
40576
40577
40578 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
40579 {
40580 parent::__construct($name, $args, $flags);
40581 $this->composer = $composer;
40582 $this->io = $io;
40583 $this->devMode = $devMode;
40584 $this->originatingEvent = null;
40585 }
40586
40587
40588
40589
40590
40591
40592 public function getComposer()
40593 {
40594 return $this->composer;
40595 }
40596
40597
40598
40599
40600
40601
40602 public function getIO()
40603 {
40604 return $this->io;
40605 }
40606
40607
40608
40609
40610
40611
40612 public function isDevMode()
40613 {
40614 return $this->devMode;
40615 }
40616
40617
40618
40619
40620
40621
40622 public function getOriginatingEvent()
40623 {
40624 return $this->originatingEvent;
40625 }
40626
40627
40628
40629
40630
40631
40632
40633 public function setOriginatingEvent(BaseEvent $event)
40634 {
40635 $this->originatingEvent = $this->calculateOriginatingEvent($event);
40636
40637 return $this;
40638 }
40639
40640
40641
40642
40643
40644
40645
40646 private function calculateOriginatingEvent(BaseEvent $event)
40647 {
40648 if ($event instanceof Event && $event->getOriginatingEvent()) {
40649 return $this->calculateOriginatingEvent($event->getOriginatingEvent());
40650 }
40651
40652 return $event;
40653 }
40654 }
40655 <?php
40656
40657
40658
40659
40660
40661
40662
40663
40664
40665
40666
40667 namespace Composer\Script;
40668
40669 use Composer\Installer\PackageEvent as BasePackageEvent;
40670
40671
40672
40673
40674
40675
40676 class PackageEvent extends BasePackageEvent
40677 {
40678 }
40679 <?php
40680
40681
40682
40683
40684
40685
40686
40687
40688
40689
40690
40691 namespace Composer\Script;
40692
40693
40694
40695
40696
40697
40698
40699 class ScriptEvents
40700 {
40701
40702
40703
40704
40705
40706
40707
40708 const PRE_INSTALL_CMD = 'pre-install-cmd';
40709
40710
40711
40712
40713
40714
40715
40716
40717 const POST_INSTALL_CMD = 'post-install-cmd';
40718
40719
40720
40721
40722
40723
40724
40725
40726 const PRE_UPDATE_CMD = 'pre-update-cmd';
40727
40728
40729
40730
40731
40732
40733
40734
40735 const POST_UPDATE_CMD = 'post-update-cmd';
40736
40737
40738
40739
40740
40741
40742
40743
40744 const PRE_STATUS_CMD = 'pre-status-cmd';
40745
40746
40747
40748
40749
40750
40751
40752
40753 const POST_STATUS_CMD = 'post-status-cmd';
40754
40755
40756
40757
40758
40759
40760
40761
40762 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
40763
40764
40765
40766
40767
40768
40769
40770
40771 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
40772
40773
40774
40775
40776
40777
40778
40779
40780 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
40781
40782
40783
40784
40785
40786
40787
40788
40789
40790 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
40791
40792
40793
40794
40795
40796
40797
40798
40799 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
40800
40801
40802
40803
40804
40805
40806
40807
40808 const POST_ARCHIVE_CMD = 'post-archive-cmd';
40809
40810
40811
40812
40813
40814
40815
40816
40817
40818
40819
40820 const PRE_PACKAGE_INSTALL = 'pre-package-install';
40821
40822
40823
40824
40825
40826
40827
40828
40829
40830 const POST_PACKAGE_INSTALL = 'post-package-install';
40831
40832
40833
40834
40835
40836
40837
40838
40839
40840 const PRE_PACKAGE_UPDATE = 'pre-package-update';
40841
40842
40843
40844
40845
40846
40847
40848
40849
40850 const POST_PACKAGE_UPDATE = 'post-package-update';
40851
40852
40853
40854
40855
40856
40857
40858
40859
40860 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
40861
40862
40863
40864
40865
40866
40867
40868
40869
40870 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
40871 }
40872 <?php
40873
40874
40875
40876
40877
40878
40879
40880
40881
40882
40883
40884 namespace Composer\SelfUpdate;
40885
40886
40887
40888
40889 class Keys
40890 {
40891 public static function fingerprint($path)
40892 {
40893 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
40894
40895 return implode(' ', array(
40896 substr($hash, 0, 8),
40897 substr($hash, 8, 8),
40898 substr($hash, 16, 8),
40899 substr($hash, 24, 8),
40900 '', 
40901  substr($hash, 32, 8),
40902 substr($hash, 40, 8),
40903 substr($hash, 48, 8),
40904 substr($hash, 56, 8),
40905 ));
40906 }
40907 }
40908 <?php
40909
40910
40911
40912
40913
40914
40915
40916
40917
40918
40919
40920 namespace Composer\SelfUpdate;
40921
40922 use Composer\Util\RemoteFilesystem;
40923 use Composer\Config;
40924 use Composer\Json\JsonFile;
40925
40926
40927
40928
40929 class Versions
40930 {
40931 private $rfs;
40932 private $config;
40933 private $channel;
40934
40935 public function __construct(Config $config, RemoteFilesystem $rfs)
40936 {
40937 $this->rfs = $rfs;
40938 $this->config = $config;
40939 }
40940
40941 public function getChannel()
40942 {
40943 if ($this->channel) {
40944 return $this->channel;
40945 }
40946
40947 $channelFile = $this->config->get('home').'/update-channel';
40948 if (file_exists($channelFile)) {
40949 $channel = trim(file_get_contents($channelFile));
40950 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
40951 return $this->channel = $channel;
40952 }
40953 }
40954
40955 return $this->channel = 'stable';
40956 }
40957
40958 public function setChannel($channel)
40959 {
40960 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
40961 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
40962 }
40963
40964 $channelFile = $this->config->get('home').'/update-channel';
40965 $this->channel = $channel;
40966 file_put_contents($channelFile, $channel.PHP_EOL);
40967 }
40968
40969 public function getLatest()
40970 {
40971 $protocol = extension_loaded('openssl') ? 'https' : 'http';
40972 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
40973
40974 foreach ($versions[$this->getChannel()] as $version) {
40975 if ($version['min-php'] <= PHP_VERSION_ID) {
40976 return $version;
40977 }
40978 }
40979
40980 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
40981 }
40982 }
40983 <?php
40984
40985
40986
40987
40988
40989
40990
40991
40992
40993
40994
40995 namespace Composer\Util;
40996
40997 use Composer\Config;
40998 use Composer\IO\IOInterface;
40999
41000
41001
41002
41003 class AuthHelper
41004 {
41005 protected $io;
41006 protected $config;
41007
41008 public function __construct(IOInterface $io, Config $config)
41009 {
41010 $this->io = $io;
41011 $this->config = $config;
41012 }
41013
41014 public function storeAuth($originUrl, $storeAuth)
41015 {
41016 $store = false;
41017 $configSource = $this->config->getAuthConfigSource();
41018 if ($storeAuth === true) {
41019 $store = $configSource;
41020 } elseif ($storeAuth === 'prompt') {
41021 $answer = $this->io->askAndValidate(
41022 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
41023 function ($value) {
41024 $input = strtolower(substr(trim($value), 0, 1));
41025 if (in_array($input, array('y','n'))) {
41026 return $input;
41027 }
41028 throw new \RuntimeException('Please answer (y)es or (n)o');
41029 },
41030 null,
41031 'y'
41032 );
41033
41034 if ($answer === 'y') {
41035 $store = $configSource;
41036 }
41037 }
41038 if ($store) {
41039 $store->addConfigSetting(
41040 'http-basic.'.$originUrl,
41041 $this->io->getAuthentication($originUrl)
41042 );
41043 }
41044 }
41045 }
41046 <?php
41047
41048
41049
41050
41051
41052
41053
41054
41055
41056
41057
41058 namespace Composer\Util;
41059
41060 use Composer\Factory;
41061 use Composer\IO\IOInterface;
41062 use Composer\Config;
41063 use Composer\Downloader\TransportException;
41064
41065
41066
41067
41068 class Bitbucket
41069 {
41070 private $io;
41071 private $config;
41072 private $process;
41073 private $remoteFilesystem;
41074 private $token = array();
41075 private $time;
41076
41077 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
41078
41079
41080
41081
41082
41083
41084
41085
41086
41087
41088 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
41089 {
41090 $this->io = $io;
41091 $this->config = $config;
41092 $this->process = $process ?: new ProcessExecutor($io);
41093 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41094 $this->time = $time;
41095 }
41096
41097
41098
41099
41100 public function getToken()
41101 {
41102 if (!isset($this->token['access_token'])) {
41103 return '';
41104 }
41105
41106 return $this->token['access_token'];
41107 }
41108
41109
41110
41111
41112
41113
41114
41115 public function authorizeOAuth($originUrl)
41116 {
41117 if ($originUrl !== 'bitbucket.org') {
41118 return false;
41119 }
41120
41121
41122  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
41123 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
41124
41125 return true;
41126 }
41127
41128 return false;
41129 }
41130
41131
41132
41133
41134
41135 private function requestAccessToken($originUrl)
41136 {
41137 try {
41138 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
41139 'retry-auth-failure' => false,
41140 'http' => array(
41141 'method' => 'POST',
41142 'content' => 'grant_type=client_credentials',
41143 ),
41144 ));
41145
41146 $this->token = json_decode($json, true);
41147 } catch (TransportException $e) {
41148 if ($e->getCode() === 400) {
41149 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
41150 $this->io->writeError('This can have two reasons:');
41151 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
41152 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
41153
41154 return false;
41155 } elseif (in_array($e->getCode(), array(403, 401))) {
41156 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
41157 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
41158
41159 return false;
41160 }
41161
41162 throw $e;
41163 }
41164
41165 return true;
41166 }
41167
41168
41169
41170
41171
41172
41173
41174
41175
41176
41177 public function authorizeOAuthInteractively($originUrl, $message = null)
41178 {
41179 if ($message) {
41180 $this->io->writeError($message);
41181 }
41182
41183 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
41184 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
41185 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
41186 $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)');
41187
41188 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
41189
41190 if (!$consumerKey) {
41191 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
41192 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
41193
41194 return false;
41195 }
41196
41197 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
41198
41199 if (!$consumerSecret) {
41200 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
41201 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
41202
41203 return false;
41204 }
41205
41206 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
41207
41208 if (!$this->requestAccessToken($originUrl)) {
41209 return false;
41210 }
41211
41212
41213  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
41214
41215
41216  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
41217
41218 $this->io->writeError('<info>Consumer stored successfully.</info>');
41219
41220 return true;
41221 }
41222
41223
41224
41225
41226
41227
41228
41229
41230
41231 public function requestToken($originUrl, $consumerKey, $consumerSecret)
41232 {
41233 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
41234 return $this->token['access_token'];
41235 }
41236
41237 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
41238 if (!$this->requestAccessToken($originUrl)) {
41239 return '';
41240 }
41241
41242 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
41243
41244 return $this->token['access_token'];
41245 }
41246
41247
41248
41249
41250
41251
41252
41253 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
41254 {
41255 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
41256
41257 $time = null === $this->time ? time() : $this->time;
41258 $consumer = array(
41259 "consumer-key" => $consumerKey,
41260 "consumer-secret" => $consumerSecret,
41261 "access-token" => $this->token['access_token'],
41262 "access-token-expiration" => $time + $this->token['expires_in'],
41263 );
41264
41265 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
41266 }
41267
41268
41269
41270
41271
41272 private function getTokenFromConfig($originUrl)
41273 {
41274 $authConfig = $this->config->get('bitbucket-oauth');
41275
41276 if (
41277 !isset($authConfig[$originUrl]['access-token'])
41278 || !isset($authConfig[$originUrl]['access-token-expiration'])
41279 || time() > $authConfig[$originUrl]['access-token-expiration']
41280 ) {
41281 return false;
41282 }
41283
41284 $this->token = array(
41285 'access_token' => $authConfig[$originUrl]['access-token'],
41286 );
41287
41288 return true;
41289 }
41290 }
41291 <?php
41292
41293
41294
41295
41296
41297
41298
41299
41300
41301
41302
41303 namespace Composer\Util;
41304
41305
41306
41307
41308
41309
41310 class ComposerMirror
41311 {
41312 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
41313 {
41314 if ($reference) {
41315 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
41316 }
41317 $version = strpos($version, '/') === false ? $version : md5($version);
41318
41319 return str_replace(
41320 array('%package%', '%version%', '%reference%', '%type%'),
41321 array($packageName, $version, $reference, $type),
41322 $mirrorUrl
41323 );
41324 }
41325
41326 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
41327 {
41328 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
41329 $url = 'gh-'.$match[1].'/'.$match[2];
41330 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
41331 $url = 'bb-'.$match[1].'/'.$match[2];
41332 } else {
41333 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
41334 }
41335
41336 return str_replace(
41337 array('%package%', '%normalizedUrl%', '%type%'),
41338 array($packageName, $url, $type),
41339 $mirrorUrl
41340 );
41341 }
41342
41343 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
41344 {
41345 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
41346 }
41347 }
41348 <?php
41349
41350
41351
41352
41353
41354
41355
41356
41357
41358
41359
41360 namespace Composer\Util;
41361
41362 use Composer\Package\Loader\ArrayLoader;
41363 use Composer\Package\Loader\ValidatingArrayLoader;
41364 use Composer\Package\Loader\InvalidPackageException;
41365 use Composer\Json\JsonValidationException;
41366 use Composer\IO\IOInterface;
41367 use Composer\Json\JsonFile;
41368 use Composer\Spdx\SpdxLicenses;
41369
41370
41371
41372
41373
41374
41375
41376 class ConfigValidator
41377 {
41378 private $io;
41379
41380 public function __construct(IOInterface $io)
41381 {
41382 $this->io = $io;
41383 }
41384
41385
41386
41387
41388
41389
41390
41391
41392
41393 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
41394 {
41395 $errors = array();
41396 $publishErrors = array();
41397 $warnings = array();
41398
41399
41400  $laxValid = false;
41401 try {
41402 $json = new JsonFile($file, null, $this->io);
41403 $manifest = $json->read();
41404
41405 $json->validateSchema(JsonFile::LAX_SCHEMA);
41406 $laxValid = true;
41407 $json->validateSchema();
41408 } catch (JsonValidationException $e) {
41409 foreach ($e->getErrors() as $message) {
41410 if ($laxValid) {
41411 $publishErrors[] = $message;
41412 } else {
41413 $errors[] = $message;
41414 }
41415 }
41416 } catch (\Exception $e) {
41417 $errors[] = $e->getMessage();
41418
41419 return array($errors, $publishErrors, $warnings);
41420 }
41421
41422
41423  if (empty($manifest['license'])) {
41424 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
41425 } else {
41426 $licenses = (array) $manifest['license'];
41427
41428
41429  foreach ($licenses as $key => $license) {
41430 if ('proprietary' === $license) {
41431 unset($licenses[$key]);
41432 }
41433 }
41434
41435 $licenseValidator = new SpdxLicenses();
41436 foreach ($licenses as $license) {
41437 $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
41438 if ($spdxLicense && $spdxLicense[3]) {
41439 if (preg_match('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) {
41440 $warnings[] = sprintf(
41441 'License "%s" is a deprecated SPDX license identifier, use "'.str_replace('+', '', $license).'-or-later" instead',
41442 $license
41443 );
41444 } elseif (preg_match('{^[AL]?GPL-[123](\.[01])?$}i', $license)) {
41445 $warnings[] = sprintf(
41446 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead',
41447 $license
41448 );
41449 } else {
41450 $warnings[] = sprintf(
41451 'License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/',
41452 $license
41453 );
41454 }
41455 }
41456 }
41457 }
41458
41459 if (isset($manifest['version'])) {
41460 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
41461 }
41462
41463 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
41464 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
41465 $suggestName = strtolower($suggestName);
41466
41467 $publishErrors[] = sprintf(
41468 '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.',
41469 $manifest['name'],
41470 $suggestName
41471 );
41472 }
41473
41474 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
41475 $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.";
41476 }
41477
41478
41479  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
41480 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
41481
41482 if (!empty($requireOverrides)) {
41483 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
41484 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
41485 }
41486 }
41487
41488
41489  $require = isset($manifest['require']) ? $manifest['require'] : array();
41490 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
41491 $packages = array_merge($require, $requireDev);
41492 foreach ($packages as $package => $version) {
41493 if (preg_match('/#/', $version) === 1) {
41494 $warnings[] = sprintf(
41495 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
41496 $package
41497 );
41498 }
41499 }
41500
41501
41502  $scriptsDescriptions = isset($manifest['scripts-descriptions']) ? $manifest['scripts-descriptions'] : array();
41503 $scripts = isset($manifest['scripts']) ? $manifest['scripts'] : array();
41504 foreach ($scriptsDescriptions as $scriptName => $scriptDescription) {
41505 if (!array_key_exists($scriptName, $scripts)) {
41506 $warnings[] = sprintf(
41507 'Description for non-existent script "%s" found in "scripts-descriptions"',
41508 $scriptName
41509 );
41510 }
41511 }
41512
41513
41514  if (isset($manifest['autoload']['psr-0'][''])) {
41515 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
41516 }
41517 if (isset($manifest['autoload']['psr-4'][''])) {
41518 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
41519 }
41520
41521 try {
41522 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
41523 if (!isset($manifest['version'])) {
41524 $manifest['version'] = '1.0.0';
41525 }
41526 if (!isset($manifest['name'])) {
41527 $manifest['name'] = 'dummy/dummy';
41528 }
41529 $loader->load($manifest);
41530 } catch (InvalidPackageException $e) {
41531 $errors = array_merge($errors, $e->getErrors());
41532 }
41533
41534 $warnings = array_merge($warnings, $loader->getWarnings());
41535
41536 return array($errors, $publishErrors, $warnings);
41537 }
41538 }
41539 <?php
41540
41541
41542
41543
41544
41545
41546
41547
41548
41549
41550
41551 namespace Composer\Util;
41552
41553 use Composer\IO\IOInterface;
41554
41555
41556
41557
41558
41559
41560 class ErrorHandler
41561 {
41562 private static $io;
41563
41564
41565
41566
41567
41568
41569
41570
41571
41572
41573
41574
41575
41576 public static function handle($level, $message, $file, $line)
41577 {
41578
41579  if (!(error_reporting() & $level)) {
41580 return;
41581 }
41582
41583 if (filter_var(ini_get('xdebug.scream'), FILTER_VALIDATE_BOOLEAN)) {
41584 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
41585 "\na legitimately suppressed error that you were not supposed to see.";
41586 }
41587
41588 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
41589 throw new \ErrorException($message, 0, $level, $file, $line);
41590 }
41591
41592 if (self::$io) {
41593 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
41594 if (self::$io->isVerbose()) {
41595 self::$io->writeError('<warning>Stack trace:</warning>');
41596 self::$io->writeError(array_filter(array_map(function ($a) {
41597 if (isset($a['line'], $a['file'])) {
41598 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
41599 }
41600
41601 return null;
41602 }, array_slice(debug_backtrace(), 2))));
41603 }
41604 }
41605
41606 return true;
41607 }
41608
41609
41610
41611
41612
41613
41614 public static function register(IOInterface $io = null)
41615 {
41616 set_error_handler(array(__CLASS__, 'handle'));
41617 error_reporting(E_ALL | E_STRICT);
41618 self::$io = $io;
41619 }
41620 }
41621 <?php
41622
41623
41624
41625
41626
41627
41628
41629
41630
41631
41632
41633 namespace Composer\Util;
41634
41635 use RecursiveDirectoryIterator;
41636 use RecursiveIteratorIterator;
41637 use Symfony\Component\Filesystem\Exception\IOException;
41638 use Symfony\Component\Finder\Finder;
41639
41640
41641
41642
41643
41644 class Filesystem
41645 {
41646 private $processExecutor;
41647
41648 public function __construct(ProcessExecutor $executor = null)
41649 {
41650 $this->processExecutor = $executor ?: new ProcessExecutor();
41651 }
41652
41653 public function remove($file)
41654 {
41655 if (is_dir($file)) {
41656 return $this->removeDirectory($file);
41657 }
41658
41659 if (file_exists($file)) {
41660 return $this->unlink($file);
41661 }
41662
41663 return false;
41664 }
41665
41666
41667
41668
41669
41670
41671
41672 public function isDirEmpty($dir)
41673 {
41674 $finder = Finder::create()
41675 ->ignoreVCS(false)
41676 ->ignoreDotFiles(false)
41677 ->depth(0)
41678 ->in($dir);
41679
41680 return count($finder) === 0;
41681 }
41682
41683 public function emptyDirectory($dir, $ensureDirectoryExists = true)
41684 {
41685 if (file_exists($dir) && is_link($dir)) {
41686 $this->unlink($dir);
41687 }
41688
41689 if ($ensureDirectoryExists) {
41690 $this->ensureDirectoryExists($dir);
41691 }
41692
41693 if (is_dir($dir)) {
41694 $finder = Finder::create()
41695 ->ignoreVCS(false)
41696 ->ignoreDotFiles(false)
41697 ->depth(0)
41698 ->in($dir);
41699
41700 foreach ($finder as $path) {
41701 $this->remove((string) $path);
41702 }
41703 }
41704 }
41705
41706
41707
41708
41709
41710
41711
41712
41713
41714
41715
41716 public function removeDirectory($directory)
41717 {
41718 if ($this->isSymlinkedDirectory($directory)) {
41719 return $this->unlinkSymlinkedDirectory($directory);
41720 }
41721
41722 if ($this->isJunction($directory)) {
41723 return $this->removeJunction($directory);
41724 }
41725
41726 if (is_link($directory)) {
41727 return unlink($directory);
41728 }
41729
41730 if (!file_exists($directory) || !is_dir($directory)) {
41731 return true;
41732 }
41733
41734 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
41735 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
41736 }
41737
41738 if (!function_exists('proc_open')) {
41739 return $this->removeDirectoryPhp($directory);
41740 }
41741
41742 if (Platform::isWindows()) {
41743 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
41744 } else {
41745 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
41746 }
41747
41748 $result = $this->getProcess()->execute($cmd, $output) === 0;
41749
41750
41751  clearstatcache();
41752
41753 if ($result && !file_exists($directory)) {
41754 return true;
41755 }
41756
41757 return $this->removeDirectoryPhp($directory);
41758 }
41759
41760
41761
41762
41763
41764
41765
41766
41767
41768
41769
41770 public function removeDirectoryPhp($directory)
41771 {
41772 try {
41773 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
41774 } catch (\UnexpectedValueException $e) {
41775
41776  
41777  clearstatcache();
41778 usleep(100000);
41779 if (!is_dir($directory)) {
41780 return true;
41781 }
41782 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
41783 }
41784 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
41785
41786 foreach ($ri as $file) {
41787 if ($file->isDir()) {
41788 $this->rmdir($file->getPathname());
41789 } else {
41790 $this->unlink($file->getPathname());
41791 }
41792 }
41793
41794 return $this->rmdir($directory);
41795 }
41796
41797 public function ensureDirectoryExists($directory)
41798 {
41799 if (!is_dir($directory)) {
41800 if (file_exists($directory)) {
41801 throw new \RuntimeException(
41802 $directory.' exists and is not a directory.'
41803 );
41804 }
41805 if (!@mkdir($directory, 0777, true)) {
41806 throw new \RuntimeException(
41807 $directory.' does not exist and could not be created.'
41808 );
41809 }
41810 }
41811 }
41812
41813
41814
41815
41816
41817
41818
41819
41820 public function unlink($path)
41821 {
41822 $unlinked = @$this->unlinkImplementation($path);
41823 if (!$unlinked) {
41824
41825  if (Platform::isWindows()) {
41826 usleep(350000);
41827 $unlinked = @$this->unlinkImplementation($path);
41828 }
41829
41830 if (!$unlinked) {
41831 $error = error_get_last();
41832 $message = 'Could not delete '.$path.': ' . @$error['message'];
41833 if (Platform::isWindows()) {
41834 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
41835 }
41836
41837 throw new \RuntimeException($message);
41838 }
41839 }
41840
41841 return true;
41842 }
41843
41844
41845
41846
41847
41848
41849
41850
41851 public function rmdir($path)
41852 {
41853 $deleted = @rmdir($path);
41854 if (!$deleted) {
41855
41856  if (Platform::isWindows()) {
41857 usleep(350000);
41858 $deleted = @rmdir($path);
41859 }
41860
41861 if (!$deleted) {
41862 $error = error_get_last();
41863 $message = 'Could not delete '.$path.': ' . @$error['message'];
41864 if (Platform::isWindows()) {
41865 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
41866 }
41867
41868 throw new \RuntimeException($message);
41869 }
41870 }
41871
41872 return true;
41873 }
41874
41875
41876
41877
41878
41879
41880
41881
41882
41883
41884 public function copyThenRemove($source, $target)
41885 {
41886 $this->copy($source, $target);
41887 if (!is_dir($source)) {
41888 $this->unlink($source);
41889
41890 return;
41891 }
41892
41893 $this->removeDirectoryPhp($source);
41894 }
41895
41896
41897
41898
41899
41900
41901
41902
41903 public function copy($source, $target)
41904 {
41905 if (!is_dir($source)) {
41906 return copy($source, $target);
41907 }
41908
41909 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
41910 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
41911 $this->ensureDirectoryExists($target);
41912
41913 $result = true;
41914 foreach ($ri as $file) {
41915 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
41916 if ($file->isDir()) {
41917 $this->ensureDirectoryExists($targetPath);
41918 } else {
41919 $result = $result && copy($file->getPathname(), $targetPath);
41920 }
41921 }
41922
41923 return $result;
41924 }
41925
41926 public function rename($source, $target)
41927 {
41928 if (true === @rename($source, $target)) {
41929 return;
41930 }
41931
41932 if (!function_exists('proc_open')) {
41933 return $this->copyThenRemove($source, $target);
41934 }
41935
41936 if (Platform::isWindows()) {
41937
41938  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
41939 $result = $this->processExecutor->execute($command, $output);
41940
41941
41942  clearstatcache();
41943
41944 if (0 === $result) {
41945 $this->remove($source);
41946
41947 return;
41948 }
41949 } else {
41950
41951  
41952  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
41953 $result = $this->processExecutor->execute($command, $output);
41954
41955
41956  clearstatcache();
41957
41958 if (0 === $result) {
41959 return;
41960 }
41961 }
41962
41963 return $this->copyThenRemove($source, $target);
41964 }
41965
41966
41967
41968
41969
41970
41971
41972
41973
41974
41975 public function findShortestPath($from, $to, $directories = false)
41976 {
41977 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
41978 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
41979 }
41980
41981 $from = lcfirst($this->normalizePath($from));
41982 $to = lcfirst($this->normalizePath($to));
41983
41984 if ($directories) {
41985 $from = rtrim($from, '/') . '/dummy_file';
41986 }
41987
41988 if (dirname($from) === dirname($to)) {
41989 return './'.basename($to);
41990 }
41991
41992 $commonPath = $to;
41993 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
41994 $commonPath = strtr(dirname($commonPath), '\\', '/');
41995 }
41996
41997 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
41998 return $to;
41999 }
42000
42001 $commonPath = rtrim($commonPath, '/') . '/';
42002 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
42003 $commonPathCode = str_repeat('../', $sourcePathDepth);
42004
42005 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
42006 }
42007
42008
42009
42010
42011
42012
42013
42014
42015
42016
42017
42018 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
42019 {
42020 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
42021 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
42022 }
42023
42024 $from = lcfirst($this->normalizePath($from));
42025 $to = lcfirst($this->normalizePath($to));
42026
42027 if ($from === $to) {
42028 return $directories ? '__DIR__' : '__FILE__';
42029 }
42030
42031 $commonPath = $to;
42032 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
42033 $commonPath = strtr(dirname($commonPath), '\\', '/');
42034 }
42035
42036 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
42037 return var_export($to, true);
42038 }
42039
42040 $commonPath = rtrim($commonPath, '/') . '/';
42041 if (strpos($to, $from.'/') === 0) {
42042 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
42043 }
42044 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
42045 if ($staticCode) {
42046 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
42047 } else {
42048 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
42049 }
42050 $relTarget = substr($to, strlen($commonPath));
42051
42052 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
42053 }
42054
42055
42056
42057
42058
42059
42060
42061 public function isAbsolutePath($path)
42062 {
42063 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':' || substr($path, 0, 2) === '\\\\';
42064 }
42065
42066
42067
42068
42069
42070
42071
42072
42073
42074 public function size($path)
42075 {
42076 if (!file_exists($path)) {
42077 throw new \RuntimeException("$path does not exist.");
42078 }
42079 if (is_dir($path)) {
42080 return $this->directorySize($path);
42081 }
42082
42083 return filesize($path);
42084 }
42085
42086
42087
42088
42089
42090
42091
42092
42093 public function normalizePath($path)
42094 {
42095 $parts = array();
42096 $path = strtr($path, '\\', '/');
42097 $prefix = '';
42098 $absolute = false;
42099
42100
42101  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
42102 $prefix = $match[1];
42103 $path = substr($path, strlen($prefix));
42104 }
42105
42106 if (substr($path, 0, 1) === '/') {
42107 $absolute = true;
42108 $path = substr($path, 1);
42109 }
42110
42111 $up = false;
42112 foreach (explode('/', $path) as $chunk) {
42113 if ('..' === $chunk && ($absolute || $up)) {
42114 array_pop($parts);
42115 $up = !(empty($parts) || '..' === end($parts));
42116 } elseif ('.' !== $chunk && '' !== $chunk) {
42117 $parts[] = $chunk;
42118 $up = '..' !== $chunk;
42119 }
42120 }
42121
42122 return $prefix.($absolute ? '/' : '').implode('/', $parts);
42123 }
42124
42125
42126
42127
42128
42129
42130
42131 public static function isLocalPath($path)
42132 {
42133 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
42134 }
42135
42136 public static function getPlatformPath($path)
42137 {
42138 if (Platform::isWindows()) {
42139 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
42140 }
42141
42142 return preg_replace('{^file://}i', '', $path);
42143 }
42144
42145 protected function directorySize($directory)
42146 {
42147 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
42148 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
42149
42150 $size = 0;
42151 foreach ($ri as $file) {
42152 if ($file->isFile()) {
42153 $size += $file->getSize();
42154 }
42155 }
42156
42157 return $size;
42158 }
42159
42160 protected function getProcess()
42161 {
42162 return $this->processExecutor;
42163 }
42164
42165
42166
42167
42168
42169
42170
42171
42172
42173
42174 private function unlinkImplementation($path)
42175 {
42176 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
42177 return rmdir($path);
42178 }
42179
42180 return unlink($path);
42181 }
42182
42183
42184
42185
42186
42187
42188
42189
42190 public function relativeSymlink($target, $link)
42191 {
42192 $cwd = getcwd();
42193
42194 $relativePath = $this->findShortestPath($link, $target);
42195 chdir(dirname($link));
42196 $result = @symlink($relativePath, $link);
42197
42198 chdir($cwd);
42199
42200 return $result;
42201 }
42202
42203
42204
42205
42206
42207
42208
42209
42210 public function isSymlinkedDirectory($directory)
42211 {
42212 if (!is_dir($directory)) {
42213 return false;
42214 }
42215
42216 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
42217
42218 return is_link($resolved);
42219 }
42220
42221
42222
42223
42224
42225
42226 private function unlinkSymlinkedDirectory($directory)
42227 {
42228 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
42229
42230 return $this->unlink($resolved);
42231 }
42232
42233
42234
42235
42236
42237
42238
42239
42240 private function resolveSymlinkedDirectorySymlink($pathname)
42241 {
42242 if (!is_dir($pathname)) {
42243 return $pathname;
42244 }
42245
42246 $resolved = rtrim($pathname, '/');
42247
42248 if (!strlen($resolved)) {
42249 return $pathname;
42250 }
42251
42252 return $resolved;
42253 }
42254
42255
42256
42257
42258
42259
42260
42261 public function junction($target, $junction)
42262 {
42263 if (!Platform::isWindows()) {
42264 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
42265 }
42266 if (!is_dir($target)) {
42267 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
42268 }
42269 $cmd = sprintf(
42270 'mklink /J %s %s',
42271 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
42272 ProcessExecutor::escape(realpath($target))
42273 );
42274 if ($this->getProcess()->execute($cmd, $output) !== 0) {
42275 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
42276 }
42277 clearstatcache(true, $junction);
42278 }
42279
42280
42281
42282
42283
42284
42285
42286
42287
42288
42289
42290
42291
42292
42293
42294
42295
42296
42297
42298
42299
42300 public function isJunction($junction)
42301 {
42302 if (!Platform::isWindows()) {
42303 return false;
42304 }
42305
42306
42307  clearstatcache(true, $junction);
42308
42309 if (!is_dir($junction) || is_link($junction)) {
42310 return false;
42311 }
42312
42313 $stat = lstat($junction);
42314
42315
42316  return $stat ? 0x4000 !== ($stat['mode'] & 0xF000) : false;
42317 }
42318
42319
42320
42321
42322
42323
42324
42325 public function removeJunction($junction)
42326 {
42327 if (!Platform::isWindows()) {
42328 return false;
42329 }
42330 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
42331 if (!$this->isJunction($junction)) {
42332 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
42333 }
42334
42335 return $this->rmdir($junction);
42336 }
42337 }
42338 <?php
42339
42340
42341
42342
42343
42344
42345
42346
42347
42348
42349
42350 namespace Composer\Util;
42351
42352 use Composer\Config;
42353 use Composer\IO\IOInterface;
42354
42355
42356
42357
42358 class Git
42359 {
42360 private static $version;
42361
42362
42363 protected $io;
42364
42365 protected $config;
42366
42367 protected $process;
42368
42369 protected $filesystem;
42370
42371 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
42372 {
42373 $this->io = $io;
42374 $this->config = $config;
42375 $this->process = $process;
42376 $this->filesystem = $fs;
42377 }
42378
42379 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
42380 {
42381
42382  $this->config->prohibitUrlByConfig($url, $this->io);
42383
42384 if ($initialClone) {
42385 $origCwd = $cwd;
42386 $cwd = null;
42387 }
42388
42389 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
42390 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.');
42391 }
42392
42393 if (!$initialClone) {
42394
42395  $this->process->execute('git remote -v', $output, $cwd);
42396 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) {
42397 $this->io->setAuthentication($match[3], rawurldecode($match[1]), rawurldecode($match[2]));
42398 }
42399 }
42400
42401 $protocols = $this->config->get('github-protocols');
42402 if (!is_array($protocols)) {
42403 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
42404 }
42405
42406  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
42407 $messages = array();
42408 foreach ($protocols as $protocol) {
42409 if ('ssh' === $protocol) {
42410 $protoUrl = "git@" . $match[1] . ":" . $match[2];
42411 } else {
42412 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
42413 }
42414
42415 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
42416 return;
42417 }
42418 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
42419 if ($initialClone) {
42420 $this->filesystem->removeDirectory($origCwd);
42421 }
42422 }
42423
42424
42425  if (!$this->io->hasAuthentication($match[1]) && !$this->io->isInteractive()) {
42426 $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
42427 }
42428 }
42429
42430
42431  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
42432
42433 $command = call_user_func($commandCallable, $url);
42434
42435 $auth = null;
42436 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
42437
42438  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)
42439 || preg_match('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)
42440 ) {
42441 if (!$this->io->hasAuthentication($match[1])) {
42442 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
42443 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
42444
42445 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
42446 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
42447 }
42448 }
42449
42450 if ($this->io->hasAuthentication($match[1])) {
42451 $auth = $this->io->getAuthentication($match[1]);
42452 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
42453 $command = call_user_func($commandCallable, $authUrl);
42454 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42455 return;
42456 }
42457 }
42458 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
42459  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
42460
42461 if (!$this->io->hasAuthentication($match[1])) {
42462 $message = 'Enter your Bitbucket credentials to access private repos';
42463
42464 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
42465 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
42466 $accessToken = $bitbucketUtil->getToken();
42467 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
42468 }
42469 } else { 
42470  $auth = $this->io->getAuthentication($match[1]);
42471
42472
42473  if ($auth['username'] !== 'x-token-auth') {
42474 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
42475 if (! empty($accessToken)) {
42476 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
42477 }
42478 }
42479 }
42480
42481 if ($this->io->hasAuthentication($match[1])) {
42482 $auth = $this->io->getAuthentication($match[1]);
42483 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
42484
42485 $command = call_user_func($commandCallable, $authUrl);
42486 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42487 return;
42488 }
42489 } else { 
42490  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
42491 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
42492 $command = call_user_func($commandCallable, $sshUrl);
42493 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42494 return;
42495 }
42496 }
42497 } elseif (
42498 preg_match('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)
42499 || preg_match('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}', $url, $match)
42500 ) {
42501 if ($match[1] === 'git') {
42502 $match[1] = 'https';
42503 }
42504
42505 if (!$this->io->hasAuthentication($match[2])) {
42506 $gitLabUtil = new GitLab($this->io, $this->config, $this->process);
42507 $message = 'Cloning failed, enter your GitLab credentials to access private repos';
42508
42509 if (!$gitLabUtil->authorizeOAuth($match[2]) && $this->io->isInteractive()) {
42510 $gitLabUtil->authorizeOAuthInteractively($match[1], $match[2], $message);
42511 }
42512 }
42513
42514 if ($this->io->hasAuthentication($match[2])) {
42515 $auth = $this->io->getAuthentication($match[2]);
42516 if ($auth['password'] === 'private-token' || $auth['password'] === 'oauth2' || $auth['password'] === 'gitlab-ci-token') {
42517 $authUrl = $match[1] . '://' . rawurlencode($auth['password']) . ':' . rawurlencode($auth['username']) . '@' . $match[2] . '/' . $match[3]; 
42518  } else {
42519 $authUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . '/' . $match[3];
42520 }
42521
42522 $command = call_user_func($commandCallable, $authUrl);
42523 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42524 return;
42525 }
42526 }
42527 } elseif ($this->isAuthenticationFailure($url, $match)) { 
42528  if (strpos($match[2], '@')) {
42529 list($authParts, $match[2]) = explode('@', $match[2], 2);
42530 }
42531
42532 $storeAuth = false;
42533 if ($this->io->hasAuthentication($match[2])) {
42534 $auth = $this->io->getAuthentication($match[2]);
42535 } elseif ($this->io->isInteractive()) {
42536 $defaultUsername = null;
42537 if (isset($authParts) && $authParts) {
42538 if (false !== strpos($authParts, ':')) {
42539 list($defaultUsername, ) = explode(':', $authParts, 2);
42540 } else {
42541 $defaultUsername = $authParts;
42542 }
42543 }
42544
42545 $this->io->writeError('    Authentication required (<info>' . $match[2] . '</info>):');
42546 $auth = array(
42547 'username' => $this->io->ask('      Username: ', $defaultUsername),
42548 'password' => $this->io->askAndHideAnswer('      Password: '),
42549 );
42550 $storeAuth = $this->config->get('store-auths');
42551 }
42552
42553 if ($auth) {
42554 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
42555
42556 $command = call_user_func($commandCallable, $authUrl);
42557 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42558 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
42559 $authHelper = new AuthHelper($this->io, $this->config);
42560 $authHelper->storeAuth($match[2], $storeAuth);
42561
42562 return;
42563 }
42564 }
42565 }
42566
42567 $errorMsg = $this->process->getErrorOutput();
42568 if ($initialClone) {
42569 $this->filesystem->removeDirectory($origCwd);
42570 }
42571
42572 $this->throwException('Failed to execute ' . $command . "\n\n" . $errorMsg, $url);
42573 }
42574 }
42575
42576 public function syncMirror($url, $dir)
42577 {
42578
42579  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
42580 try {
42581 $commandCallable = function ($url) {
42582 $sanitizedUrl = preg_replace('{://([^@]+?):(.+?)@}', '://', $url);
42583
42584 return sprintf('git remote set-url origin %s && git remote update --prune origin && git remote set-url origin %s', ProcessExecutor::escape($url), ProcessExecutor::escape($sanitizedUrl));
42585 };
42586 $this->runCommand($commandCallable, $url, $dir);
42587 } catch (\Exception $e) {
42588 return false;
42589 }
42590
42591 return true;
42592 }
42593
42594
42595  $this->filesystem->removeDirectory($dir);
42596
42597 $commandCallable = function ($url) use ($dir) {
42598 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
42599 };
42600
42601 $this->runCommand($commandCallable, $url, $dir, true);
42602
42603 return true;
42604 }
42605
42606 public function fetchRefOrSyncMirror($url, $dir, $ref)
42607 {
42608 if ($this->checkRefIsInMirror($url, $dir, $ref)) {
42609 return true;
42610 }
42611
42612 if ($this->syncMirror($url, $dir)) {
42613 return $this->checkRefIsInMirror($url, $dir, $ref);
42614 }
42615
42616 return false;
42617 }
42618
42619 private function checkRefIsInMirror($url, $dir, $ref)
42620 {
42621 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
42622 $escapedRef = ProcessExecutor::escape($ref.'^{commit}');
42623 $exitCode = $this->process->execute(sprintf('git rev-parse --quiet --verify %s', $escapedRef), $ignoredOutput, $dir);
42624 if ($exitCode === 0) {
42625 return true;
42626 }
42627 }
42628
42629 return false;
42630 }
42631
42632 private function isAuthenticationFailure($url, &$match)
42633 {
42634 if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
42635 return false;
42636 }
42637
42638 $authFailures = array(
42639 'fatal: Authentication failed',
42640 'remote error: Invalid username or password.',
42641 'error: 401 Unauthorized',
42642 'fatal: unable to access',
42643 'fatal: could not read Username',
42644 );
42645
42646 $errorOutput = $this->process->getErrorOutput();
42647 foreach ($authFailures as $authFailure) {
42648 if (strpos($errorOutput, $authFailure) !== false) {
42649 return true;
42650 }
42651 }
42652
42653 return false;
42654 }
42655
42656 public static function cleanEnv()
42657 {
42658 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
42659 throw new \RuntimeException('safe_mode is enabled and safe_mode_allowed_env_vars does not contain GIT_ASKPASS, can not set env var. You can disable safe_mode with "-dsafe_mode=0" when running composer');
42660 }
42661
42662
42663  if (getenv('GIT_ASKPASS') !== 'echo') {
42664 putenv('GIT_ASKPASS=echo');
42665 unset($_SERVER['GIT_ASKPASS']);
42666 }
42667
42668
42669  if (getenv('GIT_DIR')) {
42670 putenv('GIT_DIR');
42671 unset($_SERVER['GIT_DIR']);
42672 }
42673 if (getenv('GIT_WORK_TREE')) {
42674 putenv('GIT_WORK_TREE');
42675 unset($_SERVER['GIT_WORK_TREE']);
42676 }
42677
42678
42679  if (getenv('LANGUAGE') !== 'C') {
42680 putenv('LANGUAGE=C');
42681 }
42682
42683
42684  putenv("DYLD_LIBRARY_PATH");
42685 unset($_SERVER['DYLD_LIBRARY_PATH']);
42686 }
42687
42688 public static function getGitHubDomainsRegex(Config $config)
42689 {
42690 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
42691 }
42692
42693 public static function getGitLabDomainsRegex(Config $config)
42694 {
42695 return '(' . implode('|', array_map('preg_quote', $config->get('gitlab-domains'))) . ')';
42696 }
42697
42698 public static function sanitizeUrl($message)
42699 {
42700 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
42701 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
42702 return '://***:***@';
42703 }
42704
42705 return '://' . $m[1] . ':***@';
42706 }, $message);
42707 }
42708
42709 private function throwException($message, $url)
42710 {
42711
42712  clearstatcache();
42713
42714 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
42715 throw new \RuntimeException(self::sanitizeUrl('Failed to clone ' . $url . ', git was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()));
42716 }
42717
42718 throw new \RuntimeException(self::sanitizeUrl($message));
42719 }
42720
42721
42722
42723
42724
42725
42726 public function getVersion()
42727 {
42728 if (isset(self::$version)) {
42729 return self::$version;
42730 }
42731 if (0 !== $this->process->execute('git --version', $output)) {
42732 return;
42733 }
42734 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
42735 return self::$version = $matches[1];
42736 }
42737 }
42738 }
42739 <?php
42740
42741
42742
42743
42744
42745
42746
42747
42748
42749
42750
42751 namespace Composer\Util;
42752
42753 use Composer\Factory;
42754 use Composer\IO\IOInterface;
42755 use Composer\Config;
42756 use Composer\Downloader\TransportException;
42757
42758
42759
42760
42761 class GitHub
42762 {
42763 protected $io;
42764 protected $config;
42765 protected $process;
42766 protected $remoteFilesystem;
42767
42768
42769
42770
42771
42772
42773
42774
42775
42776 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
42777 {
42778 $this->io = $io;
42779 $this->config = $config;
42780 $this->process = $process ?: new ProcessExecutor($io);
42781 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
42782 }
42783
42784
42785
42786
42787
42788
42789
42790 public function authorizeOAuth($originUrl)
42791 {
42792 if (!in_array($originUrl, $this->config->get('github-domains'))) {
42793 return false;
42794 }
42795
42796
42797  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
42798 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
42799
42800 return true;
42801 }
42802
42803 return false;
42804 }
42805
42806
42807
42808
42809
42810
42811
42812
42813
42814
42815 public function authorizeOAuthInteractively($originUrl, $message = null)
42816 {
42817 if ($message) {
42818 $this->io->writeError($message);
42819 }
42820
42821 $note = 'Composer';
42822 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
42823 $note .= ' on ' . trim($output);
42824 }
42825 $note .= ' ' . date('Y-m-d Hi');
42826
42827 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
42828 $this->io->writeError(sprintf('Head to %s', $url));
42829 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
42830
42831 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
42832
42833 if (!$token) {
42834 $this->io->writeError('<warning>No token given, aborting.</warning>');
42835 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
42836
42837 return false;
42838 }
42839
42840 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
42841
42842 try {
42843 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
42844
42845 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
42846 'retry-auth-failure' => false,
42847 ));
42848 } catch (TransportException $e) {
42849 if (in_array($e->getCode(), array(403, 401))) {
42850 $this->io->writeError('<error>Invalid token provided.</error>');
42851 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
42852
42853 return false;
42854 }
42855
42856 throw $e;
42857 }
42858
42859
42860  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
42861 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
42862
42863 $this->io->writeError('<info>Token stored successfully.</info>');
42864
42865 return true;
42866 }
42867
42868
42869
42870
42871
42872
42873
42874
42875 public function getRateLimit(array $headers)
42876 {
42877 $rateLimit = array(
42878 'limit' => '?',
42879 'reset' => '?',
42880 );
42881
42882 foreach ($headers as $header) {
42883 $header = trim($header);
42884 if (false === strpos($header, 'X-RateLimit-')) {
42885 continue;
42886 }
42887 list($type, $value) = explode(':', $header, 2);
42888 switch ($type) {
42889 case 'X-RateLimit-Limit':
42890 $rateLimit['limit'] = (int) trim($value);
42891 break;
42892 case 'X-RateLimit-Reset':
42893 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
42894 break;
42895 }
42896 }
42897
42898 return $rateLimit;
42899 }
42900
42901
42902
42903
42904
42905
42906
42907
42908 public function isRateLimited(array $headers)
42909 {
42910 foreach ($headers as $header) {
42911 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
42912 return true;
42913 }
42914 }
42915
42916 return false;
42917 }
42918 }
42919 <?php
42920
42921
42922
42923
42924
42925
42926
42927
42928
42929
42930
42931 namespace Composer\Util;
42932
42933 use Composer\IO\IOInterface;
42934 use Composer\Config;
42935 use Composer\Factory;
42936 use Composer\Downloader\TransportException;
42937 use Composer\Json\JsonFile;
42938
42939
42940
42941
42942 class GitLab
42943 {
42944 protected $io;
42945 protected $config;
42946 protected $process;
42947 protected $remoteFilesystem;
42948
42949
42950
42951
42952
42953
42954
42955
42956
42957 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
42958 {
42959 $this->io = $io;
42960 $this->config = $config;
42961 $this->process = $process ?: new ProcessExecutor($io);
42962 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
42963 }
42964
42965
42966
42967
42968
42969
42970
42971
42972 public function authorizeOAuth($originUrl)
42973 {
42974
42975  $bcOriginUrl = preg_replace('{:\d+}', '', $originUrl);
42976
42977 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true) && !in_array($bcOriginUrl, $this->config->get('gitlab-domains'), true)) {
42978 return false;
42979 }
42980
42981
42982  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
42983 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
42984
42985 return true;
42986 }
42987
42988
42989  $authTokens = $this->config->get('gitlab-token');
42990
42991 if (isset($authTokens[$originUrl])) {
42992 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
42993
42994 return true;
42995 }
42996
42997 if (isset($authTokens[$bcOriginUrl])) {
42998 $this->io->setAuthentication($originUrl, $authTokens[$bcOriginUrl], 'private-token');
42999
43000 return true;
43001 }
43002
43003 return false;
43004 }
43005
43006
43007
43008
43009
43010
43011
43012
43013
43014
43015
43016
43017
43018 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
43019 {
43020 if ($message) {
43021 $this->io->writeError($message);
43022 }
43023
43024 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
43025 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
43026
43027 $attemptCounter = 0;
43028
43029 while ($attemptCounter++ < 5) {
43030 try {
43031 $response = $this->createToken($scheme, $originUrl);
43032 } catch (TransportException $e) {
43033
43034  
43035  if (in_array($e->getCode(), array(403, 401))) {
43036 if (401 === $e->getCode()) {
43037 $this->io->writeError('Bad credentials.');
43038 } else {
43039 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
43040 }
43041
43042 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
43043 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
43044
43045 continue;
43046 }
43047
43048 throw $e;
43049 }
43050
43051 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
43052
43053
43054  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
43055
43056 return true;
43057 }
43058
43059 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
43060 }
43061
43062 private function createToken($scheme, $originUrl)
43063 {
43064 $username = $this->io->ask('Username: ');
43065 $password = $this->io->askAndHideAnswer('Password: ');
43066
43067 $headers = array('Content-Type: application/x-www-form-urlencoded');
43068
43069 $apiUrl = $originUrl;
43070 $data = http_build_query(array(
43071 'username' => $username,
43072 'password' => $password,
43073 'grant_type' => 'password',
43074 ), null, '&');
43075 $options = array(
43076 'retry-auth-failure' => false,
43077 'http' => array(
43078 'method' => 'POST',
43079 'header' => $headers,
43080 'content' => $data,
43081 ),
43082 );
43083
43084 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
43085
43086 $this->io->writeError('Token successfully created');
43087
43088 return JsonFile::parseJson($json);
43089 }
43090 }
43091 <?php
43092
43093
43094
43095
43096
43097
43098
43099
43100
43101
43102
43103 namespace Composer\Util;
43104
43105 use Composer\Config;
43106 use Composer\IO\IOInterface;
43107
43108
43109
43110
43111 class Hg
43112 {
43113
43114
43115
43116 private $io;
43117
43118
43119
43120
43121 private $config;
43122
43123
43124
43125
43126 private $process;
43127
43128 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process)
43129 {
43130 $this->io = $io;
43131 $this->config = $config;
43132 $this->process = $process;
43133 }
43134
43135 public function runCommand($commandCallable, $url, $cwd)
43136 {
43137 $this->config->prohibitUrlByConfig($url, $this->io);
43138
43139
43140  $command = call_user_func($commandCallable, $url);
43141
43142 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43143 return;
43144 }
43145
43146
43147  if (preg_match('{^(https?)://((.+)(?:\:(.+))?@)?([^/]+)(/.*)?}mi', $url, $match) && $this->io->hasAuthentication($match[5])) {
43148 $auth = $this->io->getAuthentication($match[5]);
43149 $authenticatedUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[5] . (!empty($match[6]) ? $match[6] : null);
43150
43151 $command = call_user_func($commandCallable, $authenticatedUrl);
43152
43153 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43154 return;
43155 }
43156
43157 $error = $this->process->getErrorOutput();
43158 } else {
43159 $error = 'The given URL (' . $url . ') does not match the required format (http(s)://(username:password@)example.com/path-to-repository)';
43160 }
43161
43162 $this->throwException('Failed to clone ' . $url . ', ' . "\n\n" . $error, $url);
43163 }
43164
43165 public static function sanitizeUrl($message)
43166 {
43167 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
43168 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
43169 return '://***:***@';
43170 }
43171
43172 return '://' . $m[1] . ':***@';
43173 }, $message);
43174 }
43175
43176 private function throwException($message, $url)
43177 {
43178 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
43179 throw new \RuntimeException(self::sanitizeUrl('Failed to clone ' . $url . ', hg was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()));
43180 }
43181
43182 throw new \RuntimeException(self::sanitizeUrl($message));
43183 }
43184 }
43185 <?php
43186
43187
43188
43189
43190
43191
43192
43193
43194
43195
43196
43197 namespace Composer\Util;
43198
43199 use Composer\XdebugHandler\XdebugHandler;
43200
43201
43202
43203
43204
43205
43206
43207
43208 class IniHelper
43209 {
43210
43211
43212
43213
43214
43215
43216
43217
43218 public static function getAll()
43219 {
43220 return XdebugHandler::getAllIniFiles();
43221 }
43222
43223
43224
43225
43226
43227
43228 public static function getMessage()
43229 {
43230 $paths = self::getAll();
43231
43232 if (empty($paths[0])) {
43233 array_shift($paths);
43234 }
43235
43236 $ini = array_shift($paths);
43237
43238 if (empty($ini)) {
43239 return 'A php.ini file does not exist. You will have to create one.';
43240 }
43241
43242 if (!empty($paths)) {
43243 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
43244 }
43245
43246 return 'The php.ini used by your command-line PHP is: '.$ini;
43247 }
43248 }
43249 <?php
43250
43251
43252
43253
43254
43255
43256
43257
43258
43259
43260
43261 namespace Composer\Util;
43262
43263
43264
43265
43266 class NoProxyPattern
43267 {
43268
43269
43270
43271 protected $rules = array();
43272
43273
43274
43275
43276 public function __construct($pattern)
43277 {
43278 $this->rules = preg_split("/[\s,]+/", $pattern);
43279 }
43280
43281
43282
43283
43284
43285
43286
43287
43288 public function test($url)
43289 {
43290 $host = parse_url($url, PHP_URL_HOST);
43291 $port = parse_url($url, PHP_URL_PORT);
43292
43293 if (empty($port)) {
43294 switch (parse_url($url, PHP_URL_SCHEME)) {
43295 case 'http':
43296 $port = 80;
43297 break;
43298 case 'https':
43299 $port = 443;
43300 break;
43301 }
43302 }
43303
43304 foreach ($this->rules as $rule) {
43305 if ($rule == '*') {
43306 return true;
43307 }
43308
43309 $match = false;
43310
43311 list($ruleHost) = explode(':', $rule);
43312 list($base) = explode('/', $ruleHost);
43313
43314 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
43315
43316
43317 if (!isset($ip)) {
43318 $ip = gethostbyname($host);
43319 }
43320
43321 if (strpos($ruleHost, '/') === false) {
43322 $match = $ip === $ruleHost;
43323 } else {
43324
43325  
43326  if ($ip === $host) {
43327 $match = false;
43328 } else {
43329
43330  $match = self::inCIDRBlock($ruleHost, $ip);
43331 }
43332 }
43333 } else {
43334
43335
43336 $haystack = '.' . trim($host, '.') . '.';
43337 $needle = '.'. trim($ruleHost, '.') .'.';
43338 $match = stripos(strrev($haystack), strrev($needle)) === 0;
43339 }
43340
43341
43342  if ($match && strpos($rule, ':') !== false) {
43343 list(, $rulePort) = explode(':', $rule);
43344 if (!empty($rulePort) && $port != $rulePort) {
43345 $match = false;
43346 }
43347 }
43348
43349 if ($match) {
43350 return true;
43351 }
43352 }
43353
43354 return false;
43355 }
43356
43357
43358
43359
43360
43361
43362
43363
43364
43365
43366
43367 private static function inCIDRBlock($cidr, $ip)
43368 {
43369
43370  list($base, $bits) = explode('/', $cidr);
43371
43372
43373  list($a, $b, $c, $d) = explode('.', $base);
43374
43375
43376  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
43377 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
43378
43379
43380  $low = $i & $mask;
43381
43382
43383  $high = $i | (~$mask & 0xFFFFFFFF);
43384
43385
43386  list($a, $b, $c, $d) = explode('.', $ip);
43387
43388
43389  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
43390
43391
43392  
43393  return $check >= $low && $check <= $high;
43394 }
43395 }
43396 <?php
43397
43398
43399 namespace Composer\Util;
43400
43401 use Composer\Package\Link;
43402 use Composer\Package\PackageInterface;
43403
43404 class PackageSorter
43405 {
43406
43407
43408
43409
43410
43411
43412
43413
43414 public static function sortPackages(array $packages) {
43415 $usageList = array();
43416
43417 foreach ($packages as $package) { 
43418 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { 
43419 $target = $link->getTarget();
43420 $usageList[$target][] = $package->getName();
43421 }
43422 }
43423 $computing = array();
43424 $computed = array();
43425 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
43426
43427  if (isset($computed[$name])) {
43428 return $computed[$name];
43429 }
43430
43431
43432  if (isset($computing[$name])) {
43433 return 0;
43434 }
43435
43436 $computing[$name] = true;
43437 $weight = 0;
43438
43439 if (isset($usageList[$name])) {
43440 foreach ($usageList[$name] as $user) {
43441 $weight -= 1 - $computeImportance($user);
43442 }
43443 }
43444
43445 unset($computing[$name]);
43446 $computed[$name] = $weight;
43447
43448 return $weight;
43449 };
43450
43451 $weightList = array();
43452
43453 foreach ($packages as $name => $package) {
43454 $weight = $computeImportance($name);
43455 $weightList[$name] = $weight;
43456 }
43457
43458 $stable_sort = function (&$array) {
43459 static $transform, $restore;
43460
43461 $i = 0;
43462
43463 if (!$transform) {
43464 $transform = function (&$v, $k) use (&$i) {
43465 $v = array($v, ++$i, $k, $v);
43466 };
43467
43468 $restore = function (&$v) {
43469 $v = $v[3];
43470 };
43471 }
43472
43473 array_walk($array, $transform);
43474 asort($array);
43475 array_walk($array, $restore);
43476 };
43477
43478 $stable_sort($weightList);
43479
43480 $sortedPackages = array();
43481
43482 foreach (array_keys($weightList) as $name) {
43483 $sortedPackages[] = $packages[$name];
43484 }
43485 return $sortedPackages;
43486 }
43487 }
43488 <?php
43489
43490
43491
43492
43493
43494
43495
43496
43497
43498
43499
43500 namespace Composer\Util;
43501
43502 use Composer\IO\IOInterface;
43503 use Symfony\Component\Process\Process;
43504
43505
43506
43507
43508 class Perforce
43509 {
43510 protected $path;
43511 protected $p4Depot;
43512 protected $p4Client;
43513 protected $p4User;
43514 protected $p4Password;
43515 protected $p4Port;
43516 protected $p4Stream;
43517 protected $p4ClientSpec;
43518 protected $p4DepotType;
43519 protected $p4Branch;
43520 protected $process;
43521 protected $uniquePerforceClientName;
43522 protected $windowsFlag;
43523 protected $commandResult;
43524
43525 protected $io;
43526
43527 protected $filesystem;
43528
43529 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
43530 {
43531 $this->windowsFlag = $isWindows;
43532 $this->p4Port = $port;
43533 $this->initializePath($path);
43534 $this->process = $process;
43535 $this->initialize($repoConfig);
43536 $this->io = $io;
43537 }
43538
43539 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
43540 {
43541 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
43542 }
43543
43544 public static function checkServerExists($url, ProcessExecutor $processExecutor)
43545 {
43546 $output = null;
43547
43548 return 0 === $processExecutor->execute('p4 -p ' . ProcessExecutor::escape($url) . ' info -s', $output);
43549 }
43550
43551 public function initialize($repoConfig)
43552 {
43553 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
43554 if (!$repoConfig) {
43555 return;
43556 }
43557 if (isset($repoConfig['unique_perforce_client_name'])) {
43558 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
43559 }
43560
43561 if (isset($repoConfig['depot'])) {
43562 $this->p4Depot = $repoConfig['depot'];
43563 }
43564 if (isset($repoConfig['branch'])) {
43565 $this->p4Branch = $repoConfig['branch'];
43566 }
43567 if (isset($repoConfig['p4user'])) {
43568 $this->p4User = $repoConfig['p4user'];
43569 } else {
43570 $this->p4User = $this->getP4variable('P4USER');
43571 }
43572 if (isset($repoConfig['p4password'])) {
43573 $this->p4Password = $repoConfig['p4password'];
43574 }
43575 }
43576
43577 public function initializeDepotAndBranch($depot, $branch)
43578 {
43579 if (isset($depot)) {
43580 $this->p4Depot = $depot;
43581 }
43582 if (isset($branch)) {
43583 $this->p4Branch = $branch;
43584 }
43585 }
43586
43587 public function generateUniquePerforceClientName()
43588 {
43589 return gethostname() . "_" . time();
43590 }
43591
43592 public function cleanupClientSpec()
43593 {
43594 $client = $this->getClient();
43595 $task = 'client -d ' . ProcessExecutor::escape($client);
43596 $useP4Client = false;
43597 $command = $this->generateP4Command($task, $useP4Client);
43598 $this->executeCommand($command);
43599 $clientSpec = $this->getP4ClientSpec();
43600 $fileSystem = $this->getFilesystem();
43601 $fileSystem->remove($clientSpec);
43602 }
43603
43604 protected function executeCommand($command)
43605 {
43606 $this->commandResult = '';
43607
43608 return $this->process->execute($command, $this->commandResult);
43609 }
43610
43611 public function getClient()
43612 {
43613 if (!isset($this->p4Client)) {
43614 $cleanStreamName = str_replace(array('//', '/', '@'), array('', '_', ''), $this->getStream());
43615 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
43616 }
43617
43618 return $this->p4Client;
43619 }
43620
43621 protected function getPath()
43622 {
43623 return $this->path;
43624 }
43625
43626 public function initializePath($path)
43627 {
43628 $this->path = $path;
43629 $fs = $this->getFilesystem();
43630 $fs->ensureDirectoryExists($path);
43631 }
43632
43633 protected function getPort()
43634 {
43635 return $this->p4Port;
43636 }
43637
43638 public function setStream($stream)
43639 {
43640 $this->p4Stream = $stream;
43641 $index = strrpos($stream, '/');
43642
43643  if ($index > 2) {
43644 $this->p4DepotType = 'stream';
43645 }
43646 }
43647
43648 public function isStream()
43649 {
43650 return (strcmp($this->p4DepotType, 'stream') === 0);
43651 }
43652
43653 public function getStream()
43654 {
43655 if (!isset($this->p4Stream)) {
43656 if ($this->isStream()) {
43657 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
43658 } else {
43659 $this->p4Stream = '//' . $this->p4Depot;
43660 }
43661 }
43662
43663 return $this->p4Stream;
43664 }
43665
43666 public function getStreamWithoutLabel($stream)
43667 {
43668 $index = strpos($stream, '@');
43669 if ($index === false) {
43670 return $stream;
43671 }
43672
43673 return substr($stream, 0, $index);
43674 }
43675
43676 public function getP4ClientSpec()
43677 {
43678 return $this->path . '/' . $this->getClient() . '.p4.spec';
43679 }
43680
43681 public function getUser()
43682 {
43683 return $this->p4User;
43684 }
43685
43686 public function setUser($user)
43687 {
43688 $this->p4User = $user;
43689 }
43690
43691 public function queryP4User()
43692 {
43693 $this->getUser();
43694 if (strlen($this->p4User) > 0) {
43695 return;
43696 }
43697 $this->p4User = $this->getP4variable('P4USER');
43698 if (strlen($this->p4User) > 0) {
43699 return;
43700 }
43701 $this->p4User = $this->io->ask('Enter P4 User:');
43702 if ($this->windowsFlag) {
43703 $command = 'p4 set P4USER=' . $this->p4User;
43704 } else {
43705 $command = 'export P4USER=' . $this->p4User;
43706 }
43707 $this->executeCommand($command);
43708 }
43709
43710 protected function getP4variable($name)
43711 {
43712 if ($this->windowsFlag) {
43713 $command = 'p4 set';
43714 $this->executeCommand($command);
43715 $result = trim($this->commandResult);
43716 $resArray = explode(PHP_EOL, $result);
43717 foreach ($resArray as $line) {
43718 $fields = explode('=', $line);
43719 if (strcmp($name, $fields[0]) == 0) {
43720 $index = strpos($fields[1], ' ');
43721 if ($index === false) {
43722 $value = $fields[1];
43723 } else {
43724 $value = substr($fields[1], 0, $index);
43725 }
43726 $value = trim($value);
43727
43728 return $value;
43729 }
43730 }
43731
43732 return null;
43733 }
43734
43735 $command = 'echo $' . $name;
43736 $this->executeCommand($command);
43737 $result = trim($this->commandResult);
43738
43739 return $result;
43740 }
43741
43742 public function queryP4Password()
43743 {
43744 if (isset($this->p4Password)) {
43745 return $this->p4Password;
43746 }
43747 $password = $this->getP4variable('P4PASSWD');
43748 if (strlen($password) <= 0) {
43749 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
43750 }
43751 $this->p4Password = $password;
43752
43753 return $password;
43754 }
43755
43756 public function generateP4Command($command, $useClient = true)
43757 {
43758 $p4Command = 'p4 ';
43759 $p4Command .= '-u ' . $this->getUser() . ' ';
43760 if ($useClient) {
43761 $p4Command .= '-c ' . $this->getClient() . ' ';
43762 }
43763 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ' . $command;
43764
43765 return $p4Command;
43766 }
43767
43768 public function isLoggedIn()
43769 {
43770 $command = $this->generateP4Command('login -s', false);
43771 $exitCode = $this->executeCommand($command);
43772 if ($exitCode) {
43773 $errorOutput = $this->process->getErrorOutput();
43774 $index = strpos($errorOutput, $this->getUser());
43775 if ($index === false) {
43776 $index = strpos($errorOutput, 'p4');
43777 if ($index === false) {
43778 return false;
43779 }
43780 throw new \Exception('p4 command not found in path: ' . $errorOutput);
43781 }
43782 throw new \Exception('Invalid user name: ' . $this->getUser());
43783 }
43784
43785 return true;
43786 }
43787
43788 public function connectClient()
43789 {
43790 $p4CreateClientCommand = $this->generateP4Command(
43791 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
43792 );
43793 $this->executeCommand($p4CreateClientCommand);
43794 }
43795
43796 public function syncCodeBase($sourceReference)
43797 {
43798 $prevDir = getcwd();
43799 chdir($this->path);
43800 $p4SyncCommand = $this->generateP4Command('sync -f ');
43801 if (null !== $sourceReference) {
43802 $p4SyncCommand .= '@' . $sourceReference;
43803 }
43804 $this->executeCommand($p4SyncCommand);
43805 chdir($prevDir);
43806 }
43807
43808 public function writeClientSpecToFile($spec)
43809 {
43810 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
43811 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
43812 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
43813 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
43814 fwrite($spec, 'Description:' . PHP_EOL);
43815 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
43816 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
43817 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
43818 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
43819 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
43820 if ($this->isStream()) {
43821 fwrite($spec, 'Stream:' . PHP_EOL);
43822 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
43823 } else {
43824 fwrite(
43825 $spec,
43826 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
43827 );
43828 }
43829 }
43830
43831 public function writeP4ClientSpec()
43832 {
43833 $clientSpec = $this->getP4ClientSpec();
43834 $spec = fopen($clientSpec, 'w');
43835 try {
43836 $this->writeClientSpecToFile($spec);
43837 } catch (\Exception $e) {
43838 fclose($spec);
43839 throw $e;
43840 }
43841 fclose($spec);
43842 }
43843
43844 protected function read($pipe, $name)
43845 {
43846 if (feof($pipe)) {
43847 return;
43848 }
43849 $line = fgets($pipe);
43850 while ($line !== false) {
43851 $line = fgets($pipe);
43852 }
43853 }
43854
43855 public function windowsLogin($password)
43856 {
43857 $command = $this->generateP4Command(' login -a');
43858
43859
43860  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
43861 $process = Process::fromShellCommandline($command, null, null, $password);
43862 } else {
43863 $process = new Process($command, null, null, $password);
43864 }
43865
43866 return $process->run();
43867 }
43868
43869 public function p4Login()
43870 {
43871 $this->queryP4User();
43872 if (!$this->isLoggedIn()) {
43873 $password = $this->queryP4Password();
43874 if ($this->windowsFlag) {
43875 $this->windowsLogin($password);
43876 } else {
43877 $command = 'echo ' . ProcessExecutor::escape($password) . ' | ' . $this->generateP4Command(' login -a', false);
43878 $exitCode = $this->executeCommand($command);
43879 $result = trim($this->commandResult);
43880 if ($exitCode) {
43881 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
43882 }
43883 }
43884 }
43885 }
43886
43887 public function getComposerInformation($identifier)
43888 {
43889 $composerFileContent = $this->getFileContent('composer.json', $identifier);
43890
43891 if (!$composerFileContent) {
43892 return;
43893 }
43894
43895 return json_decode($composerFileContent, true);
43896 }
43897
43898 public function getFileContent($file, $identifier)
43899 {
43900 $path = $this->getFilePath($file, $identifier);
43901
43902 $command = $this->generateP4Command(' print ' . ProcessExecutor::escape($path));
43903 $this->executeCommand($command);
43904 $result = $this->commandResult;
43905
43906 if (!trim($result)) {
43907 return null;
43908 }
43909
43910 return $result;
43911 }
43912
43913 public function getFilePath($file, $identifier)
43914 {
43915 $index = strpos($identifier, '@');
43916 if ($index === false) {
43917 $path = $identifier. '/' . $file;
43918
43919 return $path;
43920 }
43921
43922 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
43923 $command = $this->generateP4Command(' files ' . ProcessExecutor::escape($path), false);
43924 $this->executeCommand($command);
43925 $result = $this->commandResult;
43926 $index2 = strpos($result, 'no such file(s).');
43927 if ($index2 === false) {
43928 $index3 = strpos($result, 'change');
43929 if ($index3 !== false) {
43930 $phrase = trim(substr($result, $index3));
43931 $fields = explode(' ', $phrase);
43932
43933 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
43934 }
43935 }
43936
43937 return null;
43938 }
43939
43940 public function getBranches()
43941 {
43942 $possibleBranches = array();
43943 if (!$this->isStream()) {
43944 $possibleBranches[$this->p4Branch] = $this->getStream();
43945 } else {
43946 $command = $this->generateP4Command('streams '.ProcessExecutor::escape('//' . $this->p4Depot . '/...'));
43947 $this->executeCommand($command);
43948 $result = $this->commandResult;
43949 $resArray = explode(PHP_EOL, $result);
43950 foreach ($resArray as $line) {
43951 $resBits = explode(' ', $line);
43952 if (count($resBits) > 4) {
43953 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
43954 $possibleBranches[$branch] = $resBits[1];
43955 }
43956 }
43957 }
43958 $command = $this->generateP4Command('changes '. ProcessExecutor::escape($this->getStream() . '/...'), false);
43959 $this->executeCommand($command);
43960 $result = $this->commandResult;
43961 $resArray = explode(PHP_EOL, $result);
43962 $lastCommit = $resArray[0];
43963 $lastCommitArr = explode(' ', $lastCommit);
43964 $lastCommitNum = $lastCommitArr[1];
43965
43966 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
43967
43968 return $branches;
43969 }
43970
43971 public function getTags()
43972 {
43973 $command = $this->generateP4Command('labels');
43974 $this->executeCommand($command);
43975 $result = $this->commandResult;
43976 $resArray = explode(PHP_EOL, $result);
43977 $tags = array();
43978 foreach ($resArray as $line) {
43979 if (strpos($line, 'Label') !== false) {
43980 $fields = explode(' ', $line);
43981 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
43982 }
43983 }
43984
43985 return $tags;
43986 }
43987
43988 public function checkStream()
43989 {
43990 $command = $this->generateP4Command('depots', false);
43991 $this->executeCommand($command);
43992 $result = $this->commandResult;
43993 $resArray = explode(PHP_EOL, $result);
43994 foreach ($resArray as $line) {
43995 if (strpos($line, 'Depot') !== false) {
43996 $fields = explode(' ', $line);
43997 if (strcmp($this->p4Depot, $fields[1]) === 0) {
43998 $this->p4DepotType = $fields[3];
43999
44000 return $this->isStream();
44001 }
44002 }
44003 }
44004
44005 return false;
44006 }
44007
44008
44009
44010
44011
44012 protected function getChangeList($reference)
44013 {
44014 $index = strpos($reference, '@');
44015 if ($index === false) {
44016 return null;
44017 }
44018 $label = substr($reference, $index);
44019 $command = $this->generateP4Command(' changes -m1 ' . ProcessExecutor::escape($label));
44020 $this->executeCommand($command);
44021 $changes = $this->commandResult;
44022 if (strpos($changes, 'Change') !== 0) {
44023 return null;
44024 }
44025 $fields = explode(' ', $changes);
44026
44027 return $fields[1];
44028 }
44029
44030
44031
44032
44033
44034
44035 public function getCommitLogs($fromReference, $toReference)
44036 {
44037 $fromChangeList = $this->getChangeList($fromReference);
44038 if ($fromChangeList === null) {
44039 return null;
44040 }
44041 $toChangeList = $this->getChangeList($toReference);
44042 if ($toChangeList === null) {
44043 return null;
44044 }
44045 $index = strpos($fromReference, '@');
44046 $main = substr($fromReference, 0, $index) . '/...';
44047 $command = $this->generateP4Command('filelog ' . ProcessExecutor::escape($main . '@' . $fromChangeList. ',' . $toChangeList));
44048 $this->executeCommand($command);
44049
44050 return $this->commandResult;
44051 }
44052
44053 public function getFilesystem()
44054 {
44055 if (empty($this->filesystem)) {
44056 $this->filesystem = new Filesystem($this->process);
44057 }
44058
44059 return $this->filesystem;
44060 }
44061
44062 public function setFilesystem(Filesystem $fs)
44063 {
44064 $this->filesystem = $fs;
44065 }
44066 }
44067 <?php
44068
44069
44070
44071
44072
44073
44074
44075
44076
44077
44078
44079 namespace Composer\Util;
44080
44081
44082
44083
44084
44085
44086 class Platform
44087 {
44088
44089
44090
44091
44092
44093
44094 public static function expandPath($path)
44095 {
44096 if (preg_match('#^~[\\/]#', $path)) {
44097 return self::getUserDirectory() . substr($path, 1);
44098 }
44099
44100 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
44101
44102  if (Platform::isWindows() && $matches['var'] == 'HOME') {
44103 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
44104 }
44105
44106 return getenv($matches['var']) . $matches['path'];
44107 }, $path);
44108 }
44109
44110
44111
44112
44113
44114 public static function getUserDirectory()
44115 {
44116 if (false !== ($home = getenv('HOME'))) {
44117 return $home;
44118 }
44119
44120 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
44121 return $home;
44122 }
44123
44124 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
44125 $info = posix_getpwuid(posix_getuid());
44126
44127 return $info['dir'];
44128 }
44129
44130 throw new \RuntimeException('Could not determine user directory');
44131 }
44132
44133
44134
44135
44136 public static function isWindows()
44137 {
44138 return defined('PHP_WINDOWS_VERSION_BUILD');
44139 }
44140
44141
44142
44143
44144
44145 public static function strlen($str)
44146 {
44147 static $useMbString = null;
44148 if (null === $useMbString) {
44149 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
44150 }
44151
44152 if ($useMbString) {
44153 return mb_strlen($str, '8bit');
44154 }
44155
44156 return strlen($str);
44157 }
44158 }
44159 <?php
44160
44161
44162
44163
44164
44165
44166
44167
44168
44169
44170
44171 namespace Composer\Util;
44172
44173 use Composer\IO\IOInterface;
44174 use Symfony\Component\Process\Process;
44175 use Symfony\Component\Process\ProcessUtils;
44176
44177
44178
44179
44180 class ProcessExecutor
44181 {
44182 protected static $timeout = 300;
44183
44184 protected $captureOutput;
44185 protected $errorOutput;
44186 protected $io;
44187
44188 public function __construct(IOInterface $io = null)
44189 {
44190 $this->io = $io;
44191 }
44192
44193
44194
44195
44196
44197
44198
44199
44200
44201
44202 public function execute($command, &$output = null, $cwd = null)
44203 {
44204 if ($this->io && $this->io->isDebug()) {
44205 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
44206 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
44207 return '://***:***@';
44208 }
44209
44210 return '://'.$m['user'].':***@';
44211 }, $command);
44212 $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand);
44213 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
44214 }
44215
44216
44217  
44218  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
44219 $cwd = realpath(getcwd());
44220 }
44221
44222 $this->captureOutput = func_num_args() > 1;
44223 $this->errorOutput = null;
44224
44225
44226  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
44227 $process = Process::fromShellCommandline($command, $cwd, null, null, static::getTimeout());
44228 } else {
44229 $process = new Process($command, $cwd, null, null, static::getTimeout());
44230 }
44231
44232 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
44233 $process->run($callback);
44234
44235 if ($this->captureOutput && !is_callable($output)) {
44236 $output = $process->getOutput();
44237 }
44238
44239 $this->errorOutput = $process->getErrorOutput();
44240
44241 return $process->getExitCode();
44242 }
44243
44244 public function splitLines($output)
44245 {
44246 $output = trim($output);
44247
44248 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
44249 }
44250
44251
44252
44253
44254
44255
44256 public function getErrorOutput()
44257 {
44258 return $this->errorOutput;
44259 }
44260
44261 public function outputHandler($type, $buffer)
44262 {
44263 if ($this->captureOutput) {
44264 return;
44265 }
44266
44267 if (null === $this->io) {
44268 echo $buffer;
44269
44270 return;
44271 }
44272
44273 if (method_exists($this->io, 'writeRaw')) {
44274 if (Process::ERR === $type) {
44275 $this->io->writeErrorRaw($buffer, false);
44276 } else {
44277 $this->io->writeRaw($buffer, false);
44278 }
44279 } else {
44280 if (Process::ERR === $type) {
44281 $this->io->writeError($buffer, false);
44282 } else {
44283 $this->io->write($buffer, false);
44284 }
44285 }
44286 }
44287
44288 public static function getTimeout()
44289 {
44290 return static::$timeout;
44291 }
44292
44293 public static function setTimeout($timeout)
44294 {
44295 static::$timeout = $timeout;
44296 }
44297
44298
44299
44300
44301
44302
44303
44304
44305 public static function escape($argument)
44306 {
44307 return self::escapeArgument($argument);
44308 }
44309
44310
44311
44312
44313
44314
44315
44316
44317 private static function escapeArgument($argument)
44318 {
44319
44320  
44321  
44322  
44323  if ('\\' === DIRECTORY_SEPARATOR) {
44324 if ((string) $argument === '') {
44325 return escapeshellarg($argument);
44326 }
44327
44328 $escapedArgument = '';
44329 $quote = false;
44330 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
44331 if ('"' === $part) {
44332 $escapedArgument .= '\\"';
44333 } elseif (self::isSurroundedBy($part, '%')) {
44334
44335  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
44336 } else {
44337
44338  if ('\\' === substr($part, -1)) {
44339 $part .= '\\';
44340 }
44341 $quote = true;
44342 $escapedArgument .= $part;
44343 }
44344 }
44345 if ($quote) {
44346 $escapedArgument = '"'.$escapedArgument.'"';
44347 }
44348
44349 return $escapedArgument;
44350 }
44351
44352 return "'".str_replace("'", "'\\''", $argument)."'";
44353 }
44354
44355 private static function isSurroundedBy($arg, $char)
44356 {
44357 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
44358 }
44359 }
44360 <?php
44361
44362
44363
44364
44365
44366
44367
44368
44369
44370
44371
44372 namespace Composer\Util;
44373
44374 use Composer\Config;
44375 use Composer\Composer;
44376 use Composer\Semver\Constraint\Constraint;
44377 use Composer\Package\Version\VersionParser;
44378 use Composer\IO\IOInterface;
44379 use Composer\Downloader\TransportException;
44380 use Composer\CaBundle\CaBundle;
44381 use Psr\Log\LoggerInterface;
44382
44383
44384
44385
44386
44387
44388 class RemoteFilesystem
44389 {
44390 private $io;
44391 private $config;
44392 private $scheme;
44393 private $bytesMax;
44394 private $originUrl;
44395 private $fileUrl;
44396 private $fileName;
44397 private $retry;
44398 private $progress;
44399 private $lastProgress;
44400 private $options = array();
44401 private $peerCertificateMap = array();
44402 private $disableTls = false;
44403 private $retryAuthFailure;
44404 private $lastHeaders;
44405 private $storeAuth;
44406 private $degradedMode = false;
44407 private $redirects;
44408 private $maxRedirects = 20;
44409
44410
44411
44412
44413
44414
44415
44416
44417
44418 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
44419 {
44420 $this->io = $io;
44421
44422
44423  
44424  if ($disableTls === false) {
44425 $this->options = $this->getTlsDefaults($options);
44426 } else {
44427 $this->disableTls = true;
44428 }
44429
44430
44431  $this->options = array_replace_recursive($this->options, $options);
44432 $this->config = $config;
44433 }
44434
44435
44436
44437
44438
44439
44440
44441
44442
44443
44444
44445
44446 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
44447 {
44448 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
44449 }
44450
44451
44452
44453
44454
44455
44456
44457
44458
44459
44460
44461 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
44462 {
44463 return $this->get($originUrl, $fileUrl, $options, null, $progress);
44464 }
44465
44466
44467
44468
44469
44470
44471 public function getOptions()
44472 {
44473 return $this->options;
44474 }
44475
44476
44477
44478
44479
44480
44481 public function setOptions(array $options)
44482 {
44483 $this->options = array_replace_recursive($this->options, $options);
44484 }
44485
44486
44487
44488
44489
44490
44491 public function isTlsDisabled()
44492 {
44493 return $this->disableTls === true;
44494 }
44495
44496
44497
44498
44499
44500
44501 public function getLastHeaders()
44502 {
44503 return $this->lastHeaders;
44504 }
44505
44506
44507
44508
44509
44510
44511 public function findHeaderValue(array $headers, $name)
44512 {
44513 $value = null;
44514 foreach ($headers as $header) {
44515 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
44516 $value = $match[1];
44517 } elseif (preg_match('{^HTTP/}i', $header)) {
44518
44519  
44520  $value = null;
44521 }
44522 }
44523
44524 return $value;
44525 }
44526
44527
44528
44529
44530
44531 public function findStatusCode(array $headers)
44532 {
44533 $value = null;
44534 foreach ($headers as $header) {
44535 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
44536
44537  
44538  $value = (int) $match[1];
44539 }
44540 }
44541
44542 return $value;
44543 }
44544
44545
44546
44547
44548
44549 public function findStatusMessage(array $headers)
44550 {
44551 $value = null;
44552 foreach ($headers as $header) {
44553 if (preg_match('{^HTTP/\S+ \d+}i', $header)) {
44554
44555  
44556  $value = $header;
44557 }
44558 }
44559
44560 return $value;
44561 }
44562
44563
44564
44565
44566
44567
44568
44569
44570
44571
44572
44573
44574
44575
44576
44577 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
44578 {
44579 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
44580 $originUrl = 'github.com';
44581 }
44582
44583
44584  
44585  if (
44586 $this->config
44587 && is_array($this->config->get('gitlab-domains'))
44588 && false === strpos($originUrl, '/')
44589 && !in_array($originUrl, $this->config->get('gitlab-domains'))
44590 ) {
44591 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
44592 if (0 === strpos($gitlabDomain, $originUrl)) {
44593 $originUrl = $gitlabDomain;
44594 break;
44595 }
44596 }
44597 unset($gitlabDomain);
44598 }
44599
44600 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
44601 $this->bytesMax = 0;
44602 $this->originUrl = $originUrl;
44603 $this->fileUrl = $fileUrl;
44604 $this->fileName = $fileName;
44605 $this->progress = $progress;
44606 $this->lastProgress = null;
44607 $this->retryAuthFailure = true;
44608 $this->lastHeaders = array();
44609 $this->redirects = 1; 
44610
44611
44612  if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
44613 $this->io->setAuthentication($originUrl, rawurldecode($match[1]), rawurldecode($match[2]));
44614 }
44615
44616 $tempAdditionalOptions = $additionalOptions;
44617 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
44618 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
44619
44620 unset($tempAdditionalOptions['retry-auth-failure']);
44621 }
44622
44623 $isRedirect = false;
44624 if (isset($tempAdditionalOptions['redirects'])) {
44625 $this->redirects = $tempAdditionalOptions['redirects'];
44626 $isRedirect = true;
44627
44628 unset($tempAdditionalOptions['redirects']);
44629 }
44630
44631 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
44632 unset($tempAdditionalOptions);
44633
44634 $origFileUrl = $fileUrl;
44635
44636 if (isset($options['github-token'])) {
44637
44638  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
44639 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
44640 }
44641 unset($options['github-token']);
44642 }
44643
44644 if (isset($options['gitlab-token'])) {
44645 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
44646 unset($options['gitlab-token']);
44647 }
44648
44649 if (isset($options['http'])) {
44650 $options['http']['ignore_errors'] = true;
44651 }
44652
44653 if ($this->degradedMode && substr($fileUrl, 0, 26) === 'http://repo.packagist.org/') {
44654
44655  $fileUrl = 'http://' . gethostbyname('repo.packagist.org') . substr($fileUrl, 20);
44656 $degradedPackagist = true;
44657 }
44658
44659 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
44660
44661 $actualContextOptions = stream_context_get_options($ctx);
44662 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
44663 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $this->stripCredentialsFromUrl($origFileUrl) . $usingProxy, true, IOInterface::DEBUG);
44664 unset($origFileUrl, $actualContextOptions);
44665
44666
44667  if ((!preg_match('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
44668 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
44669 }
44670
44671 if ($this->progress && !$isRedirect) {
44672 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
44673 }
44674
44675 $errorMessage = '';
44676 $errorCode = 0;
44677 $result = false;
44678 set_error_handler(function ($code, $msg) use (&$errorMessage) {
44679 if ($errorMessage) {
44680 $errorMessage .= "\n";
44681 }
44682 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
44683
44684 return true;
44685 });
44686 try {
44687 $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header);
44688
44689 if (!empty($http_response_header[0])) {
44690 $statusCode = $this->findStatusCode($http_response_header);
44691 if ($statusCode >= 400 && $this->findHeaderValue($http_response_header, 'content-type') === 'application/json') {
44692 self::outputWarnings($this->io, $originUrl, json_decode($result, true));
44693 }
44694
44695 if (in_array($statusCode, array(401, 403)) && $this->retryAuthFailure) {
44696 $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), null, $http_response_header);
44697 }
44698 }
44699
44700 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
44701 if ($contentLength && Platform::strlen($result) < $contentLength) {
44702
44703  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
44704 $e->setHeaders($http_response_header);
44705 $e->setStatusCode($this->findStatusCode($http_response_header));
44706 $e->setResponse($result);
44707 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
44708
44709 throw $e;
44710 }
44711
44712 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
44713
44714  $params = stream_context_get_params($ctx);
44715 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
44716 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
44717
44718
44719  if ($expectedPeerFingerprint !== $peerFingerprint) {
44720 throw new TransportException('Peer fingerprint did not match');
44721 }
44722 }
44723 } catch (\Exception $e) {
44724 if ($e instanceof TransportException && !empty($http_response_header[0])) {
44725 $e->setHeaders($http_response_header);
44726 $e->setStatusCode($this->findStatusCode($http_response_header));
44727 }
44728 if ($e instanceof TransportException && $result !== false) {
44729 $e->setResponse($result);
44730 }
44731 $result = false;
44732 }
44733 if ($errorMessage && !filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
44734 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
44735 }
44736 restore_error_handler();
44737 if (isset($e) && !$this->retry) {
44738 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
44739 $this->degradedMode = true;
44740 $this->io->writeError('');
44741 $this->io->writeError(array(
44742 '<error>'.$e->getMessage().'</error>',
44743 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
44744 ));
44745
44746 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44747 }
44748
44749 throw $e;
44750 }
44751
44752 $statusCode = null;
44753 $contentType = null;
44754 $locationHeader = null;
44755 if (!empty($http_response_header[0])) {
44756 $statusCode = $this->findStatusCode($http_response_header);
44757 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
44758 $locationHeader = $this->findHeaderValue($http_response_header, 'location');
44759 }
44760
44761
44762  if ($originUrl === 'bitbucket.org'
44763 && !$this->isPublicBitBucketDownload($fileUrl)
44764 && substr($fileUrl, -4) === '.zip'
44765 && (!$locationHeader || substr($locationHeader, -4) !== '.zip')
44766 && $contentType && preg_match('{^text/html\b}i', $contentType)
44767 ) {
44768 $result = false;
44769 if ($this->retryAuthFailure) {
44770 $this->promptAuthAndRetry(401);
44771 }
44772 }
44773
44774
44775  if ($statusCode === 404
44776 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
44777 && false !== strpos($fileUrl, 'archive.zip')
44778 ) {
44779 $result = false;
44780 if ($this->retryAuthFailure) {
44781 $this->promptAuthAndRetry(401);
44782 }
44783 }
44784
44785
44786  $hasFollowedRedirect = false;
44787 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
44788 $hasFollowedRedirect = true;
44789 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
44790 }
44791
44792
44793  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
44794 if (!$this->retry) {
44795 if ($this->progress && !$this->retry && !$isRedirect) {
44796 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
44797 }
44798
44799 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
44800 $e->setHeaders($http_response_header);
44801 $e->setResponse($result);
44802 $e->setStatusCode($statusCode);
44803 throw $e;
44804 }
44805 $result = false;
44806 }
44807
44808 if ($this->progress && !$this->retry && !$isRedirect) {
44809 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
44810 }
44811
44812
44813  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
44814 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
44815 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
44816
44817 if ($decode) {
44818 try {
44819 if (PHP_VERSION_ID >= 50400) {
44820 $result = zlib_decode($result);
44821 } else {
44822
44823  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
44824 }
44825
44826 if (!$result) {
44827 throw new TransportException('Failed to decode zlib stream');
44828 }
44829 } catch (\Exception $e) {
44830 if ($this->degradedMode) {
44831 throw $e;
44832 }
44833
44834 $this->degradedMode = true;
44835 $this->io->writeError(array(
44836 '',
44837 '<error>Failed to decode response: '.$e->getMessage().'</error>',
44838 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
44839 ));
44840
44841 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44842 }
44843 }
44844 }
44845
44846
44847  if (false !== $result && null !== $fileName && !$isRedirect) {
44848 if ('' === $result) {
44849 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
44850 }
44851
44852 $errorMessage = '';
44853 set_error_handler(function ($code, $msg) use (&$errorMessage) {
44854 if ($errorMessage) {
44855 $errorMessage .= "\n";
44856 }
44857 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
44858
44859 return true;
44860 });
44861 $result = (bool) file_put_contents($fileName, $result);
44862 restore_error_handler();
44863 if (false === $result) {
44864 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
44865 }
44866 }
44867
44868
44869  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
44870
44871  
44872  
44873  
44874  
44875  
44876  
44877  
44878  
44879  
44880  
44881  
44882  
44883  
44884  
44885  
44886  if (CaBundle::isOpensslParseSafe()) {
44887 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
44888
44889 if ($certDetails) {
44890 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
44891
44892 $this->retry = true;
44893 }
44894 } else {
44895 $this->io->writeError('');
44896 $this->io->writeError(sprintf(
44897 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
44898 PHP_VERSION
44899 ));
44900 }
44901 }
44902
44903 if ($this->retry) {
44904 $this->retry = false;
44905
44906 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44907
44908 if ($this->storeAuth && $this->config) {
44909 $authHelper = new AuthHelper($this->io, $this->config);
44910 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
44911 $this->storeAuth = false;
44912 }
44913
44914 return $result;
44915 }
44916
44917 if (false === $result) {
44918 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
44919 if (!empty($http_response_header[0])) {
44920 $e->setHeaders($http_response_header);
44921 }
44922
44923 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
44924 $this->degradedMode = true;
44925 $this->io->writeError('');
44926 $this->io->writeError(array(
44927 '<error>'.$e->getMessage().'</error>',
44928 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
44929 ));
44930
44931 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44932 }
44933
44934 throw $e;
44935 }
44936
44937 if (!empty($http_response_header[0])) {
44938 $this->lastHeaders = $http_response_header;
44939 }
44940
44941 return $result;
44942 }
44943
44944
44945
44946
44947
44948
44949
44950
44951
44952
44953 protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null)
44954 {
44955 try {
44956 $e = null;
44957 $result = file_get_contents($fileUrl, false, $context);
44958 } catch (\Throwable $e) {
44959 } catch (\Exception $e) {
44960 }
44961
44962 $responseHeaders = isset($http_response_header) ? $http_response_header : array();
44963
44964 if (null !== $e) {
44965 throw $e;
44966 }
44967
44968 return $result;
44969 }
44970
44971
44972
44973
44974
44975
44976
44977
44978
44979
44980
44981
44982 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
44983 {
44984 switch ($notificationCode) {
44985 case STREAM_NOTIFY_FAILURE:
44986 if (400 === $messageCode) {
44987
44988  
44989  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
44990 }
44991 break;
44992
44993 case STREAM_NOTIFY_FILE_SIZE_IS:
44994 $this->bytesMax = $bytesMax;
44995 break;
44996
44997 case STREAM_NOTIFY_PROGRESS:
44998 if ($this->bytesMax > 0 && $this->progress) {
44999 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
45000
45001 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
45002 $this->lastProgress = $progression;
45003 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
45004 }
45005 }
45006 break;
45007
45008 default:
45009 break;
45010 }
45011 }
45012
45013 protected function promptAuthAndRetry($httpStatus, $reason = null, $warning = null, $headers = array())
45014 {
45015 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
45016 $gitHubUtil = new GitHub($this->io, $this->config, null);
45017 $message = "\n";
45018
45019 $rateLimited = $gitHubUtil->isRateLimited($headers);
45020 if ($rateLimited) {
45021 $rateLimit = $gitHubUtil->getRateLimit($headers);
45022 if ($this->io->hasAuthentication($this->originUrl)) {
45023 $message = 'Review your configured GitHub OAuth token or enter a new one to go over the API rate limit.';
45024 } else {
45025 $message = 'Create a GitHub OAuth token to go over the API rate limit.';
45026 }
45027
45028 $message = sprintf(
45029 'GitHub API limit (%d calls/hr) is exhausted, could not fetch '.$this->fileUrl.'. '.$message.' You can also wait until %s for the rate limit to reset.',
45030 $rateLimit['limit'],
45031 $rateLimit['reset']
45032 )."\n";
45033 } else {
45034 $message .= 'Could not fetch '.$this->fileUrl.', please ';
45035 if ($this->io->hasAuthentication($this->originUrl)) {
45036 $message .= 'review your configured GitHub OAuth token or enter a new one to access private repos';
45037 } else {
45038 $message .= 'create a GitHub OAuth token to access private repos';
45039 }
45040 }
45041
45042 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
45043 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
45044 ) {
45045 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
45046 }
45047 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
45048 $message = "\n".'Could not fetch '.$this->fileUrl.', enter your ' . $this->originUrl . ' credentials ' .($httpStatus === 401 ? 'to access private repos' : 'to go over the API rate limit');
45049 $gitLabUtil = new GitLab($this->io, $this->config, null);
45050
45051 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && in_array($auth['password'], array('gitlab-ci-token', 'private-token'), true)) {
45052 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
45053 }
45054
45055 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
45056 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
45057 ) {
45058 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
45059 }
45060 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
45061 $askForOAuthToken = true;
45062 if ($this->io->hasAuthentication($this->originUrl)) {
45063 $auth = $this->io->getAuthentication($this->originUrl);
45064 if ($auth['username'] !== 'x-token-auth') {
45065 $bitbucketUtil = new Bitbucket($this->io, $this->config);
45066 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
45067 if (!empty($accessToken)) {
45068 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
45069 $askForOAuthToken = false;
45070 }
45071 } else {
45072 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
45073 }
45074 }
45075
45076 if ($askForOAuthToken) {
45077 $message = "\n".'Could not fetch ' . $this->fileUrl . ', please create a bitbucket OAuth token to ' . (($httpStatus === 401 || $httpStatus === 403) ? 'access private repos' : 'go over the API rate limit');
45078 $bitBucketUtil = new Bitbucket($this->io, $this->config);
45079 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
45080 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
45081 ) {
45082 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
45083 }
45084 }
45085 } else {
45086
45087  if ($httpStatus === 404) {
45088 return;
45089 }
45090
45091
45092  if (!$this->io->isInteractive()) {
45093 if ($httpStatus === 401) {
45094 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
45095 }
45096 if ($httpStatus === 403) {
45097 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
45098 }
45099
45100 throw new TransportException($message, $httpStatus);
45101 }
45102
45103  if ($this->io->hasAuthentication($this->originUrl)) {
45104 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
45105 }
45106
45107 $this->io->writeError('    Authentication required (<info>'.$this->originUrl.'</info>):');
45108 $username = $this->io->ask('      Username: ');
45109 $password = $this->io->askAndHideAnswer('      Password: ');
45110 $this->io->setAuthentication($this->originUrl, $username, $password);
45111 $this->storeAuth = $this->config->get('store-auths');
45112 }
45113
45114 $this->retry = true;
45115 throw new TransportException('RETRY');
45116 }
45117
45118 protected function getOptionsForUrl($originUrl, $additionalOptions)
45119 {
45120 $tlsOptions = array();
45121
45122
45123  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
45124 $host = parse_url($this->fileUrl, PHP_URL_HOST);
45125
45126 if (PHP_VERSION_ID < 50304) {
45127
45128  
45129  
45130  
45131
45132 if ($host === 'github.com' || $host === 'api.github.com') {
45133 $host = '*.github.com';
45134 }
45135 }
45136
45137 $tlsOptions['ssl']['CN_match'] = $host;
45138 $tlsOptions['ssl']['SNI_server_name'] = $host;
45139
45140 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
45141
45142 if (isset($this->peerCertificateMap[$urlAuthority])) {
45143
45144  $certMap = $this->peerCertificateMap[$urlAuthority];
45145
45146 $this->io->writeError('', true, IOInterface::DEBUG);
45147 $this->io->writeError(sprintf(
45148 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
45149 $certMap['cn'],
45150 $urlAuthority
45151 ), true, IOInterface::DEBUG);
45152
45153 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
45154 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
45155 } elseif (!CaBundle::isOpensslParseSafe() && $host === 'repo.packagist.org') {
45156
45157  $tlsOptions['ssl']['CN_match'] = 'packagist.org';
45158 }
45159 }
45160
45161 $headers = array();
45162
45163 if (extension_loaded('zlib')) {
45164 $headers[] = 'Accept-Encoding: gzip';
45165 }
45166
45167 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
45168 if (!$this->degradedMode) {
45169
45170  
45171  $options['http']['protocol_version'] = 1.1;
45172 $headers[] = 'Connection: close';
45173 }
45174
45175 if ($this->io->hasAuthentication($originUrl)) {
45176 $auth = $this->io->getAuthentication($originUrl);
45177 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
45178 $options['github-token'] = $auth['username'];
45179 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
45180 if ($auth['password'] === 'oauth2') {
45181 $headers[] = 'Authorization: Bearer '.$auth['username'];
45182 } elseif ($auth['password'] === 'private-token' || $auth['password'] === 'gitlab-ci-token') {
45183 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
45184 }
45185 } elseif ('bitbucket.org' === $originUrl
45186 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
45187 ) {
45188 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
45189 $headers[] = 'Authorization: Bearer ' . $auth['password'];
45190 }
45191 } else {
45192 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
45193 $headers[] = 'Authorization: Basic '.$authStr;
45194 }
45195 }
45196
45197 $options['http']['follow_location'] = 0;
45198
45199 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
45200 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
45201 }
45202 foreach ($headers as $header) {
45203 $options['http']['header'][] = $header;
45204 }
45205
45206 return $options;
45207 }
45208
45209 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
45210 {
45211 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
45212 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
45213
45214  $targetUrl = $locationHeader;
45215 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
45216
45217  $targetUrl = $this->scheme.':'.$locationHeader;
45218 } elseif ('/' === $locationHeader[0]) {
45219
45220  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
45221
45222
45223  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
45224 } else {
45225
45226  
45227  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
45228 }
45229 }
45230
45231 if (!empty($targetUrl)) {
45232 $this->redirects++;
45233
45234 $this->io->writeError('', true, IOInterface::DEBUG);
45235 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $this->stripCredentialsFromUrl($targetUrl)), true, IOInterface::DEBUG);
45236
45237 $additionalOptions['redirects'] = $this->redirects;
45238
45239 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
45240 }
45241
45242 if (!$this->retry) {
45243 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
45244 $e->setHeaders($http_response_header);
45245 $e->setResponse($result);
45246
45247 throw $e;
45248 }
45249
45250 return false;
45251 }
45252
45253
45254
45255
45256
45257
45258 private function getTlsDefaults(array $options)
45259 {
45260 $ciphers = implode(':', array(
45261 'ECDHE-RSA-AES128-GCM-SHA256',
45262 'ECDHE-ECDSA-AES128-GCM-SHA256',
45263 'ECDHE-RSA-AES256-GCM-SHA384',
45264 'ECDHE-ECDSA-AES256-GCM-SHA384',
45265 'DHE-RSA-AES128-GCM-SHA256',
45266 'DHE-DSS-AES128-GCM-SHA256',
45267 'kEDH+AESGCM',
45268 'ECDHE-RSA-AES128-SHA256',
45269 'ECDHE-ECDSA-AES128-SHA256',
45270 'ECDHE-RSA-AES128-SHA',
45271 'ECDHE-ECDSA-AES128-SHA',
45272 'ECDHE-RSA-AES256-SHA384',
45273 'ECDHE-ECDSA-AES256-SHA384',
45274 'ECDHE-RSA-AES256-SHA',
45275 'ECDHE-ECDSA-AES256-SHA',
45276 'DHE-RSA-AES128-SHA256',
45277 'DHE-RSA-AES128-SHA',
45278 'DHE-DSS-AES128-SHA256',
45279 'DHE-RSA-AES256-SHA256',
45280 'DHE-DSS-AES256-SHA',
45281 'DHE-RSA-AES256-SHA',
45282 'AES128-GCM-SHA256',
45283 'AES256-GCM-SHA384',
45284 'AES128-SHA256',
45285 'AES256-SHA256',
45286 'AES128-SHA',
45287 'AES256-SHA',
45288 'AES',
45289 'CAMELLIA',
45290 'DES-CBC3-SHA',
45291 '!aNULL',
45292 '!eNULL',
45293 '!EXPORT',
45294 '!DES',
45295 '!RC4',
45296 '!MD5',
45297 '!PSK',
45298 '!aECDH',
45299 '!EDH-DSS-DES-CBC3-SHA',
45300 '!EDH-RSA-DES-CBC3-SHA',
45301 '!KRB5-DES-CBC3-SHA',
45302 ));
45303
45304
45305
45306
45307
45308
45309
45310 $defaults = array(
45311 'ssl' => array(
45312 'ciphers' => $ciphers,
45313 'verify_peer' => true,
45314 'verify_depth' => 7,
45315 'SNI_enabled' => true,
45316 'capture_peer_cert' => true,
45317 ),
45318 );
45319
45320 if (isset($options['ssl'])) {
45321 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
45322 }
45323
45324 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
45325
45326
45327
45328
45329
45330 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
45331 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
45332
45333 if (is_dir($result)) {
45334 $defaults['ssl']['capath'] = $result;
45335 } else {
45336 $defaults['ssl']['cafile'] = $result;
45337 }
45338 }
45339
45340 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
45341 throw new TransportException('The configured cafile was not valid or could not be read.');
45342 }
45343
45344 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
45345 throw new TransportException('The configured capath was not valid or could not be read.');
45346 }
45347
45348
45349
45350
45351 if (PHP_VERSION_ID >= 50413) {
45352 $defaults['ssl']['disable_compression'] = true;
45353 }
45354
45355 return $defaults;
45356 }
45357
45358
45359
45360
45361
45362
45363 private function getCertificateCnAndFp($url, $options)
45364 {
45365 if (PHP_VERSION_ID >= 50600) {
45366 throw new \BadMethodCallException(sprintf(
45367 '%s must not be used on PHP >= 5.6',
45368 __METHOD__
45369 ));
45370 }
45371
45372 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
45373 'ssl' => array(
45374 'capture_peer_cert' => true,
45375 'verify_peer' => false, 
45376  ), ),
45377 ));
45378
45379
45380  
45381  if (false === $handle = @fopen($url, 'rb', false, $context)) {
45382 return;
45383 }
45384
45385
45386  fclose($handle);
45387 $handle = null;
45388
45389 $params = stream_context_get_params($context);
45390
45391 if (!empty($params['options']['ssl']['peer_certificate'])) {
45392 $peerCertificate = $params['options']['ssl']['peer_certificate'];
45393
45394 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
45395 return array(
45396 'cn' => $commonName,
45397 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
45398 );
45399 }
45400 }
45401 }
45402
45403 private function getUrlAuthority($url)
45404 {
45405 $defaultPorts = array(
45406 'ftp' => 21,
45407 'http' => 80,
45408 'https' => 443,
45409 'ssh2.sftp' => 22,
45410 'ssh2.scp' => 22,
45411 );
45412
45413 $scheme = parse_url($url, PHP_URL_SCHEME);
45414
45415 if (!isset($defaultPorts[$scheme])) {
45416 throw new \InvalidArgumentException(sprintf(
45417 'Could not get default port for unknown scheme: %s',
45418 $scheme
45419 ));
45420 }
45421
45422 $defaultPort = $defaultPorts[$scheme];
45423 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
45424
45425 return parse_url($url, PHP_URL_HOST).':'.$port;
45426 }
45427
45428
45429
45430
45431
45432
45433
45434
45435 private function isPublicBitBucketDownload($urlToBitBucketFile)
45436 {
45437 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
45438 if (strpos($domain, 'bitbucket.org') === false) {
45439
45440  
45441  return true;
45442 }
45443
45444 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
45445
45446
45447  
45448  $pathParts = explode('/', $path);
45449
45450 return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
45451 }
45452
45453 public static function outputWarnings(IOInterface $io, $url, $data)
45454 {
45455 foreach (array('warning', 'info') as $type) {
45456 if (empty($data[$type])) {
45457 continue;
45458 }
45459
45460 if (!empty($data[$type . '-versions'])) {
45461 $versionParser = new VersionParser();
45462 $constraint = $versionParser->parseConstraints($data[$type . '-versions']);
45463 $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion()));
45464 if (!$constraint->matches($composer)) {
45465 continue;
45466 }
45467 }
45468
45469 $io->writeError('<'.$type.'>'.ucfirst($type).' from '.$url.': '.$data[$type].'</'.$type.'>');
45470 }
45471 }
45472
45473 public static function getOrigin($urlOrPath)
45474 {
45475 $hostPort = parse_url($urlOrPath, PHP_URL_HOST);
45476 if (!$hostPort) {
45477 return $urlOrPath;
45478 }
45479 if (parse_url($urlOrPath, PHP_URL_PORT)) {
45480 $hostPort .= ':'.parse_url($urlOrPath, PHP_URL_PORT);
45481 }
45482
45483 return $hostPort;
45484 }
45485
45486 private function stripCredentialsFromUrl($url)
45487 {
45488
45489  
45490  return preg_replace('{([&?]access_token=)[^&]+}', '$1***', $url);
45491 }
45492 }
45493 <?php
45494
45495
45496
45497
45498
45499
45500
45501
45502
45503
45504
45505 namespace Composer\Util;
45506
45507
45508
45509
45510
45511
45512 class Silencer
45513 {
45514
45515
45516
45517 private static $stack = array();
45518
45519
45520
45521
45522
45523
45524
45525 public static function suppress($mask = null)
45526 {
45527 if (!isset($mask)) {
45528 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
45529 }
45530 $old = error_reporting();
45531 self::$stack[] = $old;
45532 error_reporting($old & ~$mask);
45533
45534 return $old;
45535 }
45536
45537
45538
45539
45540 public static function restore()
45541 {
45542 if (!empty(self::$stack)) {
45543 error_reporting(array_pop(self::$stack));
45544 }
45545 }
45546
45547
45548
45549
45550
45551
45552
45553
45554
45555
45556 public static function call($callable )
45557 {
45558 try {
45559 self::suppress();
45560 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
45561 self::restore();
45562
45563 return $result;
45564 } catch (\Exception $e) {
45565
45566  self::restore();
45567 throw $e;
45568 }
45569 }
45570 }
45571 <?php
45572
45573
45574
45575
45576
45577
45578
45579
45580
45581
45582
45583 namespace Composer\Util;
45584
45585 use Composer\Spdx\SpdxLicenses;
45586
45587 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
45588
45589
45590
45591
45592 class SpdxLicense extends SpdxLicenses
45593 {
45594 }
45595 <?php
45596
45597
45598
45599
45600
45601
45602
45603
45604
45605
45606
45607 namespace Composer\Util;
45608
45609 use Composer\Composer;
45610
45611
45612
45613
45614
45615
45616
45617 final class StreamContextFactory
45618 {
45619
45620
45621
45622
45623
45624
45625
45626
45627
45628 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
45629 {
45630 $options = array('http' => array(
45631
45632  'follow_location' => 1,
45633 'max_redirects' => 20,
45634 ));
45635
45636
45637  if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
45638 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
45639 }
45640
45641
45642  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
45643 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
45644 }
45645
45646
45647  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
45648 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
45649 }
45650
45651
45652  if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
45653 $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
45654 if ($pattern->test($url)) {
45655 unset($proxy);
45656 }
45657 }
45658
45659 if (!empty($proxy)) {
45660 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
45661 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
45662
45663 if (isset($proxy['port'])) {
45664 $proxyURL .= ":" . $proxy['port'];
45665 } elseif ('http://' == substr($proxyURL, 0, 7)) {
45666 $proxyURL .= ":80";
45667 } elseif ('https://' == substr($proxyURL, 0, 8)) {
45668 $proxyURL .= ":443";
45669 }
45670
45671
45672  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
45673
45674 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
45675 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
45676 }
45677
45678 $options['http']['proxy'] = $proxyURL;
45679
45680
45681  switch (parse_url($url, PHP_URL_SCHEME)) {
45682 case 'http': 
45683  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
45684 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
45685 $options['http']['request_fulluri'] = true;
45686 }
45687 break;
45688 case 'https': 
45689  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
45690 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
45691 $options['http']['request_fulluri'] = true;
45692 }
45693 break;
45694 }
45695
45696
45697  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
45698 $options['ssl']['SNI_enabled'] = true;
45699 if (PHP_VERSION_ID < 50600) {
45700 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
45701 }
45702 }
45703
45704
45705  if (isset($proxy['user'])) {
45706 $auth = rawurldecode($proxy['user']);
45707 if (isset($proxy['pass'])) {
45708 $auth .= ':' . rawurldecode($proxy['pass']);
45709 }
45710 $auth = base64_encode($auth);
45711
45712
45713  if (isset($defaultOptions['http']['header'])) {
45714 if (is_string($defaultOptions['http']['header'])) {
45715 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
45716 }
45717 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
45718 } else {
45719 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
45720 }
45721 }
45722 }
45723
45724 $options = array_replace_recursive($options, $defaultOptions);
45725
45726 if (isset($options['http']['header'])) {
45727 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
45728 }
45729
45730 if (defined('HHVM_VERSION')) {
45731 $phpVersion = 'HHVM ' . HHVM_VERSION;
45732 } else {
45733 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
45734 }
45735
45736 if (!isset($options['http']['header']) || false === stripos(implode('', $options['http']['header']), 'user-agent')) {
45737 $options['http']['header'][] = sprintf(
45738 'User-Agent: Composer/%s (%s; %s; %s%s)',
45739 Composer::getVersion(),
45740 function_exists('php_uname') ? php_uname('s') : 'Unknown',
45741 function_exists('php_uname') ? php_uname('r') : 'Unknown',
45742 $phpVersion,
45743 getenv('CI') ? '; CI' : ''
45744 );
45745 }
45746
45747 return stream_context_create($options, $defaultParams);
45748 }
45749
45750
45751
45752
45753
45754
45755
45756
45757
45758
45759
45760 private static function fixHttpHeaderField($header)
45761 {
45762 if (!is_array($header)) {
45763 $header = explode("\r\n", $header);
45764 }
45765 uasort($header, function ($el) {
45766 return stripos($el, 'content-type') === 0 ? 1 : -1;
45767 });
45768
45769 return $header;
45770 }
45771 }
45772 <?php
45773
45774
45775
45776
45777
45778
45779
45780
45781
45782
45783
45784 namespace Composer\Util;
45785
45786 use Composer\Config;
45787 use Composer\IO\IOInterface;
45788
45789
45790
45791
45792
45793 class Svn
45794 {
45795 const MAX_QTY_AUTH_TRIES = 5;
45796
45797
45798
45799
45800 protected $credentials;
45801
45802
45803
45804
45805 protected $hasAuth;
45806
45807
45808
45809
45810 protected $io;
45811
45812
45813
45814
45815 protected $url;
45816
45817
45818
45819
45820 protected $cacheCredentials = true;
45821
45822
45823
45824
45825 protected $process;
45826
45827
45828
45829
45830 protected $qtyAuthTries = 0;
45831
45832
45833
45834
45835 protected $config;
45836
45837
45838
45839
45840 private static $version;
45841
45842
45843
45844
45845
45846
45847
45848 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
45849 {
45850 $this->url = $url;
45851 $this->io = $io;
45852 $this->config = $config;
45853 $this->process = $process ?: new ProcessExecutor($io);
45854 }
45855
45856 public static function cleanEnv()
45857 {
45858
45859  putenv("DYLD_LIBRARY_PATH");
45860 unset($_SERVER['DYLD_LIBRARY_PATH']);
45861 }
45862
45863
45864
45865
45866
45867
45868
45869
45870
45871
45872
45873
45874
45875
45876 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
45877 {
45878
45879  $this->config->prohibitUrlByConfig($url, $this->io);
45880
45881 return $this->executeWithAuthRetry($command, $cwd, $url, $path, $verbose);
45882 }
45883
45884
45885
45886
45887
45888
45889
45890
45891
45892
45893
45894
45895
45896 public function executeLocal($command, $path, $cwd = null, $verbose = false)
45897 {
45898
45899  return $this->executeWithAuthRetry($command, $cwd, '', $path, $verbose);
45900 }
45901
45902 private function executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose)
45903 {
45904
45905  $command = $this->getCommand($svnCommand, $url, $path);
45906
45907 $output = null;
45908 $io = $this->io;
45909 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
45910 if ($type !== 'out') {
45911 return;
45912 }
45913 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
45914 return;
45915 }
45916 $output .= $buffer;
45917 if ($verbose) {
45918 $io->writeError($buffer, false);
45919 }
45920 };
45921 $status = $this->process->execute($command, $handler, $cwd);
45922 if (0 === $status) {
45923 return $output;
45924 }
45925
45926 $errorOutput = $this->process->getErrorOutput();
45927 $fullOutput = implode("\n", array($output, $errorOutput));
45928
45929
45930  if (false === stripos($fullOutput, 'Could not authenticate to server:')
45931 && false === stripos($fullOutput, 'authorization failed')
45932 && false === stripos($fullOutput, 'svn: E170001:')
45933 && false === stripos($fullOutput, 'svn: E215004:')) {
45934 throw new \RuntimeException($fullOutput);
45935 }
45936
45937 if (!$this->hasAuth()) {
45938 $this->doAuthDance();
45939 }
45940
45941
45942  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
45943
45944  return $this->executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose);
45945 }
45946
45947 throw new \RuntimeException(
45948 'wrong credentials provided ('.$fullOutput.')'
45949 );
45950 }
45951
45952
45953
45954
45955 public function setCacheCredentials($cacheCredentials)
45956 {
45957 $this->cacheCredentials = $cacheCredentials;
45958 }
45959
45960
45961
45962
45963
45964
45965
45966 protected function doAuthDance()
45967 {
45968
45969  if (!$this->io->isInteractive()) {
45970 throw new \RuntimeException(
45971 'can not ask for authentication in non interactive mode'
45972 );
45973 }
45974
45975 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
45976
45977 $this->hasAuth = true;
45978 $this->credentials['username'] = $this->io->ask("Username: ");
45979 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
45980
45981 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
45982
45983 return $this;
45984 }
45985
45986
45987
45988
45989
45990
45991
45992
45993
45994
45995 protected function getCommand($cmd, $url, $path = null)
45996 {
45997 $cmd = sprintf(
45998 '%s %s%s %s',
45999 $cmd,
46000 '--non-interactive ',
46001 $this->getCredentialString(),
46002 ProcessExecutor::escape($url)
46003 );
46004
46005 if ($path) {
46006 $cmd .= ' ' . ProcessExecutor::escape($path);
46007 }
46008
46009 return $cmd;
46010 }
46011
46012
46013
46014
46015
46016
46017
46018
46019 protected function getCredentialString()
46020 {
46021 if (!$this->hasAuth()) {
46022 return '';
46023 }
46024
46025 return sprintf(
46026 ' %s--username %s --password %s ',
46027 $this->getAuthCache(),
46028 ProcessExecutor::escape($this->getUsername()),
46029 ProcessExecutor::escape($this->getPassword())
46030 );
46031 }
46032
46033
46034
46035
46036
46037
46038
46039 protected function getPassword()
46040 {
46041 if ($this->credentials === null) {
46042 throw new \LogicException("No svn auth detected.");
46043 }
46044
46045 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
46046 }
46047
46048
46049
46050
46051
46052
46053
46054 protected function getUsername()
46055 {
46056 if ($this->credentials === null) {
46057 throw new \LogicException("No svn auth detected.");
46058 }
46059
46060 return $this->credentials['username'];
46061 }
46062
46063
46064
46065
46066
46067
46068 protected function hasAuth()
46069 {
46070 if (null !== $this->hasAuth) {
46071 return $this->hasAuth;
46072 }
46073
46074 if (false === $this->createAuthFromConfig()) {
46075 $this->createAuthFromUrl();
46076 }
46077
46078 return $this->hasAuth;
46079 }
46080
46081
46082
46083
46084
46085
46086 protected function getAuthCache()
46087 {
46088 return $this->cacheCredentials ? '' : '--no-auth-cache ';
46089 }
46090
46091
46092
46093
46094
46095
46096 private function createAuthFromConfig()
46097 {
46098 if (!$this->config->has('http-basic')) {
46099 return $this->hasAuth = false;
46100 }
46101
46102 $authConfig = $this->config->get('http-basic');
46103
46104 $host = parse_url($this->url, PHP_URL_HOST);
46105 if (isset($authConfig[$host])) {
46106 $this->credentials['username'] = $authConfig[$host]['username'];
46107 $this->credentials['password'] = $authConfig[$host]['password'];
46108
46109 return $this->hasAuth = true;
46110 }
46111
46112 return $this->hasAuth = false;
46113 }
46114
46115
46116
46117
46118
46119
46120 private function createAuthFromUrl()
46121 {
46122 $uri = parse_url($this->url);
46123 if (empty($uri['user'])) {
46124 return $this->hasAuth = false;
46125 }
46126
46127 $this->credentials['username'] = $uri['user'];
46128 if (!empty($uri['pass'])) {
46129 $this->credentials['password'] = $uri['pass'];
46130 }
46131
46132 return $this->hasAuth = true;
46133 }
46134
46135
46136
46137
46138
46139
46140 public function binaryVersion()
46141 {
46142 if (!self::$version) {
46143 if (0 === $this->process->execute('svn --version', $output)) {
46144 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match)) {
46145 self::$version = $match[1];
46146 }
46147 }
46148 }
46149
46150 return self::$version;
46151 }
46152 }
46153 <?php
46154
46155
46156
46157
46158
46159
46160
46161
46162
46163
46164
46165 namespace Composer\Util;
46166
46167 use Composer\CaBundle\CaBundle;
46168
46169
46170
46171
46172 final class TlsHelper
46173 {
46174
46175
46176
46177
46178
46179
46180
46181
46182
46183 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
46184 {
46185 $names = self::getCertificateNames($certificate);
46186
46187 if (empty($names)) {
46188 return false;
46189 }
46190
46191 $combinedNames = array_merge($names['san'], array($names['cn']));
46192 $hostname = strtolower($hostname);
46193
46194 foreach ($combinedNames as $certName) {
46195 $matcher = self::certNameMatcher($certName);
46196
46197 if ($matcher && $matcher($hostname)) {
46198 $cn = $names['cn'];
46199
46200 return true;
46201 }
46202 }
46203
46204 return false;
46205 }
46206
46207
46208
46209
46210
46211
46212
46213
46214 public static function getCertificateNames($certificate)
46215 {
46216 if (is_array($certificate)) {
46217 $info = $certificate;
46218 } elseif (CaBundle::isOpensslParseSafe()) {
46219 $info = openssl_x509_parse($certificate, false);
46220 }
46221
46222 if (!isset($info['subject']['commonName'])) {
46223 return null;
46224 }
46225
46226 $commonName = strtolower($info['subject']['commonName']);
46227 $subjectAltNames = array();
46228
46229 if (isset($info['extensions']['subjectAltName'])) {
46230 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
46231 $subjectAltNames = array_filter(array_map(function ($name) {
46232 if (0 === strpos($name, 'DNS:')) {
46233 return strtolower(ltrim(substr($name, 4)));
46234 }
46235
46236 return null;
46237 }, $subjectAltNames));
46238 $subjectAltNames = array_values($subjectAltNames);
46239 }
46240
46241 return array(
46242 'cn' => $commonName,
46243 'san' => $subjectAltNames,
46244 );
46245 }
46246
46247
46248
46249
46250
46251
46252
46253
46254
46255
46256
46257
46258
46259
46260
46261
46262
46263
46264
46265
46266
46267
46268
46269
46270
46271
46272
46273
46274
46275
46276
46277
46278
46279
46280
46281
46282
46283
46284
46285
46286 public static function getCertificateFingerprint($certificate)
46287 {
46288 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
46289 $pubkeypem = $pubkeydetails['key'];
46290
46291  $start = '-----BEGIN PUBLIC KEY-----';
46292 $end = '-----END PUBLIC KEY-----';
46293 $pemtrim = substr($pubkeypem, strpos($pubkeypem, $start) + strlen($start), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
46294 $der = base64_decode($pemtrim);
46295
46296 return sha1($der);
46297 }
46298
46299
46300
46301
46302
46303
46304
46305
46306
46307 public static function isOpensslParseSafe()
46308 {
46309 return CaBundle::isOpensslParseSafe();
46310 }
46311
46312
46313
46314
46315
46316
46317
46318
46319 private static function certNameMatcher($certName)
46320 {
46321 $wildcards = substr_count($certName, '*');
46322
46323 if (0 === $wildcards) {
46324
46325  return function ($hostname) use ($certName) {
46326 return $hostname === $certName;
46327 };
46328 }
46329
46330 if (1 === $wildcards) {
46331 $components = explode('.', $certName);
46332
46333 if (3 > count($components)) {
46334
46335  return;
46336 }
46337
46338 $firstComponent = $components[0];
46339
46340
46341  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
46342 return;
46343 }
46344
46345 $wildcardRegex = preg_quote($certName);
46346 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
46347 $wildcardRegex = "{^{$wildcardRegex}$}";
46348
46349 return function ($hostname) use ($wildcardRegex) {
46350 return 1 === preg_match($wildcardRegex, $hostname);
46351 };
46352 }
46353 }
46354 }
46355 <?php
46356
46357
46358
46359
46360
46361
46362
46363
46364
46365
46366
46367 namespace Composer\Util;
46368
46369 use Composer\Config;
46370
46371
46372
46373
46374 class Url
46375 {
46376 public static function updateDistReference(Config $config, $url, $ref)
46377 {
46378 $host = parse_url($url, PHP_URL_HOST);
46379
46380 if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
46381 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
46382
46383  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
46384 } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
46385
46386  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
46387 } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
46388
46389  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
46390 }
46391 } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
46392 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
46393
46394  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4];
46395 }
46396 } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
46397 if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
46398
46399  $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
46400 }
46401 } elseif (in_array($host, $config->get('github-domains'), true)) {
46402 $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url);
46403 } elseif (in_array($host, $config->get('gitlab-domains'), true)) {
46404 $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url);
46405 }
46406
46407 return $url;
46408 }
46409 }
46410 <?php
46411
46412
46413
46414
46415
46416
46417
46418
46419
46420
46421
46422 namespace Composer\Util;
46423
46424
46425
46426
46427 class Zip
46428 {
46429
46430
46431
46432
46433
46434
46435
46436
46437 public static function getComposerJson($pathToZip)
46438 {
46439 if (!extension_loaded('zip')) {
46440 throw new \RuntimeException('The Zip Util requires PHP\'s zip extension');
46441 }
46442
46443 $zip = new \ZipArchive();
46444 if ($zip->open($pathToZip) !== true) {
46445 return null;
46446 }
46447
46448 if (0 == $zip->numFiles) {
46449 $zip->close();
46450
46451 return null;
46452 }
46453
46454 $foundFileIndex = self::locateFile($zip, 'composer.json');
46455 if (false === $foundFileIndex) {
46456 $zip->close();
46457
46458 return null;
46459 }
46460
46461 $content = null;
46462 $configurationFileName = $zip->getNameIndex($foundFileIndex);
46463 $stream = $zip->getStream($configurationFileName);
46464
46465 if (false !== $stream) {
46466 $content = stream_get_contents($stream);
46467 }
46468
46469 $zip->close();
46470
46471 return $content;
46472 }
46473
46474
46475
46476
46477
46478
46479
46480
46481
46482 private static function locateFile(\ZipArchive $zip, $filename)
46483 {
46484 $indexOfShortestMatch = false;
46485 $lengthOfShortestMatch = -1;
46486
46487 for ($i = 0; $i < $zip->numFiles; $i++) {
46488 $stat = $zip->statIndex($i);
46489 if (strcmp(basename($stat['name']), $filename) === 0) {
46490 $directoryName = dirname($stat['name']);
46491 if ($directoryName === '.') {
46492
46493  
46494  return $i;
46495 }
46496
46497 if (strpos($directoryName, '\\') !== false ||
46498 strpos($directoryName, '/') !== false) {
46499
46500  continue;
46501 }
46502
46503 $length = strlen($stat['name']);
46504 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
46505
46506  $contents = $zip->getFromIndex($i);
46507 if ($contents !== false) {
46508 $indexOfShortestMatch = $i;
46509 $lengthOfShortestMatch = $length;
46510 }
46511 }
46512 }
46513 }
46514
46515 return $indexOfShortestMatch;
46516 }
46517 }
46518 <?php
46519
46520
46521
46522
46523
46524
46525
46526
46527
46528
46529
46530 namespace Composer;
46531
46532 use Symfony\Component\Console\Output\OutputInterface;
46533
46534 trigger_error('The ' . __NAMESPACE__ . '\XdebugHandler class is deprecated, use Composer\XdebugHandler\XdebugHandler instead,', E_USER_DEPRECATED);
46535
46536
46537
46538
46539 class XdebugHandler extends XdebugHandler\XdebugHandler
46540 {
46541 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
46542 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
46543
46544 public function __construct(OutputInterface $output)
46545 {
46546 parent::__construct('composer', '--ansi');
46547 }
46548 }
46549 <?php
46550
46551
46552
46553
46554
46555
46556
46557
46558
46559
46560
46561 function includeIfExists($file)
46562 {
46563 return file_exists($file) ? include $file : false;
46564 }
46565
46566 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
46567 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
46568 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
46569 exit(1);
46570 }
46571
46572 return $loader;
46573 <?php
46574
46575 /*
46576  * This file is part of Composer.
46577  *
46578  * (c) Nils Adermann <naderman@naderman.de>
46579  *     Jordi Boggiano <j.boggiano@seld.be>
46580  *
46581  * For the full copyright and license information, please view the LICENSE
46582  * file that was distributed with this source code.
46583  */
46584
46585 namespace Composer\Autoload;
46586
46587 /**
46588  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
46589  *
46590  *     $loader = new \Composer\Autoload\ClassLoader();
46591  *
46592  *     // register classes with namespaces
46593  *     $loader->add('Symfony\Component', __DIR__.'/component');
46594  *     $loader->add('Symfony',           __DIR__.'/framework');
46595  *
46596  *     // activate the autoloader
46597  *     $loader->register();
46598  *
46599  *     // to enable searching the include path (eg. for PEAR packages)
46600  *     $loader->setUseIncludePath(true);
46601  *
46602  * In this example, if you try to use a class in the Symfony\Component
46603  * namespace or one of its children (Symfony\Component\Console for instance),
46604  * the autoloader will first look for the class under the component/
46605  * directory, and it will then fallback to the framework/ directory if not
46606  * found before giving up.
46607  *
46608  * This class is loosely based on the Symfony UniversalClassLoader.
46609  *
46610  * @author Fabien Potencier <fabien@symfony.com>
46611  * @author Jordi Boggiano <j.boggiano@seld.be>
46612  * @see    http://www.php-fig.org/psr/psr-0/
46613  * @see    http://www.php-fig.org/psr/psr-4/
46614  */
46615 class ClassLoader
46616 {
46617     // PSR-4
46618     private $prefixLengthsPsr4 = array();
46619     private $prefixDirsPsr4 = array();
46620     private $fallbackDirsPsr4 = array();
46621
46622     // PSR-0
46623     private $prefixesPsr0 = array();
46624     private $fallbackDirsPsr0 = array();
46625
46626     private $useIncludePath = false;
46627     private $classMap = array();
46628     private $classMapAuthoritative = false;
46629     private $missingClasses = array();
46630     private $apcuPrefix;
46631
46632     public function getPrefixes()
46633     {
46634         if (!empty($this->prefixesPsr0)) {
46635             return call_user_func_array('array_merge', $this->prefixesPsr0);
46636         }
46637
46638         return array();
46639     }
46640
46641     public function getPrefixesPsr4()
46642     {
46643         return $this->prefixDirsPsr4;
46644     }
46645
46646     public function getFallbackDirs()
46647     {
46648         return $this->fallbackDirsPsr0;
46649     }
46650
46651     public function getFallbackDirsPsr4()
46652     {
46653         return $this->fallbackDirsPsr4;
46654     }
46655
46656     public function getClassMap()
46657     {
46658         return $this->classMap;
46659     }
46660
46661     /**
46662      * @param array $classMap Class to filename map
46663      */
46664     public function addClassMap(array $classMap)
46665     {
46666         if ($this->classMap) {
46667             $this->classMap = array_merge($this->classMap, $classMap);
46668         } else {
46669             $this->classMap = $classMap;
46670         }
46671     }
46672
46673     /**
46674      * Registers a set of PSR-0 directories for a given prefix, either
46675      * appending or prepending to the ones previously set for this prefix.
46676      *
46677      * @param string       $prefix  The prefix
46678      * @param array|string $paths   The PSR-0 root directories
46679      * @param bool         $prepend Whether to prepend the directories
46680      */
46681     public function add($prefix, $paths, $prepend = false)
46682     {
46683         if (!$prefix) {
46684             if ($prepend) {
46685                 $this->fallbackDirsPsr0 = array_merge(
46686                     (array) $paths,
46687                     $this->fallbackDirsPsr0
46688                 );
46689             } else {
46690                 $this->fallbackDirsPsr0 = array_merge(
46691                     $this->fallbackDirsPsr0,
46692                     (array) $paths
46693                 );
46694             }
46695
46696             return;
46697         }
46698
46699         $first = $prefix[0];
46700         if (!isset($this->prefixesPsr0[$first][$prefix])) {
46701             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
46702
46703             return;
46704         }
46705         if ($prepend) {
46706             $this->prefixesPsr0[$first][$prefix] = array_merge(
46707                 (array) $paths,
46708                 $this->prefixesPsr0[$first][$prefix]
46709             );
46710         } else {
46711             $this->prefixesPsr0[$first][$prefix] = array_merge(
46712                 $this->prefixesPsr0[$first][$prefix],
46713                 (array) $paths
46714             );
46715         }
46716     }
46717
46718     /**
46719      * Registers a set of PSR-4 directories for a given namespace, either
46720      * appending or prepending to the ones previously set for this namespace.
46721      *
46722      * @param string       $prefix  The prefix/namespace, with trailing '\\'
46723      * @param array|string $paths   The PSR-4 base directories
46724      * @param bool         $prepend Whether to prepend the directories
46725      *
46726      * @throws \InvalidArgumentException
46727      */
46728     public function addPsr4($prefix, $paths, $prepend = false)
46729     {
46730         if (!$prefix) {
46731             // Register directories for the root namespace.
46732             if ($prepend) {
46733                 $this->fallbackDirsPsr4 = array_merge(
46734                     (array) $paths,
46735                     $this->fallbackDirsPsr4
46736                 );
46737             } else {
46738                 $this->fallbackDirsPsr4 = array_merge(
46739                     $this->fallbackDirsPsr4,
46740                     (array) $paths
46741                 );
46742             }
46743         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
46744             // Register directories for a new namespace.
46745             $length = strlen($prefix);
46746             if ('\\' !== $prefix[$length - 1]) {
46747                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
46748             }
46749             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
46750             $this->prefixDirsPsr4[$prefix] = (array) $paths;
46751         } elseif ($prepend) {
46752             // Prepend directories for an already registered namespace.
46753             $this->prefixDirsPsr4[$prefix] = array_merge(
46754                 (array) $paths,
46755                 $this->prefixDirsPsr4[$prefix]
46756             );
46757         } else {
46758             // Append directories for an already registered namespace.
46759             $this->prefixDirsPsr4[$prefix] = array_merge(
46760                 $this->prefixDirsPsr4[$prefix],
46761                 (array) $paths
46762             );
46763         }
46764     }
46765
46766     /**
46767      * Registers a set of PSR-0 directories for a given prefix,
46768      * replacing any others previously set for this prefix.
46769      *
46770      * @param string       $prefix The prefix
46771      * @param array|string $paths  The PSR-0 base directories
46772      */
46773     public function set($prefix, $paths)
46774     {
46775         if (!$prefix) {
46776             $this->fallbackDirsPsr0 = (array) $paths;
46777         } else {
46778             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
46779         }
46780     }
46781
46782     /**
46783      * Registers a set of PSR-4 directories for a given namespace,
46784      * replacing any others previously set for this namespace.
46785      *
46786      * @param string       $prefix The prefix/namespace, with trailing '\\'
46787      * @param array|string $paths  The PSR-4 base directories
46788      *
46789      * @throws \InvalidArgumentException
46790      */
46791     public function setPsr4($prefix, $paths)
46792     {
46793         if (!$prefix) {
46794             $this->fallbackDirsPsr4 = (array) $paths;
46795         } else {
46796             $length = strlen($prefix);
46797             if ('\\' !== $prefix[$length - 1]) {
46798                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
46799             }
46800             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
46801             $this->prefixDirsPsr4[$prefix] = (array) $paths;
46802         }
46803     }
46804
46805     /**
46806      * Turns on searching the include path for class files.
46807      *
46808      * @param bool $useIncludePath
46809      */
46810     public function setUseIncludePath($useIncludePath)
46811     {
46812         $this->useIncludePath = $useIncludePath;
46813     }
46814
46815     /**
46816      * Can be used to check if the autoloader uses the include path to check
46817      * for classes.
46818      *
46819      * @return bool
46820      */
46821     public function getUseIncludePath()
46822     {
46823         return $this->useIncludePath;
46824     }
46825
46826     /**
46827      * Turns off searching the prefix and fallback directories for classes
46828      * that have not been registered with the class map.
46829      *
46830      * @param bool $classMapAuthoritative
46831      */
46832     public function setClassMapAuthoritative($classMapAuthoritative)
46833     {
46834         $this->classMapAuthoritative = $classMapAuthoritative;
46835     }
46836
46837     /**
46838      * Should class lookup fail if not found in the current class map?
46839      *
46840      * @return bool
46841      */
46842     public function isClassMapAuthoritative()
46843     {
46844         return $this->classMapAuthoritative;
46845     }
46846
46847     /**
46848      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
46849      *
46850      * @param string|null $apcuPrefix
46851      */
46852     public function setApcuPrefix($apcuPrefix)
46853     {
46854         $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
46855     }
46856
46857     /**
46858      * The APCu prefix in use, or null if APCu caching is not enabled.
46859      *
46860      * @return string|null
46861      */
46862     public function getApcuPrefix()
46863     {
46864         return $this->apcuPrefix;
46865     }
46866
46867     /**
46868      * Registers this instance as an autoloader.
46869      *
46870      * @param bool $prepend Whether to prepend the autoloader or not
46871      */
46872     public function register($prepend = false)
46873     {
46874         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
46875     }
46876
46877     /**
46878      * Unregisters this instance as an autoloader.
46879      */
46880     public function unregister()
46881     {
46882         spl_autoload_unregister(array($this, 'loadClass'));
46883     }
46884
46885     /**
46886      * Loads the given class or interface.
46887      *
46888      * @param  string    $class The name of the class
46889      * @return bool|null True if loaded, null otherwise
46890      */
46891     public function loadClass($class)
46892     {
46893         if ($file = $this->findFile($class)) {
46894             includeFile($file);
46895
46896             return true;
46897         }
46898     }
46899
46900     /**
46901      * Finds the path to the file where the class is defined.
46902      *
46903      * @param string $class The name of the class
46904      *
46905      * @return string|false The path if found, false otherwise
46906      */
46907     public function findFile($class)
46908     {
46909         // class map lookup
46910         if (isset($this->classMap[$class])) {
46911             return $this->classMap[$class];
46912         }
46913         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
46914             return false;
46915         }
46916         if (null !== $this->apcuPrefix) {
46917             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
46918             if ($hit) {
46919                 return $file;
46920             }
46921         }
46922
46923         $file = $this->findFileWithExtension($class, '.php');
46924
46925         // Search for Hack files if we are running on HHVM
46926         if (false === $file && defined('HHVM_VERSION')) {
46927             $file = $this->findFileWithExtension($class, '.hh');
46928         }
46929
46930         if (null !== $this->apcuPrefix) {
46931             apcu_add($this->apcuPrefix.$class, $file);
46932         }
46933
46934         if (false === $file) {
46935             // Remember that this class does not exist.
46936             $this->missingClasses[$class] = true;
46937         }
46938
46939         return $file;
46940     }
46941
46942     private function findFileWithExtension($class, $ext)
46943     {
46944         // PSR-4 lookup
46945         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
46946
46947         $first = $class[0];
46948         if (isset($this->prefixLengthsPsr4[$first])) {
46949             $subPath = $class;
46950             while (false !== $lastPos = strrpos($subPath, '\\')) {
46951                 $subPath = substr($subPath, 0, $lastPos);
46952                 $search = $subPath . '\\';
46953                 if (isset($this->prefixDirsPsr4[$search])) {
46954                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
46955                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
46956                         if (file_exists($file = $dir . $pathEnd)) {
46957                             return $file;
46958                         }
46959                     }
46960                 }
46961             }
46962         }
46963
46964         // PSR-4 fallback dirs
46965         foreach ($this->fallbackDirsPsr4 as $dir) {
46966             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
46967                 return $file;
46968             }
46969         }
46970
46971         // PSR-0 lookup
46972         if (false !== $pos = strrpos($class, '\\')) {
46973             // namespaced class name
46974             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
46975                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
46976         } else {
46977             // PEAR-like class name
46978             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
46979         }
46980
46981         if (isset($this->prefixesPsr0[$first])) {
46982             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
46983                 if (0 === strpos($class, $prefix)) {
46984                     foreach ($dirs as $dir) {
46985                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
46986                             return $file;
46987                         }
46988                     }
46989                 }
46990             }
46991         }
46992
46993         // PSR-0 fallback dirs
46994         foreach ($this->fallbackDirsPsr0 as $dir) {
46995             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
46996                 return $file;
46997             }
46998         }
46999
47000         // PSR-0 include paths.
47001         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
47002             return $file;
47003         }
47004
47005         return false;
47006     }
47007 }
47008
47009 /**
47010  * Scope isolated include.
47011  *
47012  * Prevents access to $this/self from included files.
47013  */
47014 function includeFile($file)
47015 {
47016     include $file;
47017 }
47018 {
47019     "$schema": "http://json-schema.org/draft-04/schema#",
47020     "description": "A representation of packages metadata.",
47021     "type": "object",
47022     "oneOf": [
47023         { "required": [ "packages" ] },
47024         { "required": [ "providers" ] },
47025         { "required": [ "provider-includes", "providers-url" ] }
47026     ],
47027     "properties": {
47028         "packages": {
47029             "type": ["object", "array"],
47030             "description": "A hashmap of package names in the form of <vendor>/<name>.",
47031             "additionalProperties": { "$ref": "#/definitions/versions" }
47032         },
47033         "providers-url": {
47034             "type": "string",
47035             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
47036         },
47037         "provider-includes": {
47038             "type": "object",
47039             "description": "A hashmap of provider listings.",
47040             "additionalProperties": { "$ref": "#/definitions/provider" }
47041         },
47042         "providers": {
47043             "type": "object",
47044             "description": "A hashmap of package names in the form of <vendor>/<name>.",
47045             "additionalProperties": { "$ref": "#/definitions/provider" }
47046         },
47047         "notify-batch": {
47048             "type": "string",
47049             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
47050         },
47051         "search": {
47052             "type": "string",
47053             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
47054         },
47055         "warning": {
47056             "type": "string",
47057             "description": "A message that will be output by Composer as a warning when this source is consulted."
47058         }
47059     },
47060     "definitions": {
47061         "versions": {
47062             "type": "object",
47063             "description": "A hashmap of versions and their metadata.",
47064             "additionalProperties": { "$ref": "#/definitions/version" }
47065         },
47066         "version": {
47067             "type": "object",
47068             "oneOf": [
47069                 { "$ref": "#/definitions/package" },
47070                 { "$ref": "#/definitions/metapackage" }
47071             ]
47072         },
47073         "package-base": {
47074             "properties": {
47075                 "name": { "type": "string" },
47076                 "type": { "type": "string" },
47077                 "version": { "type": "string" },
47078                 "version_normalized": {
47079                     "type": "string",
47080                     "description": "Normalized version, optional but can save computational time on client side."
47081                 },
47082                 "autoload": { "type": "object" },
47083                 "require": { "type": "object" },
47084                 "replace": { "type": "object" },
47085                 "conflict": { "type": "object" },
47086                 "provide": { "type": "object" },
47087                 "time": { "type": "string" }
47088             },
47089             "additionalProperties": true
47090         },
47091         "package": {
47092             "allOf": [
47093                 { "$ref": "#/definitions/package-base" },
47094                 {
47095                     "properties": {
47096                         "dist": { "type": "object" },
47097                         "source": { "type": "object" }
47098                     }
47099                 },
47100                 { "oneOf": [
47101                     { "required": [ "name", "version", "source" ] },
47102                     { "required": [ "name", "version", "dist" ] }
47103                 ] }
47104             ]
47105         },
47106         "metapackage": {
47107             "allOf": [
47108                 { "$ref": "#/definitions/package-base" },
47109                 {
47110                     "properties": {
47111                         "type": { "type": "string", "enum": [ "metapackage" ] }
47112                     },
47113                     "required": [ "name", "version", "type" ]
47114                 }
47115             ]
47116         },
47117         "provider": {
47118             "type": "object",
47119             "properties": {
47120                 "sha256": {
47121                     "type": "string",
47122                     "description": "Hash value that can be used to validate the resource."
47123                 }
47124             }
47125         }
47126     }
47127 }
47128 {
47129     "$schema": "http://json-schema.org/draft-04/schema#",
47130     "name": "Package",
47131     "type": "object",
47132     "additionalProperties": false,
47133     "required": [ "name", "description" ],
47134     "properties": {
47135         "name": {
47136             "type": "string",
47137             "description": "Package name, including 'vendor-name/' prefix."
47138         },
47139         "type": {
47140             "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.",
47141             "type": "string",
47142             "pattern": "^[a-z0-9-]+$"
47143         },
47144         "target-dir": {
47145             "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.",
47146             "type": "string"
47147         },
47148         "description": {
47149             "type": "string",
47150             "description": "Short package description."
47151         },
47152         "keywords": {
47153             "type": "array",
47154             "items": {
47155                 "type": "string",
47156                 "description": "A tag/keyword that this package relates to."
47157             }
47158         },
47159         "homepage": {
47160             "type": "string",
47161             "description": "Homepage URL for the project.",
47162             "format": "uri"
47163         },
47164         "readme": {
47165             "type": "string",
47166             "description": "Relative path to the readme document."
47167         },
47168         "version": {
47169             "type": "string",
47170             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
47171             "pattern": "^v?\\d+(((\\.\\d+)?\\.\\d+)?\\.\\d+)?|^dev-"
47172         },
47173         "time": {
47174             "type": "string",
47175             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
47176         },
47177         "license": {
47178             "type": ["string", "array"],
47179             "description": "License name. Or an array of license names."
47180         },
47181         "authors": {
47182             "$ref": "#/definitions/authors"
47183         },
47184         "require": {
47185             "type": "object",
47186             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
47187             "additionalProperties": {
47188                 "type": "string"
47189             }
47190         },
47191         "replace": {
47192             "type": "object",
47193             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
47194             "additionalProperties": {
47195                 "type": "string"
47196             }
47197         },
47198         "conflict": {
47199             "type": "object",
47200             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
47201             "additionalProperties": {
47202                 "type": "string"
47203             }
47204         },
47205         "provide": {
47206             "type": "object",
47207             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
47208             "additionalProperties": {
47209                 "type": "string"
47210             }
47211         },
47212         "require-dev": {
47213             "type": "object",
47214             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
47215             "additionalProperties": {
47216                 "type": "string"
47217             }
47218         },
47219         "suggest": {
47220             "type": "object",
47221             "description": "This is a hash of package name (keys) and descriptions (values) that this package suggests work well with it (this will be suggested to the user during installation).",
47222             "additionalProperties": {
47223                 "type": "string"
47224             }
47225         },
47226         "config": {
47227             "type": "object",
47228             "description": "Composer options.",
47229             "properties": {
47230                 "process-timeout": {
47231                     "type": "integer",
47232                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
47233                 },
47234                 "use-include-path": {
47235                     "type": "boolean",
47236                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
47237                 },
47238                 "preferred-install": {
47239                     "type": ["string", "object"],
47240                     "description": "The install method Composer will prefer to use, defaults to auto and can be any of source, dist, auto, or a hash of {\"pattern\": \"preference\"}."
47241                 },
47242                 "notify-on-install": {
47243                     "type": "boolean",
47244                     "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."
47245                 },
47246                 "github-protocols": {
47247                     "type": "array",
47248                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
47249                     "items": {
47250                         "type": "string"
47251                     }
47252                 },
47253                 "github-oauth": {
47254                     "type": "object",
47255                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
47256                     "additionalProperties": {
47257                         "type": "string"
47258                     }
47259                 },
47260                 "gitlab-oauth": {
47261                     "type": "object",
47262                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
47263                     "additionalProperties": {
47264                         "type": "string"
47265                     }
47266                 },
47267                 "gitlab-token": {
47268                     "type": "object",
47269                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
47270                     "additionalProperties": true
47271                 },
47272                 "disable-tls": {
47273                     "type": "boolean",
47274                     "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."
47275                 },
47276                 "secure-http": {
47277                     "type": "boolean",
47278                     "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."
47279                 },
47280                 "cafile": {
47281                     "type": "string",
47282                     "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."
47283                 },
47284                 "capath": {
47285                     "type": "string",
47286                     "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."
47287                 },
47288                 "http-basic": {
47289                     "type": "object",
47290                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
47291                     "additionalProperties": {
47292                         "type": "object",
47293                         "required": ["username", "password"],
47294                         "properties": {
47295                             "username": {
47296                                 "type": "string",
47297                                 "description": "The username used for HTTP Basic authentication"
47298                             },
47299                             "password": {
47300                                 "type": "string",
47301                                 "description": "The password used for HTTP Basic authentication"
47302                             }
47303                         }
47304                     }
47305                 },
47306                 "store-auths": {
47307                     "type": ["string", "boolean"],
47308                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
47309                 },
47310                 "platform": {
47311                     "type": "object",
47312                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
47313                     "additionalProperties": {
47314                         "type": "string"
47315                     }
47316                 },
47317                 "vendor-dir": {
47318                     "type": "string",
47319                     "description": "The location where all packages are installed, defaults to \"vendor\"."
47320                 },
47321                 "bin-dir": {
47322                     "type": "string",
47323                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
47324                 },
47325                 "data-dir": {
47326                     "type": "string",
47327                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
47328                 },
47329                 "cache-dir": {
47330                     "type": "string",
47331                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
47332                 },
47333                 "cache-files-dir": {
47334                     "type": "string",
47335                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
47336                 },
47337                 "cache-repo-dir": {
47338                     "type": "string",
47339                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
47340                 },
47341                 "cache-vcs-dir": {
47342                     "type": "string",
47343                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
47344                 },
47345                 "cache-ttl": {
47346                     "type": "integer",
47347                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
47348                 },
47349                 "cache-files-ttl": {
47350                     "type": "integer",
47351                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
47352                 },
47353                 "cache-files-maxsize": {
47354                     "type": ["string", "integer"],
47355                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
47356                 },
47357                 "bin-compat": {
47358                     "enum": ["auto", "full"],
47359                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
47360                 },
47361                 "discard-changes": {
47362                     "type": ["string", "boolean"],
47363                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
47364                 },
47365                 "autoloader-suffix": {
47366                     "type": "string",
47367                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
47368                 },
47369                 "optimize-autoloader": {
47370                     "type": "boolean",
47371                     "description": "Always optimize when dumping the autoloader."
47372                 },
47373                 "prepend-autoloader": {
47374                     "type": "boolean",
47375                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
47376                 },
47377                 "classmap-authoritative": {
47378                     "type": "boolean",
47379                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
47380                 },
47381                 "apcu-autoloader": {
47382                     "type": "boolean",
47383                     "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."
47384                 },
47385                 "github-domains": {
47386                     "type": "array",
47387                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
47388                     "items": {
47389                         "type": "string"
47390                     }
47391                 },
47392                 "github-expose-hostname": {
47393                     "type": "boolean",
47394                     "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."
47395                 },
47396                 "gitlab-domains": {
47397                     "type": "array",
47398                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
47399                     "items": {
47400                         "type": "string"
47401                     }
47402                 },
47403                 "use-github-api": {
47404                     "type": "boolean",
47405                     "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."
47406                 },
47407                 "archive-format": {
47408                     "type": "string",
47409                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
47410                 },
47411                 "archive-dir": {
47412                     "type": "string",
47413                     "description": "The default archive path when not provided on cli, defaults to \".\"."
47414                 },
47415                 "htaccess-protect": {
47416                     "type": "boolean",
47417                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
47418                 },
47419                 "sort-packages": {
47420                     "type": "boolean",
47421                     "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
47422                 }
47423             }
47424         },
47425         "extra": {
47426             "type": ["object", "array"],
47427             "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.",
47428             "additionalProperties": true
47429         },
47430         "autoload": {
47431             "$ref": "#/definitions/autoload"
47432         },
47433         "autoload-dev": {
47434             "type": "object",
47435             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
47436             "properties": {
47437                 "psr-0": {
47438                     "type": "object",
47439                     "description": "This is a hash of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.",
47440                     "additionalProperties": {
47441                         "type": ["string", "array"],
47442                         "items": {
47443                             "type": "string"
47444                         }
47445                     }
47446                 },
47447                 "psr-4": {
47448                     "type": "object",
47449                     "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.",
47450                     "additionalProperties": {
47451                         "type": ["string", "array"],
47452                         "items": {
47453                             "type": "string"
47454                         }
47455                     }
47456                 },
47457                 "classmap": {
47458                     "type": "array",
47459                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
47460                 },
47461                 "files": {
47462                     "type": "array",
47463                     "description": "This is an array of files that are always required on every request."
47464                 }
47465             }
47466         },
47467         "archive": {
47468             "type": ["object"],
47469             "description": "Options for creating package archives for distribution.",
47470             "properties": {
47471                 "exclude": {
47472                     "type": "array",
47473                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
47474                 }
47475             }
47476         },
47477         "repositories": {
47478             "type": ["object", "array"],
47479             "description": "A set of additional repositories where packages can be found.",
47480             "additionalProperties": {
47481                 "oneOf": [
47482                     { "$ref": "#/definitions/repository" },
47483                     { "type": "boolean", "enum": [false] }
47484                 ]
47485             },
47486             "items": {
47487                 "oneOf": [
47488                     { "$ref": "#/definitions/repository" },
47489                     {
47490                         "type": "object",
47491                         "additionalProperties": { "type": "boolean", "enum": [false] },
47492                         "minProperties": 1,
47493                         "maxProperties": 1
47494                     }
47495                 ]
47496             }
47497         },
47498         "minimum-stability": {
47499             "type": ["string"],
47500             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
47501             "pattern": "^dev|alpha|beta|rc|RC|stable$"
47502         },
47503         "prefer-stable": {
47504             "type": ["boolean"],
47505             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
47506         },
47507         "bin": {
47508             "type": ["string", "array"],
47509             "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
47510             "items": {
47511                 "type": "string"
47512             }
47513         },
47514         "include-path": {
47515             "type": ["array"],
47516             "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.",
47517             "items": {
47518                 "type": "string"
47519             }
47520         },
47521         "scripts": {
47522             "type": ["object"],
47523             "description": "Script listeners that will be executed before/after some events.",
47524             "properties": {
47525                 "pre-install-cmd": {
47526                     "type": ["array", "string"],
47527                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
47528                 },
47529                 "post-install-cmd": {
47530                     "type": ["array", "string"],
47531                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
47532                 },
47533                 "pre-update-cmd": {
47534                     "type": ["array", "string"],
47535                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
47536                 },
47537                 "post-update-cmd": {
47538                     "type": ["array", "string"],
47539                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
47540                 },
47541                 "pre-status-cmd": {
47542                     "type": ["array", "string"],
47543                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
47544                 },
47545                 "post-status-cmd": {
47546                     "type": ["array", "string"],
47547                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
47548                 },
47549                 "pre-package-install": {
47550                     "type": ["array", "string"],
47551                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
47552                 },
47553                 "post-package-install": {
47554                     "type": ["array", "string"],
47555                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
47556                 },
47557                 "pre-package-update": {
47558                     "type": ["array", "string"],
47559                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
47560                 },
47561                 "post-package-update": {
47562                     "type": ["array", "string"],
47563                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
47564                 },
47565                 "pre-package-uninstall": {
47566                     "type": ["array", "string"],
47567                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
47568                 },
47569                 "post-package-uninstall": {
47570                     "type": ["array", "string"],
47571                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
47572                 },
47573                 "pre-autoload-dump": {
47574                     "type": ["array", "string"],
47575                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
47576                 },
47577                 "post-autoload-dump": {
47578                     "type": ["array", "string"],
47579                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
47580                 },
47581                 "post-root-package-install": {
47582                     "type": ["array", "string"],
47583                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
47584                 },
47585                 "post-create-project-cmd": {
47586                     "type": ["array", "string"],
47587                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
47588                 }
47589             }
47590         },
47591         "scripts-descriptions": {
47592             "type": ["object"],
47593             "description": "Descriptions for custom commands, shown in console help.",
47594             "additionalProperties": {
47595                 "type": "string"
47596             }
47597         },
47598         "support": {
47599             "type": "object",
47600             "properties": {
47601                 "email": {
47602                     "type": "string",
47603                     "description": "Email address for support.",
47604                     "format": "email"
47605                 },
47606                 "issues": {
47607                     "type": "string",
47608                     "description": "URL to the issue tracker.",
47609                     "format": "uri"
47610                 },
47611                 "forum": {
47612                     "type": "string",
47613                     "description": "URL to the forum.",
47614                     "format": "uri"
47615                 },
47616                 "wiki": {
47617                     "type": "string",
47618                     "description": "URL to the wiki.",
47619                     "format": "uri"
47620                 },
47621                 "irc": {
47622                     "type": "string",
47623                     "description": "IRC channel for support, as irc://server/channel.",
47624                     "format": "uri"
47625                 },
47626                 "chat": {
47627                     "type": "string",
47628                     "description": "URL to the support chat.",
47629                     "format": "uri"
47630                 },
47631                 "source": {
47632                     "type": "string",
47633                     "description": "URL to browse or download the sources.",
47634                     "format": "uri"
47635                 },
47636                 "docs": {
47637                     "type": "string",
47638                     "description": "URL to the documentation.",
47639                     "format": "uri"
47640                 },
47641                 "rss": {
47642                     "type": "string",
47643                     "description": "URL to the RSS feed.",
47644                     "format": "uri"
47645                 }
47646             }
47647         },
47648         "non-feature-branches": {
47649             "type": ["array"],
47650             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
47651             "items": {
47652                 "type": "string"
47653             }
47654         },
47655         "abandoned": {
47656             "type": ["boolean", "string"],
47657             "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."
47658         },
47659         "_comment": {
47660             "type": ["array", "string"],
47661             "description": "A key to store comments in"
47662         }
47663     },
47664     "definitions": {
47665         "authors": {
47666             "type": "array",
47667             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
47668             "items": {
47669                 "type": "object",
47670                 "additionalProperties": false,
47671                 "required": [ "name"],
47672                 "properties": {
47673                     "name": {
47674                         "type": "string",
47675                         "description": "Full name of the author."
47676                     },
47677                     "email": {
47678                         "type": "string",
47679                         "description": "Email address of the author.",
47680                         "format": "email"
47681                     },
47682                     "homepage": {
47683                         "type": "string",
47684                         "description": "Homepage URL for the author.",
47685                         "format": "uri"
47686                     },
47687                     "role": {
47688                         "type": "string",
47689                         "description": "Author's role in the project."
47690                     }
47691                 }
47692             }
47693         },
47694         "autoload": {
47695             "type": "object",
47696             "description": "Description of how the package can be autoloaded.",
47697             "properties": {
47698                 "psr-0": {
47699                     "type": "object",
47700                     "description": "This is a hash of namespaces (keys) and the directories they can be found in (values, can be arrays of paths) by the autoloader.",
47701                     "additionalProperties": {
47702                         "type": ["string", "array"],
47703                         "items": {
47704                             "type": "string"
47705                         }
47706                     }
47707                 },
47708                 "psr-4": {
47709                     "type": "object",
47710                     "description": "This is a hash of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.",
47711                     "additionalProperties": {
47712                         "type": ["string", "array"],
47713                         "items": {
47714                             "type": "string"
47715                         }
47716                     }
47717                 },
47718                 "classmap": {
47719                     "type": "array",
47720                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
47721                 },
47722                 "files": {
47723                     "type": "array",
47724                     "description": "This is an array of files that are always required on every request."
47725                 },
47726                 "exclude-from-classmap": {
47727                     "type": "array",
47728                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
47729                 }
47730             }
47731         },
47732         "repository": {
47733             "type": "object",
47734             "oneOf": [
47735                 { "$ref": "#/definitions/composer-repository" },
47736                 { "$ref": "#/definitions/vcs-repository" },
47737                 { "$ref": "#/definitions/path-repository" },
47738                 { "$ref": "#/definitions/artifact-repository" },
47739                 { "$ref": "#/definitions/pear-repository" },
47740                 { "$ref": "#/definitions/package-repository" }
47741             ]
47742         },
47743         "composer-repository": {
47744             "type": "object",
47745             "required": ["type", "url"],
47746             "properties": {
47747                 "type": { "type": "string", "enum": ["composer"] },
47748                 "url": { "type": "string" },
47749                 "options": {
47750                     "type": "object",
47751                     "additionalProperties": true
47752                 },
47753                 "allow_ssl_downgrade": { "type": "boolean" },
47754                 "force-lazy-providers": { "type": "boolean" }
47755             }
47756         },
47757         "vcs-repository": {
47758             "type": "object",
47759             "required": ["type", "url"],
47760             "properties": {
47761                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
47762                 "url": { "type": "string" },
47763                 "no-api": { "type": "boolean" },
47764                 "secure-http": { "type": "boolean" },
47765                 "svn-cache-credentials": { "type": "boolean" },
47766                 "trunk-path": { "type": ["string", "boolean"] },
47767                 "branches-path": { "type": ["string", "boolean"] },
47768                 "tags-path": { "type": ["string", "boolean"] },
47769                 "package-path": { "type": "string" },
47770                 "depot": { "type": "string" },
47771                 "branch": { "type": "string" },
47772                 "unique_perforce_client_name": { "type": "string" },
47773                 "p4user": { "type": "string" },
47774                 "p4password": { "type": "string" }
47775             }
47776         },
47777         "path-repository": {
47778             "type": "object",
47779             "required": ["type", "url"],
47780             "properties": {
47781                 "type": { "type": "string", "enum": ["path"] },
47782                 "url": { "type": "string" },
47783                 "options": {
47784                     "type": "object",
47785                     "properties": {
47786                         "symlink": { "type": ["boolean", "null"] }
47787                     },
47788                     "additionalProperties": true
47789                 }
47790             }
47791         },
47792         "artifact-repository": {
47793             "type": "object",
47794             "required": ["type", "url"],
47795             "properties": {
47796                 "type": { "type": "string", "enum": ["artifact"] },
47797                 "url": { "type": "string" }
47798             }
47799         },
47800         "pear-repository": {
47801             "type": "object",
47802             "required": ["type", "url"],
47803             "properties": {
47804                 "type": { "type": "string", "enum": ["pear"] },
47805                 "url": { "type": "string" },
47806                 "vendor-alias": { "type": "string" }
47807             }
47808         },
47809         "package-repository": {
47810             "type": "object",
47811             "required": ["type", "package"],
47812             "properties": {
47813                 "type": { "type": "string", "enum": ["package"] },
47814                 "package": {
47815                     "oneOf": [
47816                         { "$ref": "#/definitions/inline-package" },
47817                         {
47818                             "type": "array",
47819                             "items": { "$ref": "#/definitions/inline-package" }
47820                         }
47821                     ]
47822                 }
47823             }
47824         },
47825         "inline-package": {
47826             "type": "object",
47827             "required": ["name", "version"],
47828             "properties": {
47829                 "name": {
47830                     "type": "string",
47831                     "description": "Package name, including 'vendor-name/' prefix."
47832                 },
47833                 "type": {
47834                     "type": "string"
47835                 },
47836                 "target-dir": {
47837                     "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.",
47838                     "type": "string"
47839                 },
47840                 "description": {
47841                     "type": "string"
47842                 },
47843                 "keywords": {
47844                     "type": "array",
47845                     "items": {
47846                         "type": "string"
47847                     }
47848                 },
47849                 "homepage": {
47850                     "type": "string",
47851                     "format": "uri"
47852                 },
47853                 "version": {
47854                     "type": "string"
47855                 },
47856                 "time": {
47857                     "type": "string"
47858                 },
47859                 "license": {
47860                     "type": [
47861                         "string",
47862                         "array"
47863                     ]
47864                 },
47865                 "authors": {
47866                     "$ref": "#/definitions/authors"
47867                 },
47868                 "require": {
47869                     "type": "object",
47870                     "additionalProperties": {
47871                         "type": "string"
47872                     }
47873                 },
47874                 "replace": {
47875                     "type": "object",
47876                     "additionalProperties": {
47877                         "type": "string"
47878                     }
47879                 },
47880                 "conflict": {
47881                     "type": "object",
47882                     "additionalProperties": {
47883                         "type": "string"
47884                     }
47885                 },
47886                 "provide": {
47887                     "type": "object",
47888                     "additionalProperties": {
47889                         "type": "string"
47890                     }
47891                 },
47892                 "require-dev": {
47893                     "type": "object",
47894                     "additionalProperties": {
47895                         "type": "string"
47896                     }
47897                 },
47898                 "suggest": {
47899                     "type": "object",
47900                     "additionalProperties": {
47901                         "type": "string"
47902                     }
47903                 },
47904                 "extra": {
47905                     "type": ["object", "array"],
47906                     "additionalProperties": true
47907                 },
47908                 "autoload": {
47909                     "$ref": "#/definitions/autoload"
47910                 },
47911                 "archive": {
47912                     "type": ["object"],
47913                     "properties": {
47914                         "exclude": {
47915                             "type": "array"
47916                         }
47917                     }
47918                 },
47919                 "bin": {
47920                     "type": ["string", "array"],
47921                     "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
47922                     "items": {
47923                         "type": "string"
47924                     }
47925                 },
47926                 "include-path": {
47927                     "type": ["array"],
47928                     "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.",
47929                     "items": {
47930                         "type": "string"
47931                     }
47932                 },
47933                 "source": {
47934                     "type": "object",
47935                     "required": ["type", "url", "reference"],
47936                     "properties": {
47937                         "type": {
47938                             "type": "string"
47939                         },
47940                         "url": {
47941                             "type": "string"
47942                         },
47943                         "reference": {
47944                             "type": "string"
47945                         },
47946                         "mirrors": {
47947                             "type": "array"
47948                         }
47949                     }
47950                 },
47951                 "dist": {
47952                     "type": "object",
47953                     "required": ["type", "url"],
47954                     "properties": {
47955                         "type": {
47956                             "type": "string"
47957                         },
47958                         "url": {
47959                             "type": "string"
47960                         },
47961                         "reference": {
47962                             "type": "string"
47963                         },
47964                         "shasum": {
47965                             "type": "string"
47966                         },
47967                         "mirrors": {
47968                             "type": "array"
47969                         }
47970                     }
47971                 }
47972             },
47973             "additionalProperties": true
47974         }
47975     }
47976 }
47977 {
47978     "389-exception": [
47979         "389 Directory Server Exception"
47980     ],
47981     "Autoconf-exception-2.0": [
47982         "Autoconf exception 2.0"
47983     ],
47984     "Autoconf-exception-3.0": [
47985         "Autoconf exception 3.0"
47986     ],
47987     "Bison-exception-2.2": [
47988         "Bison exception 2.2"
47989     ],
47990     "Bootloader-exception": [
47991         "Bootloader Distribution Exception"
47992     ],
47993     "Classpath-exception-2.0": [
47994         "Classpath exception 2.0"
47995     ],
47996     "CLISP-exception-2.0": [
47997         "CLISP exception 2.0"
47998     ],
47999     "DigiRule-FOSS-exception": [
48000         "DigiRule FOSS License Exception"
48001     ],
48002     "eCos-exception-2.0": [
48003         "eCos exception 2.0"
48004     ],
48005     "Fawkes-Runtime-exception": [
48006         "Fawkes Runtime Exception"
48007     ],
48008     "FLTK-exception": [
48009         "FLTK exception"
48010     ],
48011     "Font-exception-2.0": [
48012         "Font exception 2.0"
48013     ],
48014     "freertos-exception-2.0": [
48015         "FreeRTOS Exception 2.0"
48016     ],
48017     "GCC-exception-2.0": [
48018         "GCC Runtime Library exception 2.0"
48019     ],
48020     "GCC-exception-3.1": [
48021         "GCC Runtime Library exception 3.1"
48022     ],
48023     "gnu-javamail-exception": [
48024         "GNU JavaMail exception"
48025     ],
48026     "GPL-CC-1.0": [
48027         "GPL Cooperation Commitment 1.0"
48028     ],
48029     "i2p-gpl-java-exception": [
48030         "i2p GPL+Java Exception"
48031     ],
48032     "Libtool-exception": [
48033         "Libtool Exception"
48034     ],
48035     "Linux-syscall-note": [
48036         "Linux Syscall Note"
48037     ],
48038     "LLVM-exception": [
48039         "LLVM Exception"
48040     ],
48041     "LZMA-exception": [
48042         "LZMA exception"
48043     ],
48044     "mif-exception": [
48045         "Macros and Inline Functions Exception"
48046     ],
48047     "Nokia-Qt-exception-1.1": [
48048         "Nokia Qt LGPL exception 1.1"
48049     ],
48050     "OCaml-LGPL-linking-exception": [
48051         "OCaml LGPL Linking Exception"
48052     ],
48053     "OCCT-exception-1.0": [
48054         "Open CASCADE Exception 1.0"
48055     ],
48056     "OpenJDK-assembly-exception-1.0": [
48057         "OpenJDK Assembly exception 1.0"
48058     ],
48059     "openvpn-openssl-exception": [
48060         "OpenVPN OpenSSL Exception"
48061     ],
48062     "PS-or-PDF-font-exception-20170817": [
48063         "PS/PDF font exception (2017-08-17)"
48064     ],
48065     "Qt-GPL-exception-1.0": [
48066         "Qt GPL exception 1.0"
48067     ],
48068     "Qt-LGPL-exception-1.1": [
48069         "Qt LGPL exception 1.1"
48070     ],
48071     "Qwt-exception-1.0": [
48072         "Qwt exception 1.0"
48073     ],
48074     "Swift-exception": [
48075         "Swift Exception"
48076     ],
48077     "u-boot-exception-2.0": [
48078         "U-Boot exception 2.0"
48079     ],
48080     "Universal-FOSS-exception-1.0": [
48081         "Universal FOSS Exception, Version 1.0"
48082     ],
48083     "WxWindows-exception-3.1": [
48084         "WxWindows Library Exception 3.1"
48085     ]
48086 }{
48087     "0BSD": [
48088         "BSD Zero Clause License",
48089         true,
48090         false
48091     ],
48092     "AAL": [
48093         "Attribution Assurance License",
48094         true,
48095         false
48096     ],
48097     "Abstyles": [
48098         "Abstyles License",
48099         false,
48100         false
48101     ],
48102     "Adobe-2006": [
48103         "Adobe Systems Incorporated Source Code License Agreement",
48104         false,
48105         false
48106     ],
48107     "Adobe-Glyph": [
48108         "Adobe Glyph List License",
48109         false,
48110         false
48111     ],
48112     "ADSL": [
48113         "Amazon Digital Services License",
48114         false,
48115         false
48116     ],
48117     "AFL-1.1": [
48118         "Academic Free License v1.1",
48119         true,
48120         false
48121     ],
48122     "AFL-1.2": [
48123         "Academic Free License v1.2",
48124         true,
48125         false
48126     ],
48127     "AFL-2.0": [
48128         "Academic Free License v2.0",
48129         true,
48130         false
48131     ],
48132     "AFL-2.1": [
48133         "Academic Free License v2.1",
48134         true,
48135         false
48136     ],
48137     "AFL-3.0": [
48138         "Academic Free License v3.0",
48139         true,
48140         false
48141     ],
48142     "Afmparse": [
48143         "Afmparse License",
48144         false,
48145         false
48146     ],
48147     "AGPL-1.0": [
48148         "Affero General Public License v1.0",
48149         false,
48150         true
48151     ],
48152     "AGPL-1.0-only": [
48153         "Affero General Public License v1.0 only",
48154         false,
48155         false
48156     ],
48157     "AGPL-1.0-or-later": [
48158         "Affero General Public License v1.0 or later",
48159         false,
48160         false
48161     ],
48162     "AGPL-3.0": [
48163         "GNU Affero General Public License v3.0",
48164         true,
48165         true
48166     ],
48167     "AGPL-3.0-only": [
48168         "GNU Affero General Public License v3.0 only",
48169         true,
48170         false
48171     ],
48172     "AGPL-3.0-or-later": [
48173         "GNU Affero General Public License v3.0 or later",
48174         true,
48175         false
48176     ],
48177     "Aladdin": [
48178         "Aladdin Free Public License",
48179         false,
48180         false
48181     ],
48182     "AMDPLPA": [
48183         "AMD's plpa_map.c License",
48184         false,
48185         false
48186     ],
48187     "AML": [
48188         "Apple MIT License",
48189         false,
48190         false
48191     ],
48192     "AMPAS": [
48193         "Academy of Motion Picture Arts and Sciences BSD",
48194         false,
48195         false
48196     ],
48197     "ANTLR-PD": [
48198         "ANTLR Software Rights Notice",
48199         false,
48200         false
48201     ],
48202     "Apache-1.0": [
48203         "Apache License 1.0",
48204         false,
48205         false
48206     ],
48207     "Apache-1.1": [
48208         "Apache License 1.1",
48209         true,
48210         false
48211     ],
48212     "Apache-2.0": [
48213         "Apache License 2.0",
48214         true,
48215         false
48216     ],
48217     "APAFML": [
48218         "Adobe Postscript AFM License",
48219         false,
48220         false
48221     ],
48222     "APL-1.0": [
48223         "Adaptive Public License 1.0",
48224         true,
48225         false
48226     ],
48227     "APSL-1.0": [
48228         "Apple Public Source License 1.0",
48229         true,
48230         false
48231     ],
48232     "APSL-1.1": [
48233         "Apple Public Source License 1.1",
48234         true,
48235         false
48236     ],
48237     "APSL-1.2": [
48238         "Apple Public Source License 1.2",
48239         true,
48240         false
48241     ],
48242     "APSL-2.0": [
48243         "Apple Public Source License 2.0",
48244         true,
48245         false
48246     ],
48247     "Artistic-1.0": [
48248         "Artistic License 1.0",
48249         true,
48250         false
48251     ],
48252     "Artistic-1.0-cl8": [
48253         "Artistic License 1.0 w/clause 8",
48254         true,
48255         false
48256     ],
48257     "Artistic-1.0-Perl": [
48258         "Artistic License 1.0 (Perl)",
48259         true,
48260         false
48261     ],
48262     "Artistic-2.0": [
48263         "Artistic License 2.0",
48264         true,
48265         false
48266     ],
48267     "Bahyph": [
48268         "Bahyph License",
48269         false,
48270         false
48271     ],
48272     "Barr": [
48273         "Barr License",
48274         false,
48275         false
48276     ],
48277     "Beerware": [
48278         "Beerware License",
48279         false,
48280         false
48281     ],
48282     "BitTorrent-1.0": [
48283         "BitTorrent Open Source License v1.0",
48284         false,
48285         false
48286     ],
48287     "BitTorrent-1.1": [
48288         "BitTorrent Open Source License v1.1",
48289         false,
48290         false
48291     ],
48292     "blessing": [
48293         "SQLite Blessing",
48294         false,
48295         false
48296     ],
48297     "BlueOak-1.0.0": [
48298         "Blue Oak Model License 1.0.0",
48299         false,
48300         false
48301     ],
48302     "Borceux": [
48303         "Borceux license",
48304         false,
48305         false
48306     ],
48307     "BSD-1-Clause": [
48308         "BSD 1-Clause License",
48309         false,
48310         false
48311     ],
48312     "BSD-2-Clause": [
48313         "BSD 2-Clause \"Simplified\" License",
48314         true,
48315         false
48316     ],
48317     "BSD-2-Clause-FreeBSD": [
48318         "BSD 2-Clause FreeBSD License",
48319         false,
48320         false
48321     ],
48322     "BSD-2-Clause-NetBSD": [
48323         "BSD 2-Clause NetBSD License",
48324         false,
48325         false
48326     ],
48327     "BSD-2-Clause-Patent": [
48328         "BSD-2-Clause Plus Patent License",
48329         true,
48330         false
48331     ],
48332     "BSD-3-Clause": [
48333         "BSD 3-Clause \"New\" or \"Revised\" License",
48334         true,
48335         false
48336     ],
48337     "BSD-3-Clause-Attribution": [
48338         "BSD with attribution",
48339         false,
48340         false
48341     ],
48342     "BSD-3-Clause-Clear": [
48343         "BSD 3-Clause Clear License",
48344         false,
48345         false
48346     ],
48347     "BSD-3-Clause-LBNL": [
48348         "Lawrence Berkeley National Labs BSD variant license",
48349         true,
48350         false
48351     ],
48352     "BSD-3-Clause-No-Nuclear-License": [
48353         "BSD 3-Clause No Nuclear License",
48354         false,
48355         false
48356     ],
48357     "BSD-3-Clause-No-Nuclear-License-2014": [
48358         "BSD 3-Clause No Nuclear License 2014",
48359         false,
48360         false
48361     ],
48362     "BSD-3-Clause-No-Nuclear-Warranty": [
48363         "BSD 3-Clause No Nuclear Warranty",
48364         false,
48365         false
48366     ],
48367     "BSD-3-Clause-Open-MPI": [
48368         "BSD 3-Clause Open MPI variant",
48369         false,
48370         false
48371     ],
48372     "BSD-4-Clause": [
48373         "BSD 4-Clause \"Original\" or \"Old\" License",
48374         false,
48375         false
48376     ],
48377     "BSD-4-Clause-UC": [
48378         "BSD-4-Clause (University of California-Specific)",
48379         false,
48380         false
48381     ],
48382     "BSD-Protection": [
48383         "BSD Protection License",
48384         false,
48385         false
48386     ],
48387     "BSD-Source-Code": [
48388         "BSD Source Code Attribution",
48389         false,
48390         false
48391     ],
48392     "BSL-1.0": [
48393         "Boost Software License 1.0",
48394         true,
48395         false
48396     ],
48397     "bzip2-1.0.5": [
48398         "bzip2 and libbzip2 License v1.0.5",
48399         false,
48400         false
48401     ],
48402     "bzip2-1.0.6": [
48403         "bzip2 and libbzip2 License v1.0.6",
48404         false,
48405         false
48406     ],
48407     "Caldera": [
48408         "Caldera License",
48409         false,
48410         false
48411     ],
48412     "CATOSL-1.1": [
48413         "Computer Associates Trusted Open Source License 1.1",
48414         true,
48415         false
48416     ],
48417     "CC-BY-1.0": [
48418         "Creative Commons Attribution 1.0 Generic",
48419         false,
48420         false
48421     ],
48422     "CC-BY-2.0": [
48423         "Creative Commons Attribution 2.0 Generic",
48424         false,
48425         false
48426     ],
48427     "CC-BY-2.5": [
48428         "Creative Commons Attribution 2.5 Generic",
48429         false,
48430         false
48431     ],
48432     "CC-BY-3.0": [
48433         "Creative Commons Attribution 3.0 Unported",
48434         false,
48435         false
48436     ],
48437     "CC-BY-4.0": [
48438         "Creative Commons Attribution 4.0 International",
48439         false,
48440         false
48441     ],
48442     "CC-BY-NC-1.0": [
48443         "Creative Commons Attribution Non Commercial 1.0 Generic",
48444         false,
48445         false
48446     ],
48447     "CC-BY-NC-2.0": [
48448         "Creative Commons Attribution Non Commercial 2.0 Generic",
48449         false,
48450         false
48451     ],
48452     "CC-BY-NC-2.5": [
48453         "Creative Commons Attribution Non Commercial 2.5 Generic",
48454         false,
48455         false
48456     ],
48457     "CC-BY-NC-3.0": [
48458         "Creative Commons Attribution Non Commercial 3.0 Unported",
48459         false,
48460         false
48461     ],
48462     "CC-BY-NC-4.0": [
48463         "Creative Commons Attribution Non Commercial 4.0 International",
48464         false,
48465         false
48466     ],
48467     "CC-BY-NC-ND-1.0": [
48468         "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",
48469         false,
48470         false
48471     ],
48472     "CC-BY-NC-ND-2.0": [
48473         "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",
48474         false,
48475         false
48476     ],
48477     "CC-BY-NC-ND-2.5": [
48478         "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",
48479         false,
48480         false
48481     ],
48482     "CC-BY-NC-ND-3.0": [
48483         "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",
48484         false,
48485         false
48486     ],
48487     "CC-BY-NC-ND-4.0": [
48488         "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",
48489         false,
48490         false
48491     ],
48492     "CC-BY-NC-SA-1.0": [
48493         "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",
48494         false,
48495         false
48496     ],
48497     "CC-BY-NC-SA-2.0": [
48498         "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",
48499         false,
48500         false
48501     ],
48502     "CC-BY-NC-SA-2.5": [
48503         "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",
48504         false,
48505         false
48506     ],
48507     "CC-BY-NC-SA-3.0": [
48508         "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",
48509         false,
48510         false
48511     ],
48512     "CC-BY-NC-SA-4.0": [
48513         "Creative Commons Attribution Non Commercial Share Alike 4.0 International",
48514         false,
48515         false
48516     ],
48517     "CC-BY-ND-1.0": [
48518         "Creative Commons Attribution No Derivatives 1.0 Generic",
48519         false,
48520         false
48521     ],
48522     "CC-BY-ND-2.0": [
48523         "Creative Commons Attribution No Derivatives 2.0 Generic",
48524         false,
48525         false
48526     ],
48527     "CC-BY-ND-2.5": [
48528         "Creative Commons Attribution No Derivatives 2.5 Generic",
48529         false,
48530         false
48531     ],
48532     "CC-BY-ND-3.0": [
48533         "Creative Commons Attribution No Derivatives 3.0 Unported",
48534         false,
48535         false
48536     ],
48537     "CC-BY-ND-4.0": [
48538         "Creative Commons Attribution No Derivatives 4.0 International",
48539         false,
48540         false
48541     ],
48542     "CC-BY-SA-1.0": [
48543         "Creative Commons Attribution Share Alike 1.0 Generic",
48544         false,
48545         false
48546     ],
48547     "CC-BY-SA-2.0": [
48548         "Creative Commons Attribution Share Alike 2.0 Generic",
48549         false,
48550         false
48551     ],
48552     "CC-BY-SA-2.5": [
48553         "Creative Commons Attribution Share Alike 2.5 Generic",
48554         false,
48555         false
48556     ],
48557     "CC-BY-SA-3.0": [
48558         "Creative Commons Attribution Share Alike 3.0 Unported",
48559         false,
48560         false
48561     ],
48562     "CC-BY-SA-4.0": [
48563         "Creative Commons Attribution Share Alike 4.0 International",
48564         false,
48565         false
48566     ],
48567     "CC-PDDC": [
48568         "Creative Commons Public Domain Dedication and Certification",
48569         false,
48570         false
48571     ],
48572     "CC0-1.0": [
48573         "Creative Commons Zero v1.0 Universal",
48574         false,
48575         false
48576     ],
48577     "CDDL-1.0": [
48578         "Common Development and Distribution License 1.0",
48579         true,
48580         false
48581     ],
48582     "CDDL-1.1": [
48583         "Common Development and Distribution License 1.1",
48584         false,
48585         false
48586     ],
48587     "CDLA-Permissive-1.0": [
48588         "Community Data License Agreement Permissive 1.0",
48589         false,
48590         false
48591     ],
48592     "CDLA-Sharing-1.0": [
48593         "Community Data License Agreement Sharing 1.0",
48594         false,
48595         false
48596     ],
48597     "CECILL-1.0": [
48598         "CeCILL Free Software License Agreement v1.0",
48599         false,
48600         false
48601     ],
48602     "CECILL-1.1": [
48603         "CeCILL Free Software License Agreement v1.1",
48604         false,
48605         false
48606     ],
48607     "CECILL-2.0": [
48608         "CeCILL Free Software License Agreement v2.0",
48609         false,
48610         false
48611     ],
48612     "CECILL-2.1": [
48613         "CeCILL Free Software License Agreement v2.1",
48614         true,
48615         false
48616     ],
48617     "CECILL-B": [
48618         "CeCILL-B Free Software License Agreement",
48619         false,
48620         false
48621     ],
48622     "CECILL-C": [
48623         "CeCILL-C Free Software License Agreement",
48624         false,
48625         false
48626     ],
48627     "CERN-OHL-1.1": [
48628         "CERN Open Hardware License v1.1",
48629         false,
48630         false
48631     ],
48632     "CERN-OHL-1.2": [
48633         "CERN Open Hardware Licence v1.2",
48634         false,
48635         false
48636     ],
48637     "ClArtistic": [
48638         "Clarified Artistic License",
48639         false,
48640         false
48641     ],
48642     "CNRI-Jython": [
48643         "CNRI Jython License",
48644         false,
48645         false
48646     ],
48647     "CNRI-Python": [
48648         "CNRI Python License",
48649         true,
48650         false
48651     ],
48652     "CNRI-Python-GPL-Compatible": [
48653         "CNRI Python Open Source GPL Compatible License Agreement",
48654         false,
48655         false
48656     ],
48657     "Condor-1.1": [
48658         "Condor Public License v1.1",
48659         false,
48660         false
48661     ],
48662     "copyleft-next-0.3.0": [
48663         "copyleft-next 0.3.0",
48664         false,
48665         false
48666     ],
48667     "copyleft-next-0.3.1": [
48668         "copyleft-next 0.3.1",
48669         false,
48670         false
48671     ],
48672     "CPAL-1.0": [
48673         "Common Public Attribution License 1.0",
48674         true,
48675         false
48676     ],
48677     "CPL-1.0": [
48678         "Common Public License 1.0",
48679         true,
48680         false
48681     ],
48682     "CPOL-1.02": [
48683         "Code Project Open License 1.02",
48684         false,
48685         false
48686     ],
48687     "Crossword": [
48688         "Crossword License",
48689         false,
48690         false
48691     ],
48692     "CrystalStacker": [
48693         "CrystalStacker License",
48694         false,
48695         false
48696     ],
48697     "CUA-OPL-1.0": [
48698         "CUA Office Public License v1.0",
48699         true,
48700         false
48701     ],
48702     "Cube": [
48703         "Cube License",
48704         false,
48705         false
48706     ],
48707     "curl": [
48708         "curl License",
48709         false,
48710         false
48711     ],
48712     "D-FSL-1.0": [
48713         "Deutsche Freie Software Lizenz",
48714         false,
48715         false
48716     ],
48717     "diffmark": [
48718         "diffmark license",
48719         false,
48720         false
48721     ],
48722     "DOC": [
48723         "DOC License",
48724         false,
48725         false
48726     ],
48727     "Dotseqn": [
48728         "Dotseqn License",
48729         false,
48730         false
48731     ],
48732     "DSDP": [
48733         "DSDP License",
48734         false,
48735         false
48736     ],
48737     "dvipdfm": [
48738         "dvipdfm License",
48739         false,
48740         false
48741     ],
48742     "ECL-1.0": [
48743         "Educational Community License v1.0",
48744         true,
48745         false
48746     ],
48747     "ECL-2.0": [
48748         "Educational Community License v2.0",
48749         true,
48750         false
48751     ],
48752     "eCos-2.0": [
48753         "eCos license version 2.0",
48754         false,
48755         true
48756     ],
48757     "EFL-1.0": [
48758         "Eiffel Forum License v1.0",
48759         true,
48760         false
48761     ],
48762     "EFL-2.0": [
48763         "Eiffel Forum License v2.0",
48764         true,
48765         false
48766     ],
48767     "eGenix": [
48768         "eGenix.com Public License 1.1.0",
48769         false,
48770         false
48771     ],
48772     "Entessa": [
48773         "Entessa Public License v1.0",
48774         true,
48775         false
48776     ],
48777     "EPL-1.0": [
48778         "Eclipse Public License 1.0",
48779         true,
48780         false
48781     ],
48782     "EPL-2.0": [
48783         "Eclipse Public License 2.0",
48784         true,
48785         false
48786     ],
48787     "ErlPL-1.1": [
48788         "Erlang Public License v1.1",
48789         false,
48790         false
48791     ],
48792     "EUDatagrid": [
48793         "EU DataGrid Software License",
48794         true,
48795         false
48796     ],
48797     "EUPL-1.0": [
48798         "European Union Public License 1.0",
48799         false,
48800         false
48801     ],
48802     "EUPL-1.1": [
48803         "European Union Public License 1.1",
48804         true,
48805         false
48806     ],
48807     "EUPL-1.2": [
48808         "European Union Public License 1.2",
48809         true,
48810         false
48811     ],
48812     "Eurosym": [
48813         "Eurosym License",
48814         false,
48815         false
48816     ],
48817     "Fair": [
48818         "Fair License",
48819         true,
48820         false
48821     ],
48822     "Frameworx-1.0": [
48823         "Frameworx Open License 1.0",
48824         true,
48825         false
48826     ],
48827     "FreeImage": [
48828         "FreeImage Public License v1.0",
48829         false,
48830         false
48831     ],
48832     "FSFAP": [
48833         "FSF All Permissive License",
48834         false,
48835         false
48836     ],
48837     "FSFUL": [
48838         "FSF Unlimited License",
48839         false,
48840         false
48841     ],
48842     "FSFULLR": [
48843         "FSF Unlimited License (with License Retention)",
48844         false,
48845         false
48846     ],
48847     "FTL": [
48848         "Freetype Project License",
48849         false,
48850         false
48851     ],
48852     "GFDL-1.1": [
48853         "GNU Free Documentation License v1.1",
48854         false,
48855         true
48856     ],
48857     "GFDL-1.1-only": [
48858         "GNU Free Documentation License v1.1 only",
48859         false,
48860         false
48861     ],
48862     "GFDL-1.1-or-later": [
48863         "GNU Free Documentation License v1.1 or later",
48864         false,
48865         false
48866     ],
48867     "GFDL-1.2": [
48868         "GNU Free Documentation License v1.2",
48869         false,
48870         true
48871     ],
48872     "GFDL-1.2-only": [
48873         "GNU Free Documentation License v1.2 only",
48874         false,
48875         false
48876     ],
48877     "GFDL-1.2-or-later": [
48878         "GNU Free Documentation License v1.2 or later",
48879         false,
48880         false
48881     ],
48882     "GFDL-1.3": [
48883         "GNU Free Documentation License v1.3",
48884         false,
48885         true
48886     ],
48887     "GFDL-1.3-only": [
48888         "GNU Free Documentation License v1.3 only",
48889         false,
48890         false
48891     ],
48892     "GFDL-1.3-or-later": [
48893         "GNU Free Documentation License v1.3 or later",
48894         false,
48895         false
48896     ],
48897     "Giftware": [
48898         "Giftware License",
48899         false,
48900         false
48901     ],
48902     "GL2PS": [
48903         "GL2PS License",
48904         false,
48905         false
48906     ],
48907     "Glide": [
48908         "3dfx Glide License",
48909         false,
48910         false
48911     ],
48912     "Glulxe": [
48913         "Glulxe License",
48914         false,
48915         false
48916     ],
48917     "gnuplot": [
48918         "gnuplot License",
48919         false,
48920         false
48921     ],
48922     "GPL-1.0": [
48923         "GNU General Public License v1.0 only",
48924         false,
48925         true
48926     ],
48927     "GPL-1.0+": [
48928         "GNU General Public License v1.0 or later",
48929         false,
48930         true
48931     ],
48932     "GPL-1.0-only": [
48933         "GNU General Public License v1.0 only",
48934         false,
48935         false
48936     ],
48937     "GPL-1.0-or-later": [
48938         "GNU General Public License v1.0 or later",
48939         false,
48940         false
48941     ],
48942     "GPL-2.0": [
48943         "GNU General Public License v2.0 only",
48944         true,
48945         true
48946     ],
48947     "GPL-2.0+": [
48948         "GNU General Public License v2.0 or later",
48949         true,
48950         true
48951     ],
48952     "GPL-2.0-only": [
48953         "GNU General Public License v2.0 only",
48954         true,
48955         false
48956     ],
48957     "GPL-2.0-or-later": [
48958         "GNU General Public License v2.0 or later",
48959         true,
48960         false
48961     ],
48962     "GPL-2.0-with-autoconf-exception": [
48963         "GNU General Public License v2.0 w/Autoconf exception",
48964         false,
48965         true
48966     ],
48967     "GPL-2.0-with-bison-exception": [
48968         "GNU General Public License v2.0 w/Bison exception",
48969         false,
48970         true
48971     ],
48972     "GPL-2.0-with-classpath-exception": [
48973         "GNU General Public License v2.0 w/Classpath exception",
48974         false,
48975         true
48976     ],
48977     "GPL-2.0-with-font-exception": [
48978         "GNU General Public License v2.0 w/Font exception",
48979         false,
48980         true
48981     ],
48982     "GPL-2.0-with-GCC-exception": [
48983         "GNU General Public License v2.0 w/GCC Runtime Library exception",
48984         false,
48985         true
48986     ],
48987     "GPL-3.0": [
48988         "GNU General Public License v3.0 only",
48989         true,
48990         true
48991     ],
48992     "GPL-3.0+": [
48993         "GNU General Public License v3.0 or later",
48994         true,
48995         true
48996     ],
48997     "GPL-3.0-only": [
48998         "GNU General Public License v3.0 only",
48999         true,
49000         false
49001     ],
49002     "GPL-3.0-or-later": [
49003         "GNU General Public License v3.0 or later",
49004         true,
49005         false
49006     ],
49007     "GPL-3.0-with-autoconf-exception": [
49008         "GNU General Public License v3.0 w/Autoconf exception",
49009         false,
49010         true
49011     ],
49012     "GPL-3.0-with-GCC-exception": [
49013         "GNU General Public License v3.0 w/GCC Runtime Library exception",
49014         true,
49015         true
49016     ],
49017     "gSOAP-1.3b": [
49018         "gSOAP Public License v1.3b",
49019         false,
49020         false
49021     ],
49022     "HaskellReport": [
49023         "Haskell Language Report License",
49024         false,
49025         false
49026     ],
49027     "HPND": [
49028         "Historical Permission Notice and Disclaimer",
49029         true,
49030         false
49031     ],
49032     "HPND-sell-variant": [
49033         "Historical Permission Notice and Disclaimer - sell variant",
49034         false,
49035         false
49036     ],
49037     "IBM-pibs": [
49038         "IBM PowerPC Initialization and Boot Software",
49039         false,
49040         false
49041     ],
49042     "ICU": [
49043         "ICU License",
49044         false,
49045         false
49046     ],
49047     "IJG": [
49048         "Independent JPEG Group License",
49049         false,
49050         false
49051     ],
49052     "ImageMagick": [
49053         "ImageMagick License",
49054         false,
49055         false
49056     ],
49057     "iMatix": [
49058         "iMatix Standard Function Library Agreement",
49059         false,
49060         false
49061     ],
49062     "Imlib2": [
49063         "Imlib2 License",
49064         false,
49065         false
49066     ],
49067     "Info-ZIP": [
49068         "Info-ZIP License",
49069         false,
49070         false
49071     ],
49072     "Intel": [
49073         "Intel Open Source License",
49074         true,
49075         false
49076     ],
49077     "Intel-ACPI": [
49078         "Intel ACPI Software License Agreement",
49079         false,
49080         false
49081     ],
49082     "Interbase-1.0": [
49083         "Interbase Public License v1.0",
49084         false,
49085         false
49086     ],
49087     "IPA": [
49088         "IPA Font License",
49089         true,
49090         false
49091     ],
49092     "IPL-1.0": [
49093         "IBM Public License v1.0",
49094         true,
49095         false
49096     ],
49097     "ISC": [
49098         "ISC License",
49099         true,
49100         false
49101     ],
49102     "JasPer-2.0": [
49103         "JasPer License",
49104         false,
49105         false
49106     ],
49107     "JPNIC": [
49108         "Japan Network Information Center License",
49109         false,
49110         false
49111     ],
49112     "JSON": [
49113         "JSON License",
49114         false,
49115         false
49116     ],
49117     "LAL-1.2": [
49118         "Licence Art Libre 1.2",
49119         false,
49120         false
49121     ],
49122     "LAL-1.3": [
49123         "Licence Art Libre 1.3",
49124         false,
49125         false
49126     ],
49127     "Latex2e": [
49128         "Latex2e License",
49129         false,
49130         false
49131     ],
49132     "Leptonica": [
49133         "Leptonica License",
49134         false,
49135         false
49136     ],
49137     "LGPL-2.0": [
49138         "GNU Library General Public License v2 only",
49139         true,
49140         true
49141     ],
49142     "LGPL-2.0+": [
49143         "GNU Library General Public License v2 or later",
49144         true,
49145         true
49146     ],
49147     "LGPL-2.0-only": [
49148         "GNU Library General Public License v2 only",
49149         true,
49150         false
49151     ],
49152     "LGPL-2.0-or-later": [
49153         "GNU Library General Public License v2 or later",
49154         true,
49155         false
49156     ],
49157     "LGPL-2.1": [
49158         "GNU Lesser General Public License v2.1 only",
49159         true,
49160         true
49161     ],
49162     "LGPL-2.1+": [
49163         "GNU Library General Public License v2.1 or later",
49164         true,
49165         true
49166     ],
49167     "LGPL-2.1-only": [
49168         "GNU Lesser General Public License v2.1 only",
49169         true,
49170         false
49171     ],
49172     "LGPL-2.1-or-later": [
49173         "GNU Lesser General Public License v2.1 or later",
49174         true,
49175         false
49176     ],
49177     "LGPL-3.0": [
49178         "GNU Lesser General Public License v3.0 only",
49179         true,
49180         true
49181     ],
49182     "LGPL-3.0+": [
49183         "GNU Lesser General Public License v3.0 or later",
49184         true,
49185         true
49186     ],
49187     "LGPL-3.0-only": [
49188         "GNU Lesser General Public License v3.0 only",
49189         true,
49190         false
49191     ],
49192     "LGPL-3.0-or-later": [
49193         "GNU Lesser General Public License v3.0 or later",
49194         true,
49195         false
49196     ],
49197     "LGPLLR": [
49198         "Lesser General Public License For Linguistic Resources",
49199         false,
49200         false
49201     ],
49202     "Libpng": [
49203         "libpng License",
49204         false,
49205         false
49206     ],
49207     "libpng-2.0": [
49208         "PNG Reference Library version 2",
49209         false,
49210         false
49211     ],
49212     "libtiff": [
49213         "libtiff License",
49214         false,
49215         false
49216     ],
49217     "LiLiQ-P-1.1": [
49218         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
49219         true,
49220         false
49221     ],
49222     "LiLiQ-R-1.1": [
49223         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
49224         true,
49225         false
49226     ],
49227     "LiLiQ-Rplus-1.1": [
49228         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
49229         true,
49230         false
49231     ],
49232     "Linux-OpenIB": [
49233         "Linux Kernel Variant of OpenIB.org license",
49234         false,
49235         false
49236     ],
49237     "LPL-1.0": [
49238         "Lucent Public License Version 1.0",
49239         true,
49240         false
49241     ],
49242     "LPL-1.02": [
49243         "Lucent Public License v1.02",
49244         true,
49245         false
49246     ],
49247     "LPPL-1.0": [
49248         "LaTeX Project Public License v1.0",
49249         false,
49250         false
49251     ],
49252     "LPPL-1.1": [
49253         "LaTeX Project Public License v1.1",
49254         false,
49255         false
49256     ],
49257     "LPPL-1.2": [
49258         "LaTeX Project Public License v1.2",
49259         false,
49260         false
49261     ],
49262     "LPPL-1.3a": [
49263         "LaTeX Project Public License v1.3a",
49264         false,
49265         false
49266     ],
49267     "LPPL-1.3c": [
49268         "LaTeX Project Public License v1.3c",
49269         true,
49270         false
49271     ],
49272     "MakeIndex": [
49273         "MakeIndex License",
49274         false,
49275         false
49276     ],
49277     "MirOS": [
49278         "MirOS License",
49279         true,
49280         false
49281     ],
49282     "MIT": [
49283         "MIT License",
49284         true,
49285         false
49286     ],
49287     "MIT-0": [
49288         "MIT No Attribution",
49289         true,
49290         false
49291     ],
49292     "MIT-advertising": [
49293         "Enlightenment License (e16)",
49294         false,
49295         false
49296     ],
49297     "MIT-CMU": [
49298         "CMU License",
49299         false,
49300         false
49301     ],
49302     "MIT-enna": [
49303         "enna License",
49304         false,
49305         false
49306     ],
49307     "MIT-feh": [
49308         "feh License",
49309         false,
49310         false
49311     ],
49312     "MITNFA": [
49313         "MIT +no-false-attribs license",
49314         false,
49315         false
49316     ],
49317     "Motosoto": [
49318         "Motosoto License",
49319         true,
49320         false
49321     ],
49322     "mpich2": [
49323         "mpich2 License",
49324         false,
49325         false
49326     ],
49327     "MPL-1.0": [
49328         "Mozilla Public License 1.0",
49329         true,
49330         false
49331     ],
49332     "MPL-1.1": [
49333         "Mozilla Public License 1.1",
49334         true,
49335         false
49336     ],
49337     "MPL-2.0": [
49338         "Mozilla Public License 2.0",
49339         true,
49340         false
49341     ],
49342     "MPL-2.0-no-copyleft-exception": [
49343         "Mozilla Public License 2.0 (no copyleft exception)",
49344         true,
49345         false
49346     ],
49347     "MS-PL": [
49348         "Microsoft Public License",
49349         true,
49350         false
49351     ],
49352     "MS-RL": [
49353         "Microsoft Reciprocal License",
49354         true,
49355         false
49356     ],
49357     "MTLL": [
49358         "Matrix Template Library License",
49359         false,
49360         false
49361     ],
49362     "Multics": [
49363         "Multics License",
49364         true,
49365         false
49366     ],
49367     "Mup": [
49368         "Mup License",
49369         false,
49370         false
49371     ],
49372     "NASA-1.3": [
49373         "NASA Open Source Agreement 1.3",
49374         true,
49375         false
49376     ],
49377     "Naumen": [
49378         "Naumen Public License",
49379         true,
49380         false
49381     ],
49382     "NBPL-1.0": [
49383         "Net Boolean Public License v1",
49384         false,
49385         false
49386     ],
49387     "NCSA": [
49388         "University of Illinois/NCSA Open Source License",
49389         true,
49390         false
49391     ],
49392     "Net-SNMP": [
49393         "Net-SNMP License",
49394         false,
49395         false
49396     ],
49397     "NetCDF": [
49398         "NetCDF license",
49399         false,
49400         false
49401     ],
49402     "Newsletr": [
49403         "Newsletr License",
49404         false,
49405         false
49406     ],
49407     "NGPL": [
49408         "Nethack General Public License",
49409         true,
49410         false
49411     ],
49412     "NLOD-1.0": [
49413         "Norwegian Licence for Open Government Data",
49414         false,
49415         false
49416     ],
49417     "NLPL": [
49418         "No Limit Public License",
49419         false,
49420         false
49421     ],
49422     "Nokia": [
49423         "Nokia Open Source License",
49424         true,
49425         false
49426     ],
49427     "NOSL": [
49428         "Netizen Open Source License",
49429         false,
49430         false
49431     ],
49432     "Noweb": [
49433         "Noweb License",
49434         false,
49435         false
49436     ],
49437     "NPL-1.0": [
49438         "Netscape Public License v1.0",
49439         false,
49440         false
49441     ],
49442     "NPL-1.1": [
49443         "Netscape Public License v1.1",
49444         false,
49445         false
49446     ],
49447     "NPOSL-3.0": [
49448         "Non-Profit Open Software License 3.0",
49449         true,
49450         false
49451     ],
49452     "NRL": [
49453         "NRL License",
49454         false,
49455         false
49456     ],
49457     "NTP": [
49458         "NTP License",
49459         true,
49460         false
49461     ],
49462     "Nunit": [
49463         "Nunit License",
49464         false,
49465         true
49466     ],
49467     "OCCT-PL": [
49468         "Open CASCADE Technology Public License",
49469         false,
49470         false
49471     ],
49472     "OCLC-2.0": [
49473         "OCLC Research Public License 2.0",
49474         true,
49475         false
49476     ],
49477     "ODbL-1.0": [
49478         "ODC Open Database License v1.0",
49479         false,
49480         false
49481     ],
49482     "ODC-By-1.0": [
49483         "Open Data Commons Attribution License v1.0",
49484         false,
49485         false
49486     ],
49487     "OFL-1.0": [
49488         "SIL Open Font License 1.0",
49489         false,
49490         false
49491     ],
49492     "OFL-1.1": [
49493         "SIL Open Font License 1.1",
49494         true,
49495         false
49496     ],
49497     "OGL-UK-1.0": [
49498         "Open Government Licence v1.0",
49499         false,
49500         false
49501     ],
49502     "OGL-UK-2.0": [
49503         "Open Government Licence v2.0",
49504         false,
49505         false
49506     ],
49507     "OGL-UK-3.0": [
49508         "Open Government Licence v3.0",
49509         false,
49510         false
49511     ],
49512     "OGTSL": [
49513         "Open Group Test Suite License",
49514         true,
49515         false
49516     ],
49517     "OLDAP-1.1": [
49518         "Open LDAP Public License v1.1",
49519         false,
49520         false
49521     ],
49522     "OLDAP-1.2": [
49523         "Open LDAP Public License v1.2",
49524         false,
49525         false
49526     ],
49527     "OLDAP-1.3": [
49528         "Open LDAP Public License v1.3",
49529         false,
49530         false
49531     ],
49532     "OLDAP-1.4": [
49533         "Open LDAP Public License v1.4",
49534         false,
49535         false
49536     ],
49537     "OLDAP-2.0": [
49538         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
49539         false,
49540         false
49541     ],
49542     "OLDAP-2.0.1": [
49543         "Open LDAP Public License v2.0.1",
49544         false,
49545         false
49546     ],
49547     "OLDAP-2.1": [
49548         "Open LDAP Public License v2.1",
49549         false,
49550         false
49551     ],
49552     "OLDAP-2.2": [
49553         "Open LDAP Public License v2.2",
49554         false,
49555         false
49556     ],
49557     "OLDAP-2.2.1": [
49558         "Open LDAP Public License v2.2.1",
49559         false,
49560         false
49561     ],
49562     "OLDAP-2.2.2": [
49563         "Open LDAP Public License 2.2.2",
49564         false,
49565         false
49566     ],
49567     "OLDAP-2.3": [
49568         "Open LDAP Public License v2.3",
49569         false,
49570         false
49571     ],
49572     "OLDAP-2.4": [
49573         "Open LDAP Public License v2.4",
49574         false,
49575         false
49576     ],
49577     "OLDAP-2.5": [
49578         "Open LDAP Public License v2.5",
49579         false,
49580         false
49581     ],
49582     "OLDAP-2.6": [
49583         "Open LDAP Public License v2.6",
49584         false,
49585         false
49586     ],
49587     "OLDAP-2.7": [
49588         "Open LDAP Public License v2.7",
49589         false,
49590         false
49591     ],
49592     "OLDAP-2.8": [
49593         "Open LDAP Public License v2.8",
49594         false,
49595         false
49596     ],
49597     "OML": [
49598         "Open Market License",
49599         false,
49600         false
49601     ],
49602     "OpenSSL": [
49603         "OpenSSL License",
49604         false,
49605         false
49606     ],
49607     "OPL-1.0": [
49608         "Open Public License v1.0",
49609         false,
49610         false
49611     ],
49612     "OSET-PL-2.1": [
49613         "OSET Public License version 2.1",
49614         true,
49615         false
49616     ],
49617     "OSL-1.0": [
49618         "Open Software License 1.0",
49619         true,
49620         false
49621     ],
49622     "OSL-1.1": [
49623         "Open Software License 1.1",
49624         false,
49625         false
49626     ],
49627     "OSL-2.0": [
49628         "Open Software License 2.0",
49629         true,
49630         false
49631     ],
49632     "OSL-2.1": [
49633         "Open Software License 2.1",
49634         true,
49635         false
49636     ],
49637     "OSL-3.0": [
49638         "Open Software License 3.0",
49639         true,
49640         false
49641     ],
49642     "Parity-6.0.0": [
49643         "The Parity Public License 6.0.0",
49644         false,
49645         false
49646     ],
49647     "PDDL-1.0": [
49648         "ODC Public Domain Dedication & License 1.0",
49649         false,
49650         false
49651     ],
49652     "PHP-3.0": [
49653         "PHP License v3.0",
49654         true,
49655         false
49656     ],
49657     "PHP-3.01": [
49658         "PHP License v3.01",
49659         false,
49660         false
49661     ],
49662     "Plexus": [
49663         "Plexus Classworlds License",
49664         false,
49665         false
49666     ],
49667     "PostgreSQL": [
49668         "PostgreSQL License",
49669         true,
49670         false
49671     ],
49672     "psfrag": [
49673         "psfrag License",
49674         false,
49675         false
49676     ],
49677     "psutils": [
49678         "psutils License",
49679         false,
49680         false
49681     ],
49682     "Python-2.0": [
49683         "Python License 2.0",
49684         true,
49685         false
49686     ],
49687     "Qhull": [
49688         "Qhull License",
49689         false,
49690         false
49691     ],
49692     "QPL-1.0": [
49693         "Q Public License 1.0",
49694         true,
49695         false
49696     ],
49697     "Rdisc": [
49698         "Rdisc License",
49699         false,
49700         false
49701     ],
49702     "RHeCos-1.1": [
49703         "Red Hat eCos Public License v1.1",
49704         false,
49705         false
49706     ],
49707     "RPL-1.1": [
49708         "Reciprocal Public License 1.1",
49709         true,
49710         false
49711     ],
49712     "RPL-1.5": [
49713         "Reciprocal Public License 1.5",
49714         true,
49715         false
49716     ],
49717     "RPSL-1.0": [
49718         "RealNetworks Public Source License v1.0",
49719         true,
49720         false
49721     ],
49722     "RSA-MD": [
49723         "RSA Message-Digest License",
49724         false,
49725         false
49726     ],
49727     "RSCPL": [
49728         "Ricoh Source Code Public License",
49729         true,
49730         false
49731     ],
49732     "Ruby": [
49733         "Ruby License",
49734         false,
49735         false
49736     ],
49737     "SAX-PD": [
49738         "Sax Public Domain Notice",
49739         false,
49740         false
49741     ],
49742     "Saxpath": [
49743         "Saxpath License",
49744         false,
49745         false
49746     ],
49747     "SCEA": [
49748         "SCEA Shared Source License",
49749         false,
49750         false
49751     ],
49752     "Sendmail": [
49753         "Sendmail License",
49754         false,
49755         false
49756     ],
49757     "Sendmail-8.23": [
49758         "Sendmail License 8.23",
49759         false,
49760         false
49761     ],
49762     "SGI-B-1.0": [
49763         "SGI Free Software License B v1.0",
49764         false,
49765         false
49766     ],
49767     "SGI-B-1.1": [
49768         "SGI Free Software License B v1.1",
49769         false,
49770         false
49771     ],
49772     "SGI-B-2.0": [
49773         "SGI Free Software License B v2.0",
49774         false,
49775         false
49776     ],
49777     "SHL-0.5": [
49778         "Solderpad Hardware License v0.5",
49779         false,
49780         false
49781     ],
49782     "SHL-0.51": [
49783         "Solderpad Hardware License, Version 0.51",
49784         false,
49785         false
49786     ],
49787     "SimPL-2.0": [
49788         "Simple Public License 2.0",
49789         true,
49790         false
49791     ],
49792     "SISSL": [
49793         "Sun Industry Standards Source License v1.1",
49794         true,
49795         false
49796     ],
49797     "SISSL-1.2": [
49798         "Sun Industry Standards Source License v1.2",
49799         false,
49800         false
49801     ],
49802     "Sleepycat": [
49803         "Sleepycat License",
49804         true,
49805         false
49806     ],
49807     "SMLNJ": [
49808         "Standard ML of New Jersey License",
49809         false,
49810         false
49811     ],
49812     "SMPPL": [
49813         "Secure Messaging Protocol Public License",
49814         false,
49815         false
49816     ],
49817     "SNIA": [
49818         "SNIA Public License 1.1",
49819         false,
49820         false
49821     ],
49822     "Spencer-86": [
49823         "Spencer License 86",
49824         false,
49825         false
49826     ],
49827     "Spencer-94": [
49828         "Spencer License 94",
49829         false,
49830         false
49831     ],
49832     "Spencer-99": [
49833         "Spencer License 99",
49834         false,
49835         false
49836     ],
49837     "SPL-1.0": [
49838         "Sun Public License v1.0",
49839         true,
49840         false
49841     ],
49842     "SSPL-1.0": [
49843         "Server Side Public License, v 1",
49844         false,
49845         false
49846     ],
49847     "StandardML-NJ": [
49848         "Standard ML of New Jersey License",
49849         false,
49850         true
49851     ],
49852     "SugarCRM-1.1.3": [
49853         "SugarCRM Public License v1.1.3",
49854         false,
49855         false
49856     ],
49857     "SWL": [
49858         "Scheme Widget Library (SWL) Software License Agreement",
49859         false,
49860         false
49861     ],
49862     "TAPR-OHL-1.0": [
49863         "TAPR Open Hardware License v1.0",
49864         false,
49865         false
49866     ],
49867     "TCL": [
49868         "TCL/TK License",
49869         false,
49870         false
49871     ],
49872     "TCP-wrappers": [
49873         "TCP Wrappers License",
49874         false,
49875         false
49876     ],
49877     "TMate": [
49878         "TMate Open Source License",
49879         false,
49880         false
49881     ],
49882     "TORQUE-1.1": [
49883         "TORQUE v2.5+ Software License v1.1",
49884         false,
49885         false
49886     ],
49887     "TOSL": [
49888         "Trusster Open Source License",
49889         false,
49890         false
49891     ],
49892     "TU-Berlin-1.0": [
49893         "Technische Universitaet Berlin License 1.0",
49894         false,
49895         false
49896     ],
49897     "TU-Berlin-2.0": [
49898         "Technische Universitaet Berlin License 2.0",
49899         false,
49900         false
49901     ],
49902     "Unicode-DFS-2015": [
49903         "Unicode License Agreement - Data Files and Software (2015)",
49904         false,
49905         false
49906     ],
49907     "Unicode-DFS-2016": [
49908         "Unicode License Agreement - Data Files and Software (2016)",
49909         false,
49910         false
49911     ],
49912     "Unicode-TOU": [
49913         "Unicode Terms of Use",
49914         false,
49915         false
49916     ],
49917     "Unlicense": [
49918         "The Unlicense",
49919         false,
49920         false
49921     ],
49922     "UPL-1.0": [
49923         "Universal Permissive License v1.0",
49924         true,
49925         false
49926     ],
49927     "Vim": [
49928         "Vim License",
49929         false,
49930         false
49931     ],
49932     "VOSTROM": [
49933         "VOSTROM Public License for Open Source",
49934         false,
49935         false
49936     ],
49937     "VSL-1.0": [
49938         "Vovida Software License v1.0",
49939         true,
49940         false
49941     ],
49942     "W3C": [
49943         "W3C Software Notice and License (2002-12-31)",
49944         true,
49945         false
49946     ],
49947     "W3C-19980720": [
49948         "W3C Software Notice and License (1998-07-20)",
49949         false,
49950         false
49951     ],
49952     "W3C-20150513": [
49953         "W3C Software Notice and Document License (2015-05-13)",
49954         false,
49955         false
49956     ],
49957     "Watcom-1.0": [
49958         "Sybase Open Watcom Public License 1.0",
49959         true,
49960         false
49961     ],
49962     "Wsuipa": [
49963         "Wsuipa License",
49964         false,
49965         false
49966     ],
49967     "WTFPL": [
49968         "Do What The F*ck You Want To Public License",
49969         false,
49970         false
49971     ],
49972     "wxWindows": [
49973         "wxWindows Library License",
49974         false,
49975         true
49976     ],
49977     "X11": [
49978         "X11 License",
49979         false,
49980         false
49981     ],
49982     "Xerox": [
49983         "Xerox License",
49984         false,
49985         false
49986     ],
49987     "XFree86-1.1": [
49988         "XFree86 License 1.1",
49989         false,
49990         false
49991     ],
49992     "xinetd": [
49993         "xinetd License",
49994         false,
49995         false
49996     ],
49997     "Xnet": [
49998         "X.Net License",
49999         true,
50000         false
50001     ],
50002     "xpp": [
50003         "XPP License",
50004         false,
50005         false
50006     ],
50007     "XSkat": [
50008         "XSkat License",
50009         false,
50010         false
50011     ],
50012     "YPL-1.0": [
50013         "Yahoo! Public License v1.0",
50014         false,
50015         false
50016     ],
50017     "YPL-1.1": [
50018         "Yahoo! Public License v1.1",
50019         false,
50020         false
50021     ],
50022     "Zed": [
50023         "Zed License",
50024         false,
50025         false
50026     ],
50027     "Zend-2.0": [
50028         "Zend License v2.0",
50029         false,
50030         false
50031     ],
50032     "Zimbra-1.3": [
50033         "Zimbra Public License v1.3",
50034         false,
50035         false
50036     ],
50037     "Zimbra-1.4": [
50038         "Zimbra Public License v1.4",
50039         false,
50040         false
50041     ],
50042     "Zlib": [
50043         "zlib License",
50044         true,
50045         false
50046     ],
50047     "zlib-acknowledgement": [
50048         "zlib/libpng License with Acknowledgement",
50049         false,
50050         false
50051     ],
50052     "ZPL-1.1": [
50053         "Zope Public License 1.1",
50054         false,
50055         false
50056     ],
50057     "ZPL-2.0": [
50058         "Zope Public License 2.0",
50059         true,
50060         false
50061     ],
50062     "ZPL-2.1": [
50063         "Zope Public License 2.1",
50064         false,
50065         false
50066     ]
50067 }MZ\90\0\ 3\0\0\0\ 4\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\ e\1fº\ e\0´ Í!¸\ 1LÍ!This program cannot be run in DOS mode.\r\r
50068 $\0\0\0\0\0\0\0\7fÆ,Í;§B\9e;§B\9e;§B\9e2ß×\9e:§B\9e2ßÁ\9e-§B\9e2ßÆ\9e9§B\9e2ßÑ\9e?§B\9e\1ca9\9e8§B\9e;§C\9e\b§B\9e2ßÈ\9e:§B\9e2ßÖ\9e:§B\9e2ßÓ\9e:§B\9eRich;§B\9e\0\0\0\0\0\0\0\0PE\0\0L\ 1\ 5\0¬MoO\0\0\0\0\0\0\0\0à\0\ 2\ 1\v\ 1      \0\0
50069 \0\0\0\16\0\0\0\0\0\08\13\0\0\0\10\0\0\0 \0\0\0\0@\0\0\10\0\0\0\ 2\0\0\ 5\0\0\0\0\0\0\0\ 5\0\0\0\0\0\0\0\0`\0\0\0\ 4\0\0?\9c\0\0\ 3\0@\81\0\0\10\0\0\10\0\0\0\0\10\0\0\10\0\0\0\0\0\0\10\0\0\0\0\0\0\0\0\0\0\0\90"\0\0P\0\0\0\0@\0\0 \ 6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0P\0\0p\ 1\0\0\0!\0\0\1c\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\08!\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.text\0\0\0\v     \0\0\0\10\0\0\0
50070 \0\0\0\ 4\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0`.rdata\0\0Π\0\0\0 \0\0\0
50071 \0\0\0\ e\0\0\0\0\0\0\0\0\0\0\0\0\0\0@\0\0@.data\0\0\0\90\ 3\0\0\00\0\0\0\ 2\0\0\0\18\0\0\0\0\0\0\0\0\0\0\0\0\0\0@\0\0À.rsrc\0\0\0 \ 6\0\0\0@\0\0\0\b\0\0\0\1a\0\0\0\0\0\0\0\0\0\0\0\0\0\0@\0\0@.reloc\0\0Ì\ 1\0\0\0P\0\0\0\ 2\0\0\0"\0\0\0\0\0\0\0\0\0\0\0\0\0\0@\0\0B\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\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\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\0j$¸æ\18@\0èx\b\0\0jöÿ\15\b @\0\83\0\8bð\8dEÐPVÿ\15\0 @\0\8b\83àûPVÿ\15\ 4 @\0\8dMÔÿ\15X @\0\83\0\8dEÔPÿ5H @\0ÿ\15L @\0YYÿ5\ @\0\8dEÔPÿ5` @\0ÿ\15D @\0YY\8bÈÿ\15P @\0\83Müÿ\8dMÔÿ\15T @\03ÀèH\b\0\0Ã;\r\00@\0u\ 2óÃé¬\ 2\0\0h\80\15@\0è£\ 4\0\0¡l3@\0Ç\ 4$40@\0ÿ5h3@\0£40@\0h$0@\0h(0@\0h 0@\0ÿ\15  @\0\83Ä\14£00@\0\85À}\bj\bè¹\ 3\0\0YÃj\10h\b"@\0è\1f\ 6\0\0\89]üd¡\18\0\0\0\8bp\ 4\89]ä¿\803@\0SVWÿ\150 @\0;Ãt\19;Æu\b3öF\89uäë\10\ 3\0\0ÿ\154 @\0ëÚ3öF¡|3@\0;Æu
50072 j\1fè\\ 3\0\0Yë;¡|3@\0\85Àu,\895|3@\0hð @\0hä @\0è§\ 5\0\0YY\85Àt\17ÇEüþÿÿÿ¸ÿ\0\0\0éÝ\0\0\0\895<0@\0¡|3@\0;Æu\ehà @\0hØ @\0èl\ 5\0\0YYÇ\ 5|3@\0\ 2\0\0\09]äu\bSWÿ\158 @\09\1d\8c3@\0t\19h\8c3@\0è\83\ 4\0\0Y\85Àt
50073 Sj\ 2Sÿ\15\8c3@\0¡$0@\0\8b\r¼ @\0\89\ 1ÿ5$0@\0ÿ5(0@\0ÿ5 0@\0è\10þÿÿ\83Ä\f£80@\09\1d,0@\0u7Pÿ\15À @\0\8b\8b\b\8b     \89MàPQè\8e\ 3\0\0YYÃ\8b\8bEà£80@\03Û9\1d,0@\0u\aPÿ\15h @\09\1d<0@\0u\ 6ÿ\15\9c @\0ÇEüþÿÿÿ¡80@\0èû\ 4\0\0øMZ\0\0f9\ 5\0\0@\0t\ 43ÀëM¡<\0@\0\8d\80\0\0@\0\818PE\0\0\ f·H\18\81ù\v\ 1\0\0t\e\81ù\v\ 2\0\0\83¸\84\0\0\0\ evÌ3É9\88ø\0\0\0ë\ e\83xt\ ev¼3É9\88è\0\0\0\ f\95Á\8bÁj\ 1£,0@\0ÿ\15p @\0jÿÿ\15l @\0YY£\843@\0£\883@\0ÿ\15Ì @\0\8b\rt3@\0\89\bÿ\15\88 @\0\8b\rp3@\0\89\b¡¨ @\0\8b\0£x3@\0èV\ 2\0\0è¬\ 4\0\0\83=\140@\0\0u\f\17@\0ÿ\15¬ @\0Yèg\ 4\0\0\83=\100@\0ÿu   jÿÿ\15° @\0Y3ÀÃè{\ 4\0\0é\9fýÿÿ\8bÿU\8bì\81ì(\ 3\0\0£H1@\0\89\rD1@\0\89\15@1@\0\89\1d<1@\0\89581@\0\89=41@\0f\8c\15`1@\0f\8c\rT1@\0f\8c\1d01@\0f\8c\ 5,1@\0f\8c%(1@\0f\8c-$1@\0\9c\8f\ 5X1@\0\8bE\0£L1@\0\8bE\ 4£P1@\0\8dE\b£\1@\0\8b\85àüÿÿÇ\ 5\980@\0\ 1\0\ 1\0¡P1@\0£L0@\0Ç\ 5@0@\0   \ 4\0ÀÇ\ 5D0@\0\ 1\0\0\0¡\00@\0\89\85Øüÿÿ¡\ 40@\0\89\85Üüÿÿÿ\15\1c @\0£\900@\0j\ 1è?\ 4\0\0Yj\0ÿ\15  @\0h\1c!@\0ÿ\15$ @\0\83=\900@\0\0u\bj\ 1è\e\ 4\0\0Yh     \ 4\0Àÿ\15( @\0Pÿ\15, @\0ÉÃ\8bÿU\8bì\8bE\b\8b\0\818csmàu*\83x\10\ 3u$\8b@\14\ 5\93\19t\15=!\ 5\93\19t\ e="\ 5\93\19t\a=\0@\99\ 1u\ 5èÐ\ 3\0\03À]Â\ 4\0hH\14@\0ÿ\15  @\03ÀÃÿ%¤ @\0j\14h("@\0èb\ 2\0\0ÿ5\883@\0\8b5\8c @\0ÿÖY\89\83øÿu\fÿu\bÿ\15Ä @\0Yëgj\bè\92\ 3\0\0Y\83\0ÿ5\883@\0ÿÖ\89Eäÿ5\843@\0ÿÖYY\89\8dEàP\8dEäPÿu\b\8b5l @\0ÿÖYPèU\ 3\0\0\89EÜÿuäÿÖ£\883@\0ÿuàÿÖ\83Ä\14£\843@\0ÇEüþÿÿÿè \0\0\0\8bEÜè\18\ 2\0\0Ãj\bè\19\ 3\0\0\8bÿU\8bìÿu\bèNÿÿÿ÷Ø\eÀ÷ØYH]Ã\8bÿV¸ü!@\0¾ü!@\0W\8bø;Æs\ f\8b\a\85Àt\ 2ÿÐ\83Ç\ 4;þrñ_^Ã\8bÿV¸\ 4"@\0¾\ 4"@\0W\8bø;Æs\ f\8b\a\85Àt\ 2ÿÐ\83Ç\ 4;þrñ_^Ãÿ%È @\0ÌÌÌÌ\8bÿU\8bì\8bM\b¸MZ\0\0f9\ 1t\ 43À]Ã\8bA<\ 3Á\818PE\0\0uï3Ò¹\v\ 1\0\0f9H\18\ f\94Â\8bÂ]ÃÌÌÌÌÌÌÌÌÌÌÌ\8bÿU\8bì\8bE\b\8bH<\ 3È\ f·A\14SV\ f·q\ 63ÒW\8dD\b\18\85öv\e\8b}\f\8bH\f;ùr   \8bX\b\ 3Ù;ûr
50074 B\83À(;Örè3À_^[]ÃÌÌÌÌÌÌÌÌÌÌÌÌ\8bÿU\8bìjþhH"@\0he\17@\0\0\0\0\0P\83ì\bSVW¡\00@\01Eø3ÅP\8dEðd£\0\0\0\0\89eèÇEü\0\0\0\0h\0\0@\0è*ÿÿÿ\83Ä\ 4\85ÀtU\8bE\b-\0\0@\0Ph\0\0@\0èPÿÿÿ\83Ä\b\85Àt;\8b@$Áè\1f÷Ð\83à\ 1ÇEüþÿÿÿ\8bMðd\89\r\0\0\0\0Y_^[\8bå]Ã\8b\8b\b\8b\ 13Ò=\ 5\0\0À\ f\94Â\8bÂÃ\8beèÇEüþÿÿÿ3À\8bMðd\89\r\0\0\0\0Y_^[\8bå]ÃÌÿ%¸ @\0ÿ%´ @\0ÌÌhe\17@\0dÿ5\0\0\0\0\8bD$\10\89l$\10\8dl$\10+àSVW¡\00@\01Eü3ÅP\89eèÿuø\8bEüÇEüþÿÿÿ\89\8dEðd£\0\0\0\0Ã\8bMðd\89\r\0\0\0\0Y__^[\8bå]QÃ\8bÿU\8bìÿu\14ÿu\10ÿu\fÿu\bh\87\10@\0h\00@\0èç\0\0\0\83Ä\18\8bÿVh\0\0\ 3\0h\0\0\ 1\03öVèÙ\0\0\0\83Ä\f\85Àt\rVVVVVèÂ\0\0\0\83Ä\14^Ã3ÀÃ\8bÿU\8bì\83ì\10¡\00@\0\83\0\83\0SW¿Næ@»»\0\0ÿÿ;Çt\r\85Ãt     ÷У\ 40@\0ë`V\8dEøPÿ\15< @\0\8buü3uøÿ\15\f @\03ðÿ\15\10 @\03ðÿ\15\14 @\0\8dEðPÿ\15\18 @\0\8bEô3Eð3ð;÷u\a¾Oæ@»ë\v\85óu\a\8bÆÁà\10\vð\895\00@\0÷Ö\895\ 40@\0^_[ÉÃÿ%t @\0ÿ%x @\0ÿ%| @\0ÿ%\80 @\0ÿ%\84 @\0ÿ%\90 @\0ÿ%\94 @\0ÿ%\98 @\0ÿ%Р@\0Pdÿ5\0\0\0\0\8dD$\f+d$\fSVW\89(\8bè¡\00@\03ÅP\89EðÿuüÇEüÿÿÿÿ\8dEôd£\0\0\0\0Ã\8bMôd\89\r\0\0\0\0Y__^[\8bå]QÃ\8bMð3Íè¯÷ÿÿéÝÿÿÿ\8dMÔÿ%T @\0\8bT$\b\8dB\f\8bJÌ3Èè\90÷ÿÿ\8bJü3Èè\86÷ÿÿ¸l"@\0ésÿÿÿ\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\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\0\0\0¸#\0\0Ê#\0\0Ü#\0\0\88)\0\0r)\0\0b)\0\0H)\0\04)\0\0\16)\0\0ú(\0\0æ(\0\0Ò(\0\0´(\0\0¬(\0\0\96(\0\0\9e)\0\0\0\0\0\0ú#\0\0à$\0\0\1a%\0\0Ê%\0\0\1a&\0\0d&\0\0®&\0\0¤$\0\0\0\0\0\0('\0\0Ä'\0\0Ö'\0\0è'\0\0þ'\0\0\1e(\0\0((\0\06(\0\0¦'\0\0H(\0\0Z(\0\0t(\0\0\86(\0\0\1e'\0\0\ e'\0\0\0'\0\0\96'\0\0\82'\0\0l'\0\0^'\0\0R'\0\0F'\0\0>'\0\0>(\0\00'\0\0¶'\0\0¸)\0\0\0\0\0\0\0\0\0\0\96\10@\0\0\0\0\0\0\0\0\0W\12@\0\8a\14@\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0¬MoO\0\0\0\0\ 2\0\0\0l\0\0\0\80!\0\0\80\ f\0\0@0@\0\980@\0bad allocation\0\0\0\0\0\0H\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\00@\0ð!@\0\ 2\0\0\0RSDSÑ\8c³\10´\8f\ 1J¨!öÌëLZ\0\ 1\0\0\0c:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdb\0\0\0\0\0e\17\0\0æ\18\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þÿÿÿ\a\12@\0\e\12@\0\0\0\0\0þÿÿÿ\0\0\0\0Ìÿÿÿ\0\0\0\0þÿÿÿ\0\0\0\0:\15@\0\0\0\0\0þÿÿÿ\0\0\0\0Øÿÿÿ\0\0\0\0þÿÿÿË\16@\0ß\16@\0ÿÿÿÿÝ\18@\0"\ 5\93\19\ 1\0\0\0d"@\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ 1\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\0H#\0\0\0\0\0\0\0\0\0\0\12(\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\88)\0\0r)\0\0b)\0\0H)\0\04)\0\0\16)\0\0ú(\0\0æ(\0\0Ò(\0\0´(\0\0¬(\0\0\96(\0\0\9e)\0\0\0\0\0\0ú#\0\0à$\0\0\1a%\0\0Ê%\0\0\1a&\0\0d&\0\0®&\0\0¤$\0\0\0\0\0\0('\0\0Ä'\0\0Ö'\0\0è'\0\0þ'\0\0\1e(\0\0((\0\06(\0\0¦'\0\0H(\0\0Z(\0\0t(\0\0\86(\0\0\1e'\0\0\ e'\0\0\0'\0\0\96'\0\0\82'\0\0l'\0\0^'\0\0R'\0\0F'\0\0>'\0\0>(\0\00'\0\0¶'\0\0¸)\0\0\0\0\0\0\95\ 1GetConsoleMode\0\0·\ 3SetConsoleMode\0\0;\ 2GetStdHandle\0\0KERNEL32.dll\0\0\16\0??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z\0\91\ 6?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A\0\0J\ 6?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A\0Â\0??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z\0\1d\ 3??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z\0\0_\ 2??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ\0\0{\ 1??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ\0\0³\a?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z\0\0MSVCP90.dll\0\15\ 1_amsg_exit\0\0\9f\0__getmainargs\0,\ 1_cexit\0\0|\ 1_exit\0f\0_XcptFilter\0Ì\ 4exit\0\0 \0__initenv\0\ 4\ 2_initterm\0\ 5\ 2_initterm_e\0<\ 1_configthreadlocale\0ã\0__setusermatherr\0\0\v\ 1_adjust_fdiv\0\0Ë\0__p__commode\0\0Ï\0__p__fmode\0\0j\ 1_encode_pointer\0à\0__set_app_type\0\0K\ 1_crt_debugger_hook\0\0C\0?terminate@@YAXXZ\0MSVCR90.dll\0æ\ 3_unlock\0\96\0__dllonexit\0v\ 2_lock\0\1c\ 3_onexit\0`\ 1_decode_pointer\0s\ 1_except_handler4_common\0\v\ 2_invoke_watson\0\0?\ 1_controlfp_s\0\0½\ 2InterlockedExchange\0!\ 4Sleep\0º\ 2InterlockedCompareExchange\0\0-\ 4TerminateProcess\0\0©\ 1GetCurrentProcess\0>\ 4UnhandledExceptionFilter\0\0\15\ 4SetUnhandledExceptionFilter\0Ñ\ 2IsDebuggerPresent\0T\ 3QueryPerformanceCounter\0f\ 2GetTickCount\0\0­\ 1GetCurrentThreadId\0\0ª\ 1GetCurrentProcessId\0O\ 2GetSystemTimeAsFileTime\0s\0__CxxFrameHandler3\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\0Næ@»±\19¿Dÿÿÿÿÿÿÿÿþÿÿÿ\ 1\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\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\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\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\0\0\0\0\0\0\0\0\0\0\0\0\ 4\0\0\0\0\0\ 2\0\10\0\0\0 \0\0\80\18\0\0\08\0\0\80\0\0\0\0\0\0\0\0\ 4\0\0\0\0\0\ 1\0\ 1\0\0\0P\0\0\80\0\0\0\0\0\0\0\0\ 4\0\0\0\0\0\ 1\0\ 1\0\0\0h\0\0\80\0\0\0\0\0\0\0\0\ 4\0\0\0\0\0\ 1\0 \ 4\0\0\80\0\0\0\0\0\0\0\0\0\0\0\ 4\0\0\0\0\0\ 1\0 \ 4\0\0\90\0\0\0 @\0\0(\ 3\0\0ä\ 4\0\0\0\0\0\0ÈC\0\0V\ 2\0\0ä\ 4\0\0\0\0\0\0(\ 34\0\0\0V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0\0\0\0½\ 4ïþ\0\0\ 1\0\0\0\ 1\0\0\0\0\0\0\0\ 1\0\0\0\0\0\17\0\0\0\0\0\0\0\ 4\0\0\0\ 1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\86\ 2\0\0\ 1\0S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0b\ 2\0\0\ 1\00\04\00\09\00\04\0b\00\0\0\0Ê\0Q\0\ 1\0F\0i\0l\0e\0D\0e\0s\0c\0r\0i\0p\0t\0i\0o\0n\0\0\0\0\0R\0e\0a\0d\0s\0 \0f\0r\0o\0m\0 \0s\0t\0d\0i\0n\0 \0w\0i\0t\0h\0o\0u\0t\0 \0l\0e\0a\0k\0i\0n\0g\0 \0i\0n\0f\0o\0 \0t\0o\0 \0t\0h\0e\0 \0t\0e\0r\0m\0i\0n\0a\0l\0 \0a\0n\0d\0 \0o\0u\0t\0p\0u\0t\0s\0 \0b\0a\0c\0k\0 \0t\0o\0 \0s\0t\0d\0o\0u\0t\0\0\0\0\06\0\v\0\ 1\0F\0i\0l\0e\0V\0e\0r\0s\0i\0o\0n\0\0\0\0\01\0,\0 \00\0,\0 \00\0,\0 \00\0\0\0\0\08\0\f\0\ 1\0I\0n\0t\0e\0r\0n\0a\0l\0N\0a\0m\0e\0\0\0h\0i\0d\0d\0e\0n\0i\0n\0p\0u\0t\0\0\0P\0\16\0\ 1\0L\0e\0g\0a\0l\0C\0o\0p\0y\0r\0i\0g\0h\0t\0\0\0J\0o\0r\0d\0i\0 \0B\0o\0g\0g\0i\0a\0n\0o\0 \0-\0 \02\00\01\02\0\0\0H\0\10\0\ 1\0O\0r\0i\0g\0i\0n\0a\0l\0F\0i\0l\0e\0n\0a\0m\0e\0\0\0h\0i\0d\0d\0e\0n\0i\0n\0p\0u\0t\0.\0e\0x\0e\0\0\0:\0\r\0\ 1\0P\0r\0o\0d\0u\0c\0t\0N\0a\0m\0e\0\0\0\0\0H\0i\0d\0d\0e\0n\0 \0I\0n\0p\0u\0t\0\0\0\0\0:\0\v\0\ 1\0P\0r\0o\0d\0u\0c\0t\0V\0e\0r\0s\0i\0o\0n\0\0\01\0,\0 \00\0,\0 \00\0,\0 \00\0\0\0\0\0D\0\0\0\ 1\0V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0\0\0$\0\ 4\0\0\0T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0\0\0\0     \ 4°\ 4<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\r
50075   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
50076     <security>\r
50077       <requestedPrivileges>\r
50078         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
50079       </requestedPrivileges>\r
50080     </security>\r
50081   </trustInfo>\r
50082   <dependency>\r
50083     <dependentAssembly>\r
50084       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
50085     </dependentAssembly>\r
50086   </dependency>\r
50087 </assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING\0\10\0\0@\ 1\0\0\ 30\100!0/080F0L0T0^0d0n0{0\890\970¡0¨0®0³0¸0½0Â0È0Ð0ä0ÿ0\b1#1-1@1J1O1T1v1{1\841\891\961§1­1´1È1Í1Ó1Û1á1ç1ô1ú1\ 32"2*23292A2M2_2j2p2¹2¿2Ç2Î2Ó2Ù2ß2ç2í2ô2û2\v3\133\193%303N3T3Z3`3f3l3s3z3\813\883\8f3\963\9d3¥3­3µ3Á3Ê3Ï3Õ3ß3è3ó3ÿ3\ 44\144\194\1f4%4;4B4\8b4\914\9a4¡4¬4²4Æ4Û4æ4þ4\145!5^5c5\845\895¨5H6M6_6}6\916\976\07\ 67\r7*7w7|7Á7ä7ñ7ý7\ 58\r8\198=8E8P8V8\8b8h8n8t8z8\808\9c8â8\ 29\0\0\0 \0\0$\0\0\0Ü0è0ì0\1c1 1t1x1\1c2 2@2\2`2h2t2\00\0\0\f\0\0\0\180\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\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<?php
50088
50089
50090
50091
50092
50093
50094
50095
50096
50097
50098 namespace Symfony\Component\Console;
50099
50100 use Symfony\Component\Console\Command\Command;
50101 use Symfony\Component\Console\Command\HelpCommand;
50102 use Symfony\Component\Console\Command\ListCommand;
50103 use Symfony\Component\Console\Descriptor\TextDescriptor;
50104 use Symfony\Component\Console\Descriptor\XmlDescriptor;
50105 use Symfony\Component\Console\Event\ConsoleCommandEvent;
50106 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
50107 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
50108 use Symfony\Component\Console\Exception\CommandNotFoundException;
50109 use Symfony\Component\Console\Exception\ExceptionInterface;
50110 use Symfony\Component\Console\Exception\LogicException;
50111 use Symfony\Component\Console\Formatter\OutputFormatter;
50112 use Symfony\Component\Console\Helper\DebugFormatterHelper;
50113 use Symfony\Component\Console\Helper\DialogHelper;
50114 use Symfony\Component\Console\Helper\FormatterHelper;
50115 use Symfony\Component\Console\Helper\Helper;
50116 use Symfony\Component\Console\Helper\HelperSet;
50117 use Symfony\Component\Console\Helper\ProcessHelper;
50118 use Symfony\Component\Console\Helper\ProgressHelper;
50119 use Symfony\Component\Console\Helper\QuestionHelper;
50120 use Symfony\Component\Console\Helper\TableHelper;
50121 use Symfony\Component\Console\Input\ArgvInput;
50122 use Symfony\Component\Console\Input\ArrayInput;
50123 use Symfony\Component\Console\Input\InputArgument;
50124 use Symfony\Component\Console\Input\InputAwareInterface;
50125 use Symfony\Component\Console\Input\InputDefinition;
50126 use Symfony\Component\Console\Input\InputInterface;
50127 use Symfony\Component\Console\Input\InputOption;
50128 use Symfony\Component\Console\Output\BufferedOutput;
50129 use Symfony\Component\Console\Output\ConsoleOutput;
50130 use Symfony\Component\Console\Output\ConsoleOutputInterface;
50131 use Symfony\Component\Console\Output\OutputInterface;
50132 use Symfony\Component\Debug\Exception\FatalThrowableError;
50133 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
50134
50135
50136
50137
50138
50139
50140
50141
50142
50143
50144
50145
50146
50147
50148
50149
50150 class Application
50151 {
50152 private $commands = array();
50153 private $wantHelps = false;
50154 private $runningCommand;
50155 private $name;
50156 private $version;
50157 private $catchExceptions = true;
50158 private $autoExit = true;
50159 private $definition;
50160 private $helperSet;
50161 private $dispatcher;
50162 private $terminalDimensions;
50163 private $defaultCommand;
50164 private $initialized;
50165
50166
50167
50168
50169
50170 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
50171 {
50172 $this->name = $name;
50173 $this->version = $version;
50174 $this->defaultCommand = 'list';
50175 }
50176
50177 public function setDispatcher(EventDispatcherInterface $dispatcher)
50178 {
50179 $this->dispatcher = $dispatcher;
50180 }
50181
50182
50183
50184
50185
50186
50187
50188
50189 public function run(InputInterface $input = null, OutputInterface $output = null)
50190 {
50191 if (null === $input) {
50192 $input = new ArgvInput();
50193 }
50194
50195 if (null === $output) {
50196 $output = new ConsoleOutput();
50197 }
50198
50199 $this->configureIO($input, $output);
50200
50201 try {
50202 $e = null;
50203 $exitCode = $this->doRun($input, $output);
50204 } catch (\Exception $e) {
50205 }
50206
50207 if (null !== $e) {
50208 if (!$this->catchExceptions) {
50209 throw $e;
50210 }
50211
50212 if ($output instanceof ConsoleOutputInterface) {
50213 $this->renderException($e, $output->getErrorOutput());
50214 } else {
50215 $this->renderException($e, $output);
50216 }
50217
50218 $exitCode = $this->getExitCodeForThrowable($e);
50219 }
50220
50221 if ($this->autoExit) {
50222 if ($exitCode > 255) {
50223 $exitCode = 255;
50224 }
50225
50226 exit($exitCode);
50227 }
50228
50229 return $exitCode;
50230 }
50231
50232
50233
50234
50235
50236
50237 public function doRun(InputInterface $input, OutputInterface $output)
50238 {
50239 if (true === $input->hasParameterOption(array('--version', '-V'))) {
50240 $output->writeln($this->getLongVersion());
50241
50242 return 0;
50243 }
50244
50245 $name = $this->getCommandName($input);
50246 if (true === $input->hasParameterOption(array('--help', '-h'))) {
50247 if (!$name) {
50248 $name = 'help';
50249 $input = new ArrayInput(array('command' => 'help'));
50250 } else {
50251 $this->wantHelps = true;
50252 }
50253 }
50254
50255 if (!$name) {
50256 $name = $this->defaultCommand;
50257 $definition = $this->getDefinition();
50258 $definition->setArguments(array_merge(
50259 $definition->getArguments(),
50260 array(
50261 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
50262 )
50263 ));
50264 }
50265
50266 $this->runningCommand = null;
50267
50268  $command = $this->find($name);
50269
50270 $this->runningCommand = $command;
50271 $exitCode = $this->doRunCommand($command, $input, $output);
50272 $this->runningCommand = null;
50273
50274 return $exitCode;
50275 }
50276
50277 public function setHelperSet(HelperSet $helperSet)
50278 {
50279 $this->helperSet = $helperSet;
50280 }
50281
50282
50283
50284
50285
50286
50287 public function getHelperSet()
50288 {
50289 if (!$this->helperSet) {
50290 $this->helperSet = $this->getDefaultHelperSet();
50291 }
50292
50293 return $this->helperSet;
50294 }
50295
50296 public function setDefinition(InputDefinition $definition)
50297 {
50298 $this->definition = $definition;
50299 }
50300
50301
50302
50303
50304
50305
50306 public function getDefinition()
50307 {
50308 if (!$this->definition) {
50309 $this->definition = $this->getDefaultInputDefinition();
50310 }
50311
50312 return $this->definition;
50313 }
50314
50315
50316
50317
50318
50319
50320 public function getHelp()
50321 {
50322 return $this->getLongVersion();
50323 }
50324
50325
50326
50327
50328
50329
50330 public function setCatchExceptions($boolean)
50331 {
50332 $this->catchExceptions = (bool) $boolean;
50333 }
50334
50335
50336
50337
50338
50339
50340 public function setAutoExit($boolean)
50341 {
50342 $this->autoExit = (bool) $boolean;
50343 }
50344
50345
50346
50347
50348
50349
50350 public function getName()
50351 {
50352 return $this->name;
50353 }
50354
50355
50356
50357
50358
50359
50360 public function setName($name)
50361 {
50362 $this->name = $name;
50363 }
50364
50365
50366
50367
50368
50369
50370 public function getVersion()
50371 {
50372 return $this->version;
50373 }
50374
50375
50376
50377
50378
50379
50380 public function setVersion($version)
50381 {
50382 $this->version = $version;
50383 }
50384
50385
50386
50387
50388
50389
50390 public function getLongVersion()
50391 {
50392 if ('UNKNOWN' !== $this->getName()) {
50393 if ('UNKNOWN' !== $this->getVersion()) {
50394 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
50395 }
50396
50397 return sprintf('<info>%s</info>', $this->getName());
50398 }
50399
50400 return '<info>Console Tool</info>';
50401 }
50402
50403
50404
50405
50406
50407
50408
50409
50410 public function register($name)
50411 {
50412 return $this->add(new Command($name));
50413 }
50414
50415
50416
50417
50418
50419
50420
50421
50422 public function addCommands(array $commands)
50423 {
50424 foreach ($commands as $command) {
50425 $this->add($command);
50426 }
50427 }
50428
50429
50430
50431
50432
50433
50434
50435
50436
50437 public function add(Command $command)
50438 {
50439 $this->init();
50440
50441 $command->setApplication($this);
50442
50443 if (!$command->isEnabled()) {
50444 $command->setApplication(null);
50445
50446 return;
50447 }
50448
50449 if (null === $command->getDefinition()) {
50450 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($command)));
50451 }
50452
50453 $this->commands[$command->getName()] = $command;
50454
50455 foreach ($command->getAliases() as $alias) {
50456 $this->commands[$alias] = $command;
50457 }
50458
50459 return $command;
50460 }
50461
50462
50463
50464
50465
50466
50467
50468
50469
50470
50471 public function get($name)
50472 {
50473 $this->init();
50474
50475 if (!isset($this->commands[$name])) {
50476 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
50477 }
50478
50479 $command = $this->commands[$name];
50480
50481 if ($this->wantHelps) {
50482 $this->wantHelps = false;
50483
50484 $helpCommand = $this->get('help');
50485 $helpCommand->setCommand($command);
50486
50487 return $helpCommand;
50488 }
50489
50490 return $command;
50491 }
50492
50493
50494
50495
50496
50497
50498
50499
50500 public function has($name)
50501 {
50502 $this->init();
50503
50504 return isset($this->commands[$name]);
50505 }
50506
50507
50508
50509
50510
50511
50512
50513
50514 public function getNamespaces()
50515 {
50516 $namespaces = array();
50517 foreach ($this->all() as $command) {
50518 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
50519
50520 foreach ($command->getAliases() as $alias) {
50521 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
50522 }
50523 }
50524
50525 return array_values(array_unique(array_filter($namespaces)));
50526 }
50527
50528
50529
50530
50531
50532
50533
50534
50535
50536
50537 public function findNamespace($namespace)
50538 {
50539 $allNamespaces = $this->getNamespaces();
50540 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
50541 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
50542
50543 if (empty($namespaces)) {
50544 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
50545
50546 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
50547 if (1 == \count($alternatives)) {
50548 $message .= "\n\nDid you mean this?\n    ";
50549 } else {
50550 $message .= "\n\nDid you mean one of these?\n    ";
50551 }
50552
50553 $message .= implode("\n    ", $alternatives);
50554 }
50555
50556 throw new CommandNotFoundException($message, $alternatives);
50557 }
50558
50559 $exact = \in_array($namespace, $namespaces, true);
50560 if (\count($namespaces) > 1 && !$exact) {
50561 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
50562 }
50563
50564 return $exact ? $namespace : reset($namespaces);
50565 }
50566
50567
50568
50569
50570
50571
50572
50573
50574
50575
50576
50577
50578
50579 public function find($name)
50580 {
50581 $this->init();
50582 $aliases = array();
50583 $allCommands = array_keys($this->commands);
50584 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
50585 $commands = preg_grep('{^'.$expr.'}', $allCommands);
50586
50587 if (empty($commands) || \count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
50588 if (false !== $pos = strrpos($name, ':')) {
50589
50590  $this->findNamespace(substr($name, 0, $pos));
50591 }
50592
50593 $message = sprintf('Command "%s" is not defined.', $name);
50594
50595 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
50596 if (1 == \count($alternatives)) {
50597 $message .= "\n\nDid you mean this?\n    ";
50598 } else {
50599 $message .= "\n\nDid you mean one of these?\n    ";
50600 }
50601 $message .= implode("\n    ", $alternatives);
50602 }
50603
50604 throw new CommandNotFoundException($message, $alternatives);
50605 }
50606
50607
50608  if (\count($commands) > 1) {
50609 $commandList = $this->commands;
50610 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
50611 $commandName = $commandList[$nameOrAlias]->getName();
50612 $aliases[$nameOrAlias] = $commandName;
50613
50614 return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
50615 });
50616 }
50617
50618 $exact = \in_array($name, $commands, true) || isset($aliases[$name]);
50619 if (!$exact && \count($commands) > 1) {
50620 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
50621
50622 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
50623 }
50624
50625 return $this->get($exact ? $name : reset($commands));
50626 }
50627
50628
50629
50630
50631
50632
50633
50634
50635
50636
50637 public function all($namespace = null)
50638 {
50639 $this->init();
50640
50641 if (null === $namespace) {
50642 return $this->commands;
50643 }
50644
50645 $commands = array();
50646 foreach ($this->commands as $name => $command) {
50647 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
50648 $commands[$name] = $command;
50649 }
50650 }
50651
50652 return $commands;
50653 }
50654
50655
50656
50657
50658
50659
50660
50661
50662 public static function getAbbreviations($names)
50663 {
50664 $abbrevs = array();
50665 foreach ($names as $name) {
50666 for ($len = \strlen($name); $len > 0; --$len) {
50667 $abbrev = substr($name, 0, $len);
50668 $abbrevs[$abbrev][] = $name;
50669 }
50670 }
50671
50672 return $abbrevs;
50673 }
50674
50675
50676
50677
50678
50679
50680
50681
50682
50683
50684
50685 public function asText($namespace = null, $raw = false)
50686 {
50687 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
50688
50689 $descriptor = new TextDescriptor();
50690 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
50691 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
50692
50693 return $output->fetch();
50694 }
50695
50696
50697
50698
50699
50700
50701
50702
50703
50704
50705
50706 public function asXml($namespace = null, $asDom = false)
50707 {
50708 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
50709
50710 $descriptor = new XmlDescriptor();
50711
50712 if ($asDom) {
50713 return $descriptor->getApplicationDocument($this, $namespace);
50714 }
50715
50716 $output = new BufferedOutput();
50717 $descriptor->describe($output, $this, array('namespace' => $namespace));
50718
50719 return $output->fetch();
50720 }
50721
50722
50723
50724
50725 public function renderException($e, $output)
50726 {
50727 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
50728
50729 do {
50730 $title = sprintf('  [%s]  ', \get_class($e));
50731
50732 $len = Helper::strlen($title);
50733
50734 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
50735
50736  if (\defined('HHVM_VERSION') && $width > 1 << 31) {
50737 $width = 1 << 31;
50738 }
50739 $lines = array();
50740 foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) {
50741 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
50742
50743  $lineLength = Helper::strlen($line) + 4;
50744 $lines[] = array($line, $lineLength);
50745
50746 $len = max($lineLength, $len);
50747 }
50748 }
50749
50750 $messages = array();
50751 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
50752 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
50753 foreach ($lines as $line) {
50754 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
50755 }
50756 $messages[] = $emptyLine;
50757 $messages[] = '';
50758
50759 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
50760
50761 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
50762 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
50763
50764
50765  $trace = $e->getTrace();
50766 array_unshift($trace, array(
50767 'function' => '',
50768 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a',
50769 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a',
50770 'args' => array(),
50771 ));
50772
50773 for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
50774 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
50775 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
50776 $function = $trace[$i]['function'];
50777 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
50778 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
50779
50780 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
50781 }
50782
50783 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
50784 }
50785 } while ($e = $e->getPrevious());
50786
50787 if (null !== $this->runningCommand) {
50788 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
50789 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
50790 }
50791 }
50792
50793
50794
50795
50796
50797
50798 protected function getTerminalWidth()
50799 {
50800 $dimensions = $this->getTerminalDimensions();
50801
50802 return $dimensions[0];
50803 }
50804
50805
50806
50807
50808
50809
50810 protected function getTerminalHeight()
50811 {
50812 $dimensions = $this->getTerminalDimensions();
50813
50814 return $dimensions[1];
50815 }
50816
50817
50818
50819
50820
50821
50822 public function getTerminalDimensions()
50823 {
50824 if ($this->terminalDimensions) {
50825 return $this->terminalDimensions;
50826 }
50827
50828 if ('\\' === \DIRECTORY_SEPARATOR) {
50829
50830  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
50831 return array((int) $matches[1], (int) $matches[2]);
50832 }
50833
50834  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
50835 return array((int) $matches[1], (int) $matches[2]);
50836 }
50837 }
50838
50839 if ($sttyString = $this->getSttyColumns()) {
50840
50841  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
50842 return array((int) $matches[2], (int) $matches[1]);
50843 }
50844
50845  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
50846 return array((int) $matches[2], (int) $matches[1]);
50847 }
50848 }
50849
50850 return array(null, null);
50851 }
50852
50853
50854
50855
50856
50857
50858
50859
50860
50861
50862
50863 public function setTerminalDimensions($width, $height)
50864 {
50865 $this->terminalDimensions = array($width, $height);
50866
50867 return $this;
50868 }
50869
50870
50871
50872
50873 protected function configureIO(InputInterface $input, OutputInterface $output)
50874 {
50875 if (true === $input->hasParameterOption(array('--ansi'))) {
50876 $output->setDecorated(true);
50877 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
50878 $output->setDecorated(false);
50879 }
50880
50881 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
50882 $input->setInteractive(false);
50883 } elseif (\function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
50884 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
50885 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
50886 $input->setInteractive(false);
50887 }
50888 }
50889
50890 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
50891 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
50892 $input->setInteractive(false);
50893 } else {
50894 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) {
50895 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
50896 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) {
50897 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
50898 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
50899 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
50900 }
50901 }
50902 }
50903
50904
50905
50906
50907
50908
50909
50910
50911
50912 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
50913 {
50914 foreach ($command->getHelperSet() as $helper) {
50915 if ($helper instanceof InputAwareInterface) {
50916 $helper->setInput($input);
50917 }
50918 }
50919
50920 if (null === $this->dispatcher) {
50921 return $command->run($input, $output);
50922 }
50923
50924
50925  try {
50926 $command->mergeApplicationDefinition();
50927 $input->bind($command->getDefinition());
50928 } catch (ExceptionInterface $e) {
50929
50930  }
50931
50932 $event = new ConsoleCommandEvent($command, $input, $output);
50933 $e = null;
50934
50935 try {
50936 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
50937
50938 if ($event->commandShouldRun()) {
50939 $exitCode = $command->run($input, $output);
50940 } else {
50941 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
50942 }
50943 } catch (\Exception $e) {
50944 } catch (\Throwable $e) {
50945 }
50946 if (null !== $e) {
50947 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
50948 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
50949 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
50950
50951 if ($x !== $event->getException()) {
50952 $e = $event->getException();
50953 }
50954
50955 $exitCode = $this->getExitCodeForThrowable($e);
50956 }
50957
50958 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
50959 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
50960
50961 if (null !== $e) {
50962 throw $e;
50963 }
50964
50965 return $event->getExitCode();
50966 }
50967
50968
50969
50970
50971
50972
50973 protected function getCommandName(InputInterface $input)
50974 {
50975 return $input->getFirstArgument();
50976 }
50977
50978
50979
50980
50981
50982
50983 protected function getDefaultInputDefinition()
50984 {
50985 return new InputDefinition(array(
50986 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
50987
50988 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
50989 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
50990 new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
50991 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
50992 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
50993 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
50994 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
50995 ));
50996 }
50997
50998
50999
51000
51001
51002
51003 protected function getDefaultCommands()
51004 {
51005 return array(new HelpCommand(), new ListCommand());
51006 }
51007
51008
51009
51010
51011
51012
51013 protected function getDefaultHelperSet()
51014 {
51015 return new HelperSet(array(
51016 new FormatterHelper(),
51017 new DialogHelper(false),
51018 new ProgressHelper(false),
51019 new TableHelper(false),
51020 new DebugFormatterHelper(),
51021 new ProcessHelper(),
51022 new QuestionHelper(),
51023 ));
51024 }
51025
51026
51027
51028
51029
51030
51031 private function getSttyColumns()
51032 {
51033 if (!\function_exists('proc_open')) {
51034 return;
51035 }
51036
51037 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
51038 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
51039 if (\is_resource($process)) {
51040 $info = stream_get_contents($pipes[1]);
51041 fclose($pipes[1]);
51042 fclose($pipes[2]);
51043 proc_close($process);
51044
51045 return $info;
51046 }
51047 }
51048
51049
51050
51051
51052
51053
51054 private function getConsoleMode()
51055 {
51056 if (!\function_exists('proc_open')) {
51057 return;
51058 }
51059
51060 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
51061 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
51062 if (\is_resource($process)) {
51063 $info = stream_get_contents($pipes[1]);
51064 fclose($pipes[1]);
51065 fclose($pipes[2]);
51066 proc_close($process);
51067
51068 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
51069 return $matches[2].'x'.$matches[1];
51070 }
51071 }
51072 }
51073
51074
51075
51076
51077
51078
51079
51080
51081 private function getAbbreviationSuggestions($abbrevs)
51082 {
51083 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], \count($abbrevs) > 2 ? sprintf(' and %d more', \count($abbrevs) - 2) : '');
51084 }
51085
51086
51087
51088
51089
51090
51091
51092
51093
51094
51095
51096 public function extractNamespace($name, $limit = null)
51097 {
51098 $parts = explode(':', $name);
51099 array_pop($parts);
51100
51101 return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
51102 }
51103
51104
51105
51106
51107
51108
51109
51110
51111
51112
51113 private function findAlternatives($name, $collection)
51114 {
51115 $threshold = 1e3;
51116 $alternatives = array();
51117
51118 $collectionParts = array();
51119 foreach ($collection as $item) {
51120 $collectionParts[$item] = explode(':', $item);
51121 }
51122
51123 foreach (explode(':', $name) as $i => $subname) {
51124 foreach ($collectionParts as $collectionName => $parts) {
51125 $exists = isset($alternatives[$collectionName]);
51126 if (!isset($parts[$i]) && $exists) {
51127 $alternatives[$collectionName] += $threshold;
51128 continue;
51129 } elseif (!isset($parts[$i])) {
51130 continue;
51131 }
51132
51133 $lev = levenshtein($subname, $parts[$i]);
51134 if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
51135 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
51136 } elseif ($exists) {
51137 $alternatives[$collectionName] += $threshold;
51138 }
51139 }
51140 }
51141
51142 foreach ($collection as $item) {
51143 $lev = levenshtein($name, $item);
51144 if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) {
51145 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
51146 }
51147 }
51148
51149 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
51150 asort($alternatives);
51151
51152 return array_keys($alternatives);
51153 }
51154
51155
51156
51157
51158
51159
51160 public function setDefaultCommand($commandName)
51161 {
51162 $this->defaultCommand = $commandName;
51163 }
51164
51165 private function splitStringByWidth($string, $width)
51166 {
51167
51168  
51169  
51170  if (false === $encoding = mb_detect_encoding($string, null, true)) {
51171 return str_split($string, $width);
51172 }
51173
51174 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
51175 $lines = array();
51176 $line = '';
51177 foreach (preg_split('//u', $utf8String) as $char) {
51178
51179  if (mb_strwidth($line.$char, 'utf8') <= $width) {
51180 $line .= $char;
51181 continue;
51182 }
51183
51184  $lines[] = str_pad($line, $width);
51185 $line = $char;
51186 }
51187
51188 $lines[] = \count($lines) ? str_pad($line, $width) : $line;
51189
51190 mb_convert_variables($encoding, 'utf8', $lines);
51191
51192 return $lines;
51193 }
51194
51195
51196
51197
51198
51199
51200
51201
51202 private function extractAllNamespaces($name)
51203 {
51204
51205  $parts = explode(':', $name, -1);
51206 $namespaces = array();
51207
51208 foreach ($parts as $part) {
51209 if (\count($namespaces)) {
51210 $namespaces[] = end($namespaces).':'.$part;
51211 } else {
51212 $namespaces[] = $part;
51213 }
51214 }
51215
51216 return $namespaces;
51217 }
51218
51219 private function init()
51220 {
51221 if ($this->initialized) {
51222 return;
51223 }
51224 $this->initialized = true;
51225
51226 foreach ($this->getDefaultCommands() as $command) {
51227 $this->add($command);
51228 }
51229 }
51230
51231
51232
51233
51234
51235
51236 private function getExitCodeForThrowable($throwable)
51237 {
51238 $exitCode = $throwable->getCode();
51239 if (is_numeric($exitCode)) {
51240 $exitCode = (int) $exitCode;
51241 if (0 === $exitCode) {
51242 $exitCode = 1;
51243 }
51244 } else {
51245 $exitCode = 1;
51246 }
51247
51248 return $exitCode;
51249 }
51250 }
51251 <?php
51252
51253
51254
51255
51256
51257
51258
51259
51260
51261
51262 namespace Symfony\Component\Console\Command;
51263
51264 use Symfony\Component\Console\Application;
51265 use Symfony\Component\Console\Descriptor\TextDescriptor;
51266 use Symfony\Component\Console\Descriptor\XmlDescriptor;
51267 use Symfony\Component\Console\Exception\ExceptionInterface;
51268 use Symfony\Component\Console\Exception\InvalidArgumentException;
51269 use Symfony\Component\Console\Exception\LogicException;
51270 use Symfony\Component\Console\Helper\HelperSet;
51271 use Symfony\Component\Console\Input\InputArgument;
51272 use Symfony\Component\Console\Input\InputDefinition;
51273 use Symfony\Component\Console\Input\InputInterface;
51274 use Symfony\Component\Console\Input\InputOption;
51275 use Symfony\Component\Console\Output\BufferedOutput;
51276 use Symfony\Component\Console\Output\OutputInterface;
51277
51278
51279
51280
51281
51282
51283 class Command
51284 {
51285 private $application;
51286 private $name;
51287 private $processTitle;
51288 private $aliases = array();
51289 private $definition;
51290 private $help;
51291 private $description;
51292 private $ignoreValidationErrors = false;
51293 private $applicationDefinitionMerged = false;
51294 private $applicationDefinitionMergedWithArgs = false;
51295 private $code;
51296 private $synopsis = array();
51297 private $usages = array();
51298 private $helperSet;
51299
51300
51301
51302
51303
51304
51305 public function __construct($name = null)
51306 {
51307 $this->definition = new InputDefinition();
51308
51309 if (null !== $name) {
51310 $this->setName($name);
51311 }
51312
51313 $this->configure();
51314
51315 if (!$this->name) {
51316 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($this)));
51317 }
51318 }
51319
51320
51321
51322
51323
51324
51325 public function ignoreValidationErrors()
51326 {
51327 $this->ignoreValidationErrors = true;
51328 }
51329
51330 public function setApplication(Application $application = null)
51331 {
51332 $this->application = $application;
51333 if ($application) {
51334 $this->setHelperSet($application->getHelperSet());
51335 } else {
51336 $this->helperSet = null;
51337 }
51338 }
51339
51340 public function setHelperSet(HelperSet $helperSet)
51341 {
51342 $this->helperSet = $helperSet;
51343 }
51344
51345
51346
51347
51348
51349
51350 public function getHelperSet()
51351 {
51352 return $this->helperSet;
51353 }
51354
51355
51356
51357
51358
51359
51360 public function getApplication()
51361 {
51362 return $this->application;
51363 }
51364
51365
51366
51367
51368
51369
51370
51371
51372
51373 public function isEnabled()
51374 {
51375 return true;
51376 }
51377
51378
51379
51380
51381 protected function configure()
51382 {
51383 }
51384
51385
51386
51387
51388
51389
51390
51391
51392
51393
51394
51395
51396
51397
51398
51399 protected function execute(InputInterface $input, OutputInterface $output)
51400 {
51401 throw new LogicException('You must override the execute() method in the concrete command class.');
51402 }
51403
51404
51405
51406
51407
51408
51409
51410
51411 protected function interact(InputInterface $input, OutputInterface $output)
51412 {
51413 }
51414
51415
51416
51417
51418
51419
51420
51421
51422
51423
51424
51425 protected function initialize(InputInterface $input, OutputInterface $output)
51426 {
51427 }
51428
51429
51430
51431
51432
51433
51434
51435
51436
51437
51438
51439
51440
51441
51442
51443 public function run(InputInterface $input, OutputInterface $output)
51444 {
51445
51446  $this->getSynopsis(true);
51447 $this->getSynopsis(false);
51448
51449
51450  $this->mergeApplicationDefinition();
51451
51452
51453  try {
51454 $input->bind($this->definition);
51455 } catch (ExceptionInterface $e) {
51456 if (!$this->ignoreValidationErrors) {
51457 throw $e;
51458 }
51459 }
51460
51461 $this->initialize($input, $output);
51462
51463 if (null !== $this->processTitle) {
51464 if (\function_exists('cli_set_process_title')) {
51465 if (!@cli_set_process_title($this->processTitle)) {
51466 if ('Darwin' === PHP_OS) {
51467 $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
51468 } else {
51469 cli_set_process_title($this->processTitle);
51470 }
51471 }
51472 } elseif (\function_exists('setproctitle')) {
51473 setproctitle($this->processTitle);
51474 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
51475 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
51476 }
51477 }
51478
51479 if ($input->isInteractive()) {
51480 $this->interact($input, $output);
51481 }
51482
51483
51484  
51485  
51486  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
51487 $input->setArgument('command', $this->getName());
51488 }
51489
51490 $input->validate();
51491
51492 if ($this->code) {
51493 $statusCode = \call_user_func($this->code, $input, $output);
51494 } else {
51495 $statusCode = $this->execute($input, $output);
51496 }
51497
51498 return is_numeric($statusCode) ? (int) $statusCode : 0;
51499 }
51500
51501
51502
51503
51504
51505
51506
51507
51508
51509
51510
51511
51512
51513
51514
51515 public function setCode($code)
51516 {
51517 if (!\is_callable($code)) {
51518 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
51519 }
51520
51521 if (\PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
51522 $r = new \ReflectionFunction($code);
51523 if (null === $r->getClosureThis()) {
51524 if (\PHP_VERSION_ID < 70000) {
51525
51526  
51527  
51528  
51529  $code = @\Closure::bind($code, $this);
51530 } else {
51531 $code = \Closure::bind($code, $this);
51532 }
51533 }
51534 }
51535
51536 $this->code = $code;
51537
51538 return $this;
51539 }
51540
51541
51542
51543
51544
51545
51546
51547
51548 public function mergeApplicationDefinition($mergeArgs = true)
51549 {
51550 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
51551 return;
51552 }
51553
51554 $this->definition->addOptions($this->application->getDefinition()->getOptions());
51555
51556 $this->applicationDefinitionMerged = true;
51557
51558 if ($mergeArgs) {
51559 $currentArguments = $this->definition->getArguments();
51560 $this->definition->setArguments($this->application->getDefinition()->getArguments());
51561 $this->definition->addArguments($currentArguments);
51562
51563 $this->applicationDefinitionMergedWithArgs = true;
51564 }
51565 }
51566
51567
51568
51569
51570
51571
51572
51573
51574 public function setDefinition($definition)
51575 {
51576 if ($definition instanceof InputDefinition) {
51577 $this->definition = $definition;
51578 } else {
51579 $this->definition->setDefinition($definition);
51580 }
51581
51582 $this->applicationDefinitionMerged = false;
51583
51584 return $this;
51585 }
51586
51587
51588
51589
51590
51591
51592 public function getDefinition()
51593 {
51594 return $this->definition;
51595 }
51596
51597
51598
51599
51600
51601
51602
51603
51604
51605
51606
51607 public function getNativeDefinition()
51608 {
51609 return $this->getDefinition();
51610 }
51611
51612
51613
51614
51615
51616
51617
51618
51619
51620
51621
51622
51623
51624 public function addArgument($name, $mode = null, $description = '', $default = null)
51625 {
51626 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
51627
51628 return $this;
51629 }
51630
51631
51632
51633
51634
51635
51636
51637
51638
51639
51640
51641
51642
51643
51644 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
51645 {
51646 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
51647
51648 return $this;
51649 }
51650
51651
51652
51653
51654
51655
51656
51657
51658
51659
51660
51661
51662
51663
51664
51665 public function setName($name)
51666 {
51667 $this->validateName($name);
51668
51669 $this->name = $name;
51670
51671 return $this;
51672 }
51673
51674
51675
51676
51677
51678
51679
51680
51681
51682
51683
51684
51685
51686 public function setProcessTitle($title)
51687 {
51688 $this->processTitle = $title;
51689
51690 return $this;
51691 }
51692
51693
51694
51695
51696
51697
51698 public function getName()
51699 {
51700 return $this->name;
51701 }
51702
51703
51704
51705
51706
51707
51708
51709
51710 public function setDescription($description)
51711 {
51712 $this->description = $description;
51713
51714 return $this;
51715 }
51716
51717
51718
51719
51720
51721
51722 public function getDescription()
51723 {
51724 return $this->description;
51725 }
51726
51727
51728
51729
51730
51731
51732
51733
51734 public function setHelp($help)
51735 {
51736 $this->help = $help;
51737
51738 return $this;
51739 }
51740
51741
51742
51743
51744
51745
51746 public function getHelp()
51747 {
51748 return $this->help;
51749 }
51750
51751
51752
51753
51754
51755
51756
51757 public function getProcessedHelp()
51758 {
51759 $name = $this->name;
51760
51761 $placeholders = array(
51762 '%command.name%',
51763 '%command.full_name%',
51764 );
51765 $replacements = array(
51766 $name,
51767 $_SERVER['PHP_SELF'].' '.$name,
51768 );
51769
51770 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
51771 }
51772
51773
51774
51775
51776
51777
51778
51779
51780
51781
51782 public function setAliases($aliases)
51783 {
51784 if (!\is_array($aliases) && !$aliases instanceof \Traversable) {
51785 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
51786 }
51787
51788 foreach ($aliases as $alias) {
51789 $this->validateName($alias);
51790 }
51791
51792 $this->aliases = $aliases;
51793
51794 return $this;
51795 }
51796
51797
51798
51799
51800
51801
51802 public function getAliases()
51803 {
51804 return $this->aliases;
51805 }
51806
51807
51808
51809
51810
51811
51812
51813
51814 public function getSynopsis($short = false)
51815 {
51816 $key = $short ? 'short' : 'long';
51817
51818 if (!isset($this->synopsis[$key])) {
51819 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
51820 }
51821
51822 return $this->synopsis[$key];
51823 }
51824
51825
51826
51827
51828
51829
51830
51831
51832 public function addUsage($usage)
51833 {
51834 if (0 !== strpos($usage, $this->name)) {
51835 $usage = sprintf('%s %s', $this->name, $usage);
51836 }
51837
51838 $this->usages[] = $usage;
51839
51840 return $this;
51841 }
51842
51843
51844
51845
51846
51847
51848 public function getUsages()
51849 {
51850 return $this->usages;
51851 }
51852
51853
51854
51855
51856
51857
51858
51859
51860
51861
51862
51863 public function getHelper($name)
51864 {
51865 if (null === $this->helperSet) {
51866 throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
51867 }
51868
51869 return $this->helperSet->get($name);
51870 }
51871
51872
51873
51874
51875
51876
51877
51878
51879 public function asText()
51880 {
51881 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
51882
51883 $descriptor = new TextDescriptor();
51884 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
51885 $descriptor->describe($output, $this, array('raw_output' => true));
51886
51887 return $output->fetch();
51888 }
51889
51890
51891
51892
51893
51894
51895
51896
51897
51898
51899 public function asXml($asDom = false)
51900 {
51901 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
51902
51903 $descriptor = new XmlDescriptor();
51904
51905 if ($asDom) {
51906 return $descriptor->getCommandDocument($this);
51907 }
51908
51909 $output = new BufferedOutput();
51910 $descriptor->describe($output, $this);
51911
51912 return $output->fetch();
51913 }
51914
51915
51916
51917
51918
51919
51920
51921
51922
51923
51924 private function validateName($name)
51925 {
51926 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
51927 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
51928 }
51929 }
51930 }
51931 <?php
51932
51933
51934
51935
51936
51937
51938
51939
51940
51941
51942 namespace Symfony\Component\Console\Command;
51943
51944 use Symfony\Component\Console\Helper\DescriptorHelper;
51945 use Symfony\Component\Console\Input\InputArgument;
51946 use Symfony\Component\Console\Input\InputInterface;
51947 use Symfony\Component\Console\Input\InputOption;
51948 use Symfony\Component\Console\Output\OutputInterface;
51949
51950
51951
51952
51953
51954
51955 class HelpCommand extends Command
51956 {
51957 private $command;
51958
51959
51960
51961
51962 protected function configure()
51963 {
51964 $this->ignoreValidationErrors();
51965
51966 $this
51967 ->setName('help')
51968 ->setDefinition(array(
51969 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
51970 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
51971 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
51972 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
51973 ))
51974 ->setDescription('Displays help for a command')
51975 ->setHelp(<<<'EOF'
51976 The <info>%command.name%</info> command displays help for a given command:
51977
51978   <info>php %command.full_name% list</info>
51979
51980 You can also output the help in other formats by using the <comment>--format</comment> option:
51981
51982   <info>php %command.full_name% --format=xml list</info>
51983
51984 To display the list of available commands, please use the <info>list</info> command.
51985 EOF
51986 )
51987 ;
51988 }
51989
51990 public function setCommand(Command $command)
51991 {
51992 $this->command = $command;
51993 }
51994
51995
51996
51997
51998 protected function execute(InputInterface $input, OutputInterface $output)
51999 {
52000 if (null === $this->command) {
52001 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
52002 }
52003
52004 if ($input->getOption('xml')) {
52005 @trigger_error('The --xml option was deprecated in version 2.7 and will be removed in version 3.0. Use the --format option instead.', E_USER_DEPRECATED);
52006
52007 $input->setOption('format', 'xml');
52008 }
52009
52010 $helper = new DescriptorHelper();
52011 $helper->describe($output, $this->command, array(
52012 'format' => $input->getOption('format'),
52013 'raw_text' => $input->getOption('raw'),
52014 ));
52015
52016 $this->command = null;
52017 }
52018 }
52019 <?php
52020
52021
52022
52023
52024
52025
52026
52027
52028
52029
52030 namespace Symfony\Component\Console\Command;
52031
52032 use Symfony\Component\Console\Helper\DescriptorHelper;
52033 use Symfony\Component\Console\Input\InputArgument;
52034 use Symfony\Component\Console\Input\InputDefinition;
52035 use Symfony\Component\Console\Input\InputInterface;
52036 use Symfony\Component\Console\Input\InputOption;
52037 use Symfony\Component\Console\Output\OutputInterface;
52038
52039
52040
52041
52042
52043
52044 class ListCommand extends Command
52045 {
52046
52047
52048
52049 protected function configure()
52050 {
52051 $this
52052 ->setName('list')
52053 ->setDefinition($this->createDefinition())
52054 ->setDescription('Lists commands')
52055 ->setHelp(<<<'EOF'
52056 The <info>%command.name%</info> command lists all commands:
52057
52058   <info>php %command.full_name%</info>
52059
52060 You can also display the commands for a specific namespace:
52061
52062   <info>php %command.full_name% test</info>
52063
52064 You can also output the information in other formats by using the <comment>--format</comment> option:
52065
52066   <info>php %command.full_name% --format=xml</info>
52067
52068 It's also possible to get raw list of commands (useful for embedding command runner):
52069
52070   <info>php %command.full_name% --raw</info>
52071 EOF
52072 )
52073 ;
52074 }
52075
52076
52077
52078
52079 public function getNativeDefinition()
52080 {
52081 return $this->createDefinition();
52082 }
52083
52084
52085
52086
52087 protected function execute(InputInterface $input, OutputInterface $output)
52088 {
52089 if ($input->getOption('xml')) {
52090 @trigger_error('The --xml option was deprecated in version 2.7 and will be removed in version 3.0. Use the --format option instead.', E_USER_DEPRECATED);
52091
52092 $input->setOption('format', 'xml');
52093 }
52094
52095 $helper = new DescriptorHelper();
52096 $helper->describe($output, $this->getApplication(), array(
52097 'format' => $input->getOption('format'),
52098 'raw_text' => $input->getOption('raw'),
52099 'namespace' => $input->getArgument('namespace'),
52100 ));
52101 }
52102
52103
52104
52105
52106 private function createDefinition()
52107 {
52108 return new InputDefinition(array(
52109 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
52110 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
52111 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
52112 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
52113 ));
52114 }
52115 }
52116 <?php
52117
52118
52119
52120
52121
52122
52123
52124
52125
52126
52127 namespace Symfony\Component\Console;
52128
52129
52130
52131
52132
52133
52134 final class ConsoleEvents
52135 {
52136
52137
52138
52139
52140
52141
52142
52143
52144
52145
52146 const COMMAND = 'console.command';
52147
52148
52149
52150
52151
52152
52153
52154
52155
52156
52157 const TERMINATE = 'console.terminate';
52158
52159
52160
52161
52162
52163
52164
52165
52166
52167
52168
52169 const EXCEPTION = 'console.exception';
52170 }
52171 <?php
52172
52173
52174
52175
52176
52177
52178
52179
52180
52181
52182 namespace Symfony\Component\Console\Descriptor;
52183
52184 use Symfony\Component\Console\Application;
52185 use Symfony\Component\Console\Command\Command;
52186 use Symfony\Component\Console\Exception\CommandNotFoundException;
52187
52188
52189
52190
52191
52192
52193 class ApplicationDescription
52194 {
52195 const GLOBAL_NAMESPACE = '_global';
52196
52197 private $application;
52198 private $namespace;
52199
52200
52201
52202
52203 private $namespaces;
52204
52205
52206
52207
52208 private $commands;
52209
52210
52211
52212
52213 private $aliases;
52214
52215 public function __construct(Application $application, $namespace = null)
52216 {
52217 $this->application = $application;
52218 $this->namespace = $namespace;
52219 }
52220
52221
52222
52223
52224 public function getNamespaces()
52225 {
52226 if (null === $this->namespaces) {
52227 $this->inspectApplication();
52228 }
52229
52230 return $this->namespaces;
52231 }
52232
52233
52234
52235
52236 public function getCommands()
52237 {
52238 if (null === $this->commands) {
52239 $this->inspectApplication();
52240 }
52241
52242 return $this->commands;
52243 }
52244
52245
52246
52247
52248
52249
52250
52251
52252 public function getCommand($name)
52253 {
52254 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
52255 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
52256 }
52257
52258 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
52259 }
52260
52261 private function inspectApplication()
52262 {
52263 $this->commands = array();
52264 $this->namespaces = array();
52265
52266 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
52267 foreach ($this->sortCommands($all) as $namespace => $commands) {
52268 $names = array();
52269
52270
52271 foreach ($commands as $name => $command) {
52272 if (!$command->getName()) {
52273 continue;
52274 }
52275
52276 if ($command->getName() === $name) {
52277 $this->commands[$name] = $command;
52278 } else {
52279 $this->aliases[$name] = $command;
52280 }
52281
52282 $names[] = $name;
52283 }
52284
52285 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
52286 }
52287 }
52288
52289
52290
52291
52292 private function sortCommands(array $commands)
52293 {
52294 $namespacedCommands = array();
52295 $globalCommands = array();
52296 foreach ($commands as $name => $command) {
52297 $key = $this->application->extractNamespace($name, 1);
52298 if (!$key) {
52299 $globalCommands['_global'][$name] = $command;
52300 } else {
52301 $namespacedCommands[$key][$name] = $command;
52302 }
52303 }
52304 ksort($namespacedCommands);
52305 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
52306
52307 foreach ($namespacedCommands as &$commandsSet) {
52308 ksort($commandsSet);
52309 }
52310
52311  unset($commandsSet);
52312
52313 return $namespacedCommands;
52314 }
52315 }
52316 <?php
52317
52318
52319
52320
52321
52322
52323
52324
52325
52326
52327 namespace Symfony\Component\Console\Descriptor;
52328
52329 use Symfony\Component\Console\Application;
52330 use Symfony\Component\Console\Command\Command;
52331 use Symfony\Component\Console\Exception\InvalidArgumentException;
52332 use Symfony\Component\Console\Input\InputArgument;
52333 use Symfony\Component\Console\Input\InputDefinition;
52334 use Symfony\Component\Console\Input\InputOption;
52335 use Symfony\Component\Console\Output\OutputInterface;
52336
52337
52338
52339
52340
52341
52342 abstract class Descriptor implements DescriptorInterface
52343 {
52344
52345
52346
52347 private $output;
52348
52349
52350
52351
52352 public function describe(OutputInterface $output, $object, array $options = array())
52353 {
52354 $this->output = $output;
52355
52356 switch (true) {
52357 case $object instanceof InputArgument:
52358 $this->describeInputArgument($object, $options);
52359 break;
52360 case $object instanceof InputOption:
52361 $this->describeInputOption($object, $options);
52362 break;
52363 case $object instanceof InputDefinition:
52364 $this->describeInputDefinition($object, $options);
52365 break;
52366 case $object instanceof Command:
52367 $this->describeCommand($object, $options);
52368 break;
52369 case $object instanceof Application:
52370 $this->describeApplication($object, $options);
52371 break;
52372 default:
52373 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object)));
52374 }
52375 }
52376
52377
52378
52379
52380
52381
52382
52383 protected function write($content, $decorated = false)
52384 {
52385 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
52386 }
52387
52388
52389
52390
52391
52392
52393 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
52394
52395
52396
52397
52398
52399
52400 abstract protected function describeInputOption(InputOption $option, array $options = array());
52401
52402
52403
52404
52405
52406
52407 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
52408
52409
52410
52411
52412
52413
52414 abstract protected function describeCommand(Command $command, array $options = array());
52415
52416
52417
52418
52419
52420
52421 abstract protected function describeApplication(Application $application, array $options = array());
52422 }
52423 <?php
52424
52425
52426
52427
52428
52429
52430
52431
52432
52433
52434 namespace Symfony\Component\Console\Descriptor;
52435
52436 use Symfony\Component\Console\Output\OutputInterface;
52437
52438
52439
52440
52441
52442
52443 interface DescriptorInterface
52444 {
52445
52446
52447
52448
52449
52450
52451
52452 public function describe(OutputInterface $output, $object, array $options = array());
52453 }
52454 <?php
52455
52456
52457
52458
52459
52460
52461
52462
52463
52464
52465 namespace Symfony\Component\Console\Descriptor;
52466
52467 use Symfony\Component\Console\Application;
52468 use Symfony\Component\Console\Command\Command;
52469 use Symfony\Component\Console\Input\InputArgument;
52470 use Symfony\Component\Console\Input\InputDefinition;
52471 use Symfony\Component\Console\Input\InputOption;
52472
52473
52474
52475
52476
52477
52478
52479
52480 class JsonDescriptor extends Descriptor
52481 {
52482
52483
52484
52485 protected function describeInputArgument(InputArgument $argument, array $options = array())
52486 {
52487 $this->writeData($this->getInputArgumentData($argument), $options);
52488 }
52489
52490
52491
52492
52493 protected function describeInputOption(InputOption $option, array $options = array())
52494 {
52495 $this->writeData($this->getInputOptionData($option), $options);
52496 }
52497
52498
52499
52500
52501 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
52502 {
52503 $this->writeData($this->getInputDefinitionData($definition), $options);
52504 }
52505
52506
52507
52508
52509 protected function describeCommand(Command $command, array $options = array())
52510 {
52511 $this->writeData($this->getCommandData($command), $options);
52512 }
52513
52514
52515
52516
52517 protected function describeApplication(Application $application, array $options = array())
52518 {
52519 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
52520 $description = new ApplicationDescription($application, $describedNamespace);
52521 $commands = array();
52522
52523 foreach ($description->getCommands() as $command) {
52524 $commands[] = $this->getCommandData($command);
52525 }
52526
52527 $data = $describedNamespace
52528 ? array('commands' => $commands, 'namespace' => $describedNamespace)
52529 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
52530
52531 $this->writeData($data, $options);
52532 }
52533
52534
52535
52536
52537
52538
52539 private function writeData(array $data, array $options)
52540 {
52541 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
52542 }
52543
52544
52545
52546
52547 private function getInputArgumentData(InputArgument $argument)
52548 {
52549 return array(
52550 'name' => $argument->getName(),
52551 'is_required' => $argument->isRequired(),
52552 'is_array' => $argument->isArray(),
52553 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
52554 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
52555 );
52556 }
52557
52558
52559
52560
52561 private function getInputOptionData(InputOption $option)
52562 {
52563 return array(
52564 'name' => '--'.$option->getName(),
52565 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
52566 'accept_value' => $option->acceptValue(),
52567 'is_value_required' => $option->isValueRequired(),
52568 'is_multiple' => $option->isArray(),
52569 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
52570 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
52571 );
52572 }
52573
52574
52575
52576
52577 private function getInputDefinitionData(InputDefinition $definition)
52578 {
52579 $inputArguments = array();
52580 foreach ($definition->getArguments() as $name => $argument) {
52581 $inputArguments[$name] = $this->getInputArgumentData($argument);
52582 }
52583
52584 $inputOptions = array();
52585 foreach ($definition->getOptions() as $name => $option) {
52586 $inputOptions[$name] = $this->getInputOptionData($option);
52587 }
52588
52589 return array('arguments' => $inputArguments, 'options' => $inputOptions);
52590 }
52591
52592
52593
52594
52595 private function getCommandData(Command $command)
52596 {
52597 $command->getSynopsis();
52598 $command->mergeApplicationDefinition(false);
52599
52600 return array(
52601 'name' => $command->getName(),
52602 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
52603 'description' => $command->getDescription(),
52604 'help' => $command->getProcessedHelp(),
52605 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
52606 );
52607 }
52608 }
52609 <?php
52610
52611
52612
52613
52614
52615
52616
52617
52618
52619
52620 namespace Symfony\Component\Console\Descriptor;
52621
52622 use Symfony\Component\Console\Application;
52623 use Symfony\Component\Console\Command\Command;
52624 use Symfony\Component\Console\Helper\Helper;
52625 use Symfony\Component\Console\Input\InputArgument;
52626 use Symfony\Component\Console\Input\InputDefinition;
52627 use Symfony\Component\Console\Input\InputOption;
52628
52629
52630
52631
52632
52633
52634
52635
52636 class MarkdownDescriptor extends Descriptor
52637 {
52638
52639
52640
52641 protected function describeInputArgument(InputArgument $argument, array $options = array())
52642 {
52643 $this->write(
52644 '**'.$argument->getName().':**'."\n\n"
52645 .'* Name: '.($argument->getName() ?: '<none>')."\n"
52646 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
52647 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
52648 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
52649 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
52650 );
52651 }
52652
52653
52654
52655
52656 protected function describeInputOption(InputOption $option, array $options = array())
52657 {
52658 $this->write(
52659 '**'.$option->getName().':**'."\n\n"
52660 .'* Name: `--'.$option->getName().'`'."\n"
52661 .'* Shortcut: '.($option->getShortcut() ? '`-'.str_replace('|', '|-', $option->getShortcut()).'`' : '<none>')."\n"
52662 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
52663 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
52664 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
52665 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
52666 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
52667 );
52668 }
52669
52670
52671
52672
52673 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
52674 {
52675 if ($showArguments = \count($definition->getArguments()) > 0) {
52676 $this->write('### Arguments:');
52677 foreach ($definition->getArguments() as $argument) {
52678 $this->write("\n\n");
52679 $this->write($this->describeInputArgument($argument));
52680 }
52681 }
52682
52683 if (\count($definition->getOptions()) > 0) {
52684 if ($showArguments) {
52685 $this->write("\n\n");
52686 }
52687
52688 $this->write('### Options:');
52689 foreach ($definition->getOptions() as $option) {
52690 $this->write("\n\n");
52691 $this->write($this->describeInputOption($option));
52692 }
52693 }
52694 }
52695
52696
52697
52698
52699 protected function describeCommand(Command $command, array $options = array())
52700 {
52701 $command->getSynopsis();
52702 $command->mergeApplicationDefinition(false);
52703
52704 $this->write(
52705 $command->getName()."\n"
52706 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
52707 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
52708 .'* Usage:'."\n\n"
52709 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
52710 return $carry.'  * `'.$usage.'`'."\n";
52711 })
52712 );
52713
52714 if ($help = $command->getProcessedHelp()) {
52715 $this->write("\n");
52716 $this->write($help);
52717 }
52718
52719 if ($command->getNativeDefinition()) {
52720 $this->write("\n\n");
52721 $this->describeInputDefinition($command->getNativeDefinition());
52722 }
52723 }
52724
52725
52726
52727
52728 protected function describeApplication(Application $application, array $options = array())
52729 {
52730 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
52731 $description = new ApplicationDescription($application, $describedNamespace);
52732
52733 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
52734
52735 foreach ($description->getNamespaces() as $namespace) {
52736 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
52737 $this->write("\n\n");
52738 $this->write('**'.$namespace['id'].':**');
52739 }
52740
52741 $this->write("\n\n");
52742 $this->write(implode("\n", array_map(function ($commandName) {
52743 return '* '.$commandName;
52744 }, $namespace['commands'])));
52745 }
52746
52747 foreach ($description->getCommands() as $command) {
52748 $this->write("\n\n");
52749 $this->write($this->describeCommand($command));
52750 }
52751 }
52752 }
52753 <?php
52754
52755
52756
52757
52758
52759
52760
52761
52762
52763
52764 namespace Symfony\Component\Console\Descriptor;
52765
52766 use Symfony\Component\Console\Application;
52767 use Symfony\Component\Console\Command\Command;
52768 use Symfony\Component\Console\Formatter\OutputFormatter;
52769 use Symfony\Component\Console\Helper\Helper;
52770 use Symfony\Component\Console\Input\InputArgument;
52771 use Symfony\Component\Console\Input\InputDefinition;
52772 use Symfony\Component\Console\Input\InputOption;
52773
52774
52775
52776
52777
52778
52779
52780
52781 class TextDescriptor extends Descriptor
52782 {
52783
52784
52785
52786 protected function describeInputArgument(InputArgument $argument, array $options = array())
52787 {
52788 if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
52789 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
52790 } else {
52791 $default = '';
52792 }
52793
52794 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
52795 $spacingWidth = $totalWidth - \strlen($argument->getName());
52796
52797 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
52798 $argument->getName(),
52799 str_repeat(' ', $spacingWidth),
52800
52801  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
52802 $default
52803 ), $options);
52804 }
52805
52806
52807
52808
52809 protected function describeInputOption(InputOption $option, array $options = array())
52810 {
52811 if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
52812 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
52813 } else {
52814 $default = '';
52815 }
52816
52817 $value = '';
52818 if ($option->acceptValue()) {
52819 $value = '='.strtoupper($option->getName());
52820
52821 if ($option->isValueOptional()) {
52822 $value = '['.$value.']';
52823 }
52824 }
52825
52826 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
52827 $synopsis = sprintf('%s%s',
52828 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
52829 sprintf('--%s%s', $option->getName(), $value)
52830 );
52831
52832 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
52833
52834 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
52835 $synopsis,
52836 str_repeat(' ', $spacingWidth),
52837
52838  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
52839 $default,
52840 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
52841 ), $options);
52842 }
52843
52844
52845
52846
52847 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
52848 {
52849 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
52850 foreach ($definition->getArguments() as $argument) {
52851 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
52852 }
52853
52854 if ($definition->getArguments()) {
52855 $this->writeText('<comment>Arguments:</comment>', $options);
52856 $this->writeText("\n");
52857 foreach ($definition->getArguments() as $argument) {
52858 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
52859 $this->writeText("\n");
52860 }
52861 }
52862
52863 if ($definition->getArguments() && $definition->getOptions()) {
52864 $this->writeText("\n");
52865 }
52866
52867 if ($definition->getOptions()) {
52868 $laterOptions = array();
52869
52870 $this->writeText('<comment>Options:</comment>', $options);
52871 foreach ($definition->getOptions() as $option) {
52872 if (\strlen($option->getShortcut()) > 1) {
52873 $laterOptions[] = $option;
52874 continue;
52875 }
52876 $this->writeText("\n");
52877 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
52878 }
52879 foreach ($laterOptions as $option) {
52880 $this->writeText("\n");
52881 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
52882 }
52883 }
52884 }
52885
52886
52887
52888
52889 protected function describeCommand(Command $command, array $options = array())
52890 {
52891 $command->getSynopsis(true);
52892 $command->getSynopsis(false);
52893 $command->mergeApplicationDefinition(false);
52894
52895 $this->writeText('<comment>Usage:</comment>', $options);
52896 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
52897 $this->writeText("\n");
52898 $this->writeText('  '.OutputFormatter::escape($usage), $options);
52899 }
52900 $this->writeText("\n");
52901
52902 $definition = $command->getNativeDefinition();
52903 if ($definition->getOptions() || $definition->getArguments()) {
52904 $this->writeText("\n");
52905 $this->describeInputDefinition($definition, $options);
52906 $this->writeText("\n");
52907 }
52908
52909 if ($help = $command->getProcessedHelp()) {
52910 $this->writeText("\n");
52911 $this->writeText('<comment>Help:</comment>', $options);
52912 $this->writeText("\n");
52913 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
52914 $this->writeText("\n");
52915 }
52916 }
52917
52918
52919
52920
52921 protected function describeApplication(Application $application, array $options = array())
52922 {
52923 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
52924 $description = new ApplicationDescription($application, $describedNamespace);
52925
52926 if (isset($options['raw_text']) && $options['raw_text']) {
52927 $width = $this->getColumnWidth($description->getCommands());
52928
52929 foreach ($description->getCommands() as $command) {
52930 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
52931 $this->writeText("\n");
52932 }
52933 } else {
52934 if ('' != $help = $application->getHelp()) {
52935 $this->writeText("$help\n\n", $options);
52936 }
52937
52938 $this->writeText("<comment>Usage:</comment>\n", $options);
52939 $this->writeText("  command [options] [arguments]\n\n", $options);
52940
52941 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
52942
52943 $this->writeText("\n");
52944 $this->writeText("\n");
52945
52946 $width = $this->getColumnWidth($description->getCommands());
52947
52948 if ($describedNamespace) {
52949 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
52950 } else {
52951 $this->writeText('<comment>Available commands:</comment>', $options);
52952 }
52953
52954
52955  foreach ($description->getNamespaces() as $namespace) {
52956 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
52957 $this->writeText("\n");
52958 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
52959 }
52960
52961 foreach ($namespace['commands'] as $name) {
52962 $this->writeText("\n");
52963 $spacingWidth = $width - Helper::strlen($name);
52964 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
52965 }
52966 }
52967
52968 $this->writeText("\n");
52969 }
52970 }
52971
52972
52973
52974
52975 private function writeText($content, array $options = array())
52976 {
52977 $this->write(
52978 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
52979 isset($options['raw_output']) ? !$options['raw_output'] : true
52980 );
52981 }
52982
52983
52984
52985
52986
52987
52988
52989
52990 private function formatDefaultValue($default)
52991 {
52992 if (INF === $default) {
52993 return 'INF';
52994 }
52995
52996 if (\is_string($default)) {
52997 $default = OutputFormatter::escape($default);
52998 } elseif (\is_array($default)) {
52999 foreach ($default as $key => $value) {
53000 if (\is_string($value)) {
53001 $default[$key] = OutputFormatter::escape($value);
53002 }
53003 }
53004 }
53005
53006 if (\PHP_VERSION_ID < 50400) {
53007 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
53008 }
53009
53010 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
53011 }
53012
53013
53014
53015
53016
53017
53018 private function getColumnWidth(array $commands)
53019 {
53020 $widths = array();
53021
53022 foreach ($commands as $command) {
53023 $widths[] = Helper::strlen($command->getName());
53024 foreach ($command->getAliases() as $alias) {
53025 $widths[] = Helper::strlen($alias);
53026 }
53027 }
53028
53029 return max($widths) + 2;
53030 }
53031
53032
53033
53034
53035
53036
53037 private function calculateTotalWidthForOptions(array $options)
53038 {
53039 $totalWidth = 0;
53040 foreach ($options as $option) {
53041
53042  $nameLength = 1 + max(\strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
53043
53044 if ($option->acceptValue()) {
53045 $valueLength = 1 + Helper::strlen($option->getName()); 
53046  $valueLength += $option->isValueOptional() ? 2 : 0; 
53047
53048 $nameLength += $valueLength;
53049 }
53050 $totalWidth = max($totalWidth, $nameLength);
53051 }
53052
53053 return $totalWidth;
53054 }
53055 }
53056 <?php
53057
53058
53059
53060
53061
53062
53063
53064
53065
53066
53067 namespace Symfony\Component\Console\Descriptor;
53068
53069 use Symfony\Component\Console\Application;
53070 use Symfony\Component\Console\Command\Command;
53071 use Symfony\Component\Console\Input\InputArgument;
53072 use Symfony\Component\Console\Input\InputDefinition;
53073 use Symfony\Component\Console\Input\InputOption;
53074
53075
53076
53077
53078
53079
53080
53081
53082 class XmlDescriptor extends Descriptor
53083 {
53084
53085
53086
53087 public function getInputDefinitionDocument(InputDefinition $definition)
53088 {
53089 $dom = new \DOMDocument('1.0', 'UTF-8');
53090 $dom->appendChild($definitionXML = $dom->createElement('definition'));
53091
53092 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
53093 foreach ($definition->getArguments() as $argument) {
53094 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
53095 }
53096
53097 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
53098 foreach ($definition->getOptions() as $option) {
53099 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
53100 }
53101
53102 return $dom;
53103 }
53104
53105
53106
53107
53108 public function getCommandDocument(Command $command)
53109 {
53110 $dom = new \DOMDocument('1.0', 'UTF-8');
53111 $dom->appendChild($commandXML = $dom->createElement('command'));
53112
53113 $command->getSynopsis();
53114 $command->mergeApplicationDefinition(false);
53115
53116 $commandXML->setAttribute('id', $command->getName());
53117 $commandXML->setAttribute('name', $command->getName());
53118
53119 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
53120
53121 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
53122 $usagesXML->appendChild($dom->createElement('usage', $usage));
53123 }
53124
53125 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
53126 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
53127
53128 $commandXML->appendChild($helpXML = $dom->createElement('help'));
53129 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
53130
53131 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
53132 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
53133
53134 return $dom;
53135 }
53136
53137
53138
53139
53140
53141
53142
53143 public function getApplicationDocument(Application $application, $namespace = null)
53144 {
53145 $dom = new \DOMDocument('1.0', 'UTF-8');
53146 $dom->appendChild($rootXml = $dom->createElement('symfony'));
53147
53148 if ('UNKNOWN' !== $application->getName()) {
53149 $rootXml->setAttribute('name', $application->getName());
53150 if ('UNKNOWN' !== $application->getVersion()) {
53151 $rootXml->setAttribute('version', $application->getVersion());
53152 }
53153 }
53154
53155 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
53156
53157 $description = new ApplicationDescription($application, $namespace);
53158
53159 if ($namespace) {
53160 $commandsXML->setAttribute('namespace', $namespace);
53161 }
53162
53163 foreach ($description->getCommands() as $command) {
53164 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
53165 }
53166
53167 if (!$namespace) {
53168 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
53169
53170 foreach ($description->getNamespaces() as $namespaceDescription) {
53171 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
53172 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
53173
53174 foreach ($namespaceDescription['commands'] as $name) {
53175 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
53176 $commandXML->appendChild($dom->createTextNode($name));
53177 }
53178 }
53179 }
53180
53181 return $dom;
53182 }
53183
53184
53185
53186
53187 protected function describeInputArgument(InputArgument $argument, array $options = array())
53188 {
53189 $this->writeDocument($this->getInputArgumentDocument($argument));
53190 }
53191
53192
53193
53194
53195 protected function describeInputOption(InputOption $option, array $options = array())
53196 {
53197 $this->writeDocument($this->getInputOptionDocument($option));
53198 }
53199
53200
53201
53202
53203 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
53204 {
53205 $this->writeDocument($this->getInputDefinitionDocument($definition));
53206 }
53207
53208
53209
53210
53211 protected function describeCommand(Command $command, array $options = array())
53212 {
53213 $this->writeDocument($this->getCommandDocument($command));
53214 }
53215
53216
53217
53218
53219 protected function describeApplication(Application $application, array $options = array())
53220 {
53221 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
53222 }
53223
53224
53225
53226
53227 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
53228 {
53229 foreach ($importedParent->childNodes as $childNode) {
53230 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
53231 }
53232 }
53233
53234
53235
53236
53237
53238
53239 private function writeDocument(\DOMDocument $dom)
53240 {
53241 $dom->formatOutput = true;
53242 $this->write($dom->saveXML());
53243 }
53244
53245
53246
53247
53248 private function getInputArgumentDocument(InputArgument $argument)
53249 {
53250 $dom = new \DOMDocument('1.0', 'UTF-8');
53251
53252 $dom->appendChild($objectXML = $dom->createElement('argument'));
53253 $objectXML->setAttribute('name', $argument->getName());
53254 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
53255 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
53256 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
53257 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
53258
53259 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
53260 $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
53261 foreach ($defaults as $default) {
53262 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
53263 $defaultXML->appendChild($dom->createTextNode($default));
53264 }
53265
53266 return $dom;
53267 }
53268
53269
53270
53271
53272 private function getInputOptionDocument(InputOption $option)
53273 {
53274 $dom = new \DOMDocument('1.0', 'UTF-8');
53275
53276 $dom->appendChild($objectXML = $dom->createElement('option'));
53277 $objectXML->setAttribute('name', '--'.$option->getName());
53278 $pos = strpos($option->getShortcut(), '|');
53279 if (false !== $pos) {
53280 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
53281 $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
53282 } else {
53283 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
53284 }
53285 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
53286 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
53287 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
53288 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
53289 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
53290
53291 if ($option->acceptValue()) {
53292 $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
53293 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
53294
53295 if (!empty($defaults)) {
53296 foreach ($defaults as $default) {
53297 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
53298 $defaultXML->appendChild($dom->createTextNode($default));
53299 }
53300 }
53301 }
53302
53303 return $dom;
53304 }
53305 }
53306 <?php
53307
53308
53309
53310
53311
53312
53313
53314
53315
53316
53317 namespace Symfony\Component\Console\Event;
53318
53319
53320
53321
53322
53323
53324 class ConsoleCommandEvent extends ConsoleEvent
53325 {
53326
53327
53328
53329 const RETURN_CODE_DISABLED = 113;
53330
53331
53332
53333
53334 private $commandShouldRun = true;
53335
53336
53337
53338
53339
53340
53341 public function disableCommand()
53342 {
53343 return $this->commandShouldRun = false;
53344 }
53345
53346
53347
53348
53349
53350
53351 public function enableCommand()
53352 {
53353 return $this->commandShouldRun = true;
53354 }
53355
53356
53357
53358
53359
53360
53361 public function commandShouldRun()
53362 {
53363 return $this->commandShouldRun;
53364 }
53365 }
53366 <?php
53367
53368
53369
53370
53371
53372
53373
53374
53375
53376
53377 namespace Symfony\Component\Console\Event;
53378
53379 use Symfony\Component\Console\Command\Command;
53380 use Symfony\Component\Console\Input\InputInterface;
53381 use Symfony\Component\Console\Output\OutputInterface;
53382 use Symfony\Component\EventDispatcher\Event;
53383
53384
53385
53386
53387
53388
53389 class ConsoleEvent extends Event
53390 {
53391 protected $command;
53392
53393 private $input;
53394 private $output;
53395
53396 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
53397 {
53398 $this->command = $command;
53399 $this->input = $input;
53400 $this->output = $output;
53401 }
53402
53403
53404
53405
53406
53407
53408 public function getCommand()
53409 {
53410 return $this->command;
53411 }
53412
53413
53414
53415
53416
53417
53418 public function getInput()
53419 {
53420 return $this->input;
53421 }
53422
53423
53424
53425
53426
53427
53428 public function getOutput()
53429 {
53430 return $this->output;
53431 }
53432 }
53433 <?php
53434
53435
53436
53437
53438
53439
53440
53441
53442
53443
53444 namespace Symfony\Component\Console\Event;
53445
53446 use Symfony\Component\Console\Command\Command;
53447 use Symfony\Component\Console\Input\InputInterface;
53448 use Symfony\Component\Console\Output\OutputInterface;
53449
53450
53451
53452
53453
53454
53455 class ConsoleExceptionEvent extends ConsoleEvent
53456 {
53457 private $exception;
53458 private $exitCode;
53459
53460 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
53461 {
53462 parent::__construct($command, $input, $output);
53463
53464 $this->setException($exception);
53465 $this->exitCode = (int) $exitCode;
53466 }
53467
53468
53469
53470
53471
53472
53473 public function getException()
53474 {
53475 return $this->exception;
53476 }
53477
53478
53479
53480
53481
53482
53483
53484
53485 public function setException(\Exception $exception)
53486 {
53487 $this->exception = $exception;
53488 }
53489
53490
53491
53492
53493
53494
53495 public function getExitCode()
53496 {
53497 return $this->exitCode;
53498 }
53499 }
53500 <?php
53501
53502
53503
53504
53505
53506
53507
53508
53509
53510
53511 namespace Symfony\Component\Console\Event;
53512
53513 use Symfony\Component\Console\Command\Command;
53514 use Symfony\Component\Console\Input\InputInterface;
53515 use Symfony\Component\Console\Output\OutputInterface;
53516
53517
53518
53519
53520
53521
53522 class ConsoleTerminateEvent extends ConsoleEvent
53523 {
53524
53525
53526
53527
53528
53529 private $exitCode;
53530
53531 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
53532 {
53533 parent::__construct($command, $input, $output);
53534
53535 $this->setExitCode($exitCode);
53536 }
53537
53538
53539
53540
53541
53542
53543 public function setExitCode($exitCode)
53544 {
53545 $this->exitCode = (int) $exitCode;
53546 }
53547
53548
53549
53550
53551
53552
53553 public function getExitCode()
53554 {
53555 return $this->exitCode;
53556 }
53557 }
53558 <?php
53559
53560
53561
53562
53563
53564
53565
53566
53567
53568
53569 namespace Symfony\Component\Console\Exception;
53570
53571
53572
53573
53574
53575
53576 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
53577 {
53578 private $alternatives;
53579
53580
53581
53582
53583
53584
53585
53586 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
53587 {
53588 parent::__construct($message, $code, $previous);
53589
53590 $this->alternatives = $alternatives;
53591 }
53592
53593
53594
53595
53596 public function getAlternatives()
53597 {
53598 return $this->alternatives;
53599 }
53600 }
53601 <?php
53602
53603
53604
53605
53606
53607
53608
53609
53610
53611
53612 namespace Symfony\Component\Console\Exception;
53613
53614
53615
53616
53617
53618
53619 interface ExceptionInterface
53620 {
53621 }
53622 <?php
53623
53624
53625
53626
53627
53628
53629
53630
53631
53632
53633 namespace Symfony\Component\Console\Exception;
53634
53635
53636
53637
53638 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
53639 {
53640 }
53641 <?php
53642
53643
53644
53645
53646
53647
53648
53649
53650
53651
53652 namespace Symfony\Component\Console\Exception;
53653
53654
53655
53656
53657
53658
53659 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
53660 {
53661 }
53662 <?php
53663
53664
53665
53666
53667
53668
53669
53670
53671
53672
53673 namespace Symfony\Component\Console\Exception;
53674
53675
53676
53677
53678 class LogicException extends \LogicException implements ExceptionInterface
53679 {
53680 }
53681 <?php
53682
53683
53684
53685
53686
53687
53688
53689
53690
53691
53692 namespace Symfony\Component\Console\Exception;
53693
53694
53695
53696
53697 class RuntimeException extends \RuntimeException implements ExceptionInterface
53698 {
53699 }
53700 <?php
53701
53702
53703
53704
53705
53706
53707
53708
53709
53710
53711 namespace Symfony\Component\Console\Formatter;
53712
53713 use Symfony\Component\Console\Exception\InvalidArgumentException;
53714
53715
53716
53717
53718
53719
53720 class OutputFormatter implements OutputFormatterInterface
53721 {
53722 private $decorated;
53723 private $styles = array();
53724 private $styleStack;
53725
53726
53727
53728
53729
53730
53731
53732
53733 public static function escape($text)
53734 {
53735 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
53736
53737 return self::escapeTrailingBackslash($text);
53738 }
53739
53740
53741
53742
53743
53744
53745
53746
53747
53748
53749 public static function escapeTrailingBackslash($text)
53750 {
53751 if ('\\' === substr($text, -1)) {
53752 $len = \strlen($text);
53753 $text = rtrim($text, '\\');
53754 $text = str_replace("\0", '', $text);
53755 $text .= str_repeat("\0", $len - \strlen($text));
53756 }
53757
53758 return $text;
53759 }
53760
53761
53762
53763
53764
53765
53766
53767 public function __construct($decorated = false, array $styles = array())
53768 {
53769 $this->decorated = (bool) $decorated;
53770
53771 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
53772 $this->setStyle('info', new OutputFormatterStyle('green'));
53773 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
53774 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
53775
53776 foreach ($styles as $name => $style) {
53777 $this->setStyle($name, $style);
53778 }
53779
53780 $this->styleStack = new OutputFormatterStyleStack();
53781 }
53782
53783
53784
53785
53786 public function setDecorated($decorated)
53787 {
53788 $this->decorated = (bool) $decorated;
53789 }
53790
53791
53792
53793
53794 public function isDecorated()
53795 {
53796 return $this->decorated;
53797 }
53798
53799
53800
53801
53802 public function setStyle($name, OutputFormatterStyleInterface $style)
53803 {
53804 $this->styles[strtolower($name)] = $style;
53805 }
53806
53807
53808
53809
53810 public function hasStyle($name)
53811 {
53812 return isset($this->styles[strtolower($name)]);
53813 }
53814
53815
53816
53817
53818 public function getStyle($name)
53819 {
53820 if (!$this->hasStyle($name)) {
53821 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
53822 }
53823
53824 return $this->styles[strtolower($name)];
53825 }
53826
53827
53828
53829
53830 public function format($message)
53831 {
53832 $message = (string) $message;
53833 $offset = 0;
53834 $output = '';
53835 $tagRegex = '[a-z][a-z0-9_=;-]*+';
53836 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
53837 foreach ($matches[0] as $i => $match) {
53838 $pos = $match[1];
53839 $text = $match[0];
53840
53841 if (0 != $pos && '\\' == $message[$pos - 1]) {
53842 continue;
53843 }
53844
53845
53846  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
53847 $offset = $pos + \strlen($text);
53848
53849
53850  if ($open = '/' != $text[1]) {
53851 $tag = $matches[1][$i][0];
53852 } else {
53853 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
53854 }
53855
53856 if (!$open && !$tag) {
53857
53858  $this->styleStack->pop();
53859 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
53860 $output .= $this->applyCurrentStyle($text);
53861 } elseif ($open) {
53862 $this->styleStack->push($style);
53863 } else {
53864 $this->styleStack->pop($style);
53865 }
53866 }
53867
53868 $output .= $this->applyCurrentStyle(substr($message, $offset));
53869
53870 if (false !== strpos($output, "\0")) {
53871 return strtr($output, array("\0" => '\\', '\\<' => '<'));
53872 }
53873
53874 return str_replace('\\<', '<', $output);
53875 }
53876
53877
53878
53879
53880 public function getStyleStack()
53881 {
53882 return $this->styleStack;
53883 }
53884
53885
53886
53887
53888
53889
53890
53891
53892 private function createStyleFromString($string)
53893 {
53894 if (isset($this->styles[$string])) {
53895 return $this->styles[$string];
53896 }
53897
53898 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
53899 return false;
53900 }
53901
53902 $style = new OutputFormatterStyle();
53903 foreach ($matches as $match) {
53904 array_shift($match);
53905
53906 if ('fg' == $match[0]) {
53907 $style->setForeground($match[1]);
53908 } elseif ('bg' == $match[0]) {
53909 $style->setBackground($match[1]);
53910 } else {
53911 try {
53912 $style->setOption($match[1]);
53913 } catch (\InvalidArgumentException $e) {
53914 return false;
53915 }
53916 }
53917 }
53918
53919 return $style;
53920 }
53921
53922
53923
53924
53925
53926
53927
53928
53929 private function applyCurrentStyle($text)
53930 {
53931 return $this->isDecorated() && \strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
53932 }
53933 }
53934 <?php
53935
53936
53937
53938
53939
53940
53941
53942
53943
53944
53945 namespace Symfony\Component\Console\Formatter;
53946
53947
53948
53949
53950
53951
53952 interface OutputFormatterInterface
53953 {
53954
53955
53956
53957
53958
53959 public function setDecorated($decorated);
53960
53961
53962
53963
53964
53965
53966 public function isDecorated();
53967
53968
53969
53970
53971
53972
53973
53974 public function setStyle($name, OutputFormatterStyleInterface $style);
53975
53976
53977
53978
53979
53980
53981
53982
53983 public function hasStyle($name);
53984
53985
53986
53987
53988
53989
53990
53991
53992
53993
53994 public function getStyle($name);
53995
53996
53997
53998
53999
54000
54001
54002
54003 public function format($message);
54004 }
54005 <?php
54006
54007
54008
54009
54010
54011
54012
54013
54014
54015
54016 namespace Symfony\Component\Console\Formatter;
54017
54018 use Symfony\Component\Console\Exception\InvalidArgumentException;
54019
54020
54021
54022
54023
54024
54025 class OutputFormatterStyle implements OutputFormatterStyleInterface
54026 {
54027 private static $availableForegroundColors = array(
54028 'black' => array('set' => 30, 'unset' => 39),
54029 'red' => array('set' => 31, 'unset' => 39),
54030 'green' => array('set' => 32, 'unset' => 39),
54031 'yellow' => array('set' => 33, 'unset' => 39),
54032 'blue' => array('set' => 34, 'unset' => 39),
54033 'magenta' => array('set' => 35, 'unset' => 39),
54034 'cyan' => array('set' => 36, 'unset' => 39),
54035 'white' => array('set' => 37, 'unset' => 39),
54036 'default' => array('set' => 39, 'unset' => 39),
54037 );
54038 private static $availableBackgroundColors = array(
54039 'black' => array('set' => 40, 'unset' => 49),
54040 'red' => array('set' => 41, 'unset' => 49),
54041 'green' => array('set' => 42, 'unset' => 49),
54042 'yellow' => array('set' => 43, 'unset' => 49),
54043 'blue' => array('set' => 44, 'unset' => 49),
54044 'magenta' => array('set' => 45, 'unset' => 49),
54045 'cyan' => array('set' => 46, 'unset' => 49),
54046 'white' => array('set' => 47, 'unset' => 49),
54047 'default' => array('set' => 49, 'unset' => 49),
54048 );
54049 private static $availableOptions = array(
54050 'bold' => array('set' => 1, 'unset' => 22),
54051 'underscore' => array('set' => 4, 'unset' => 24),
54052 'blink' => array('set' => 5, 'unset' => 25),
54053 'reverse' => array('set' => 7, 'unset' => 27),
54054 'conceal' => array('set' => 8, 'unset' => 28),
54055 );
54056
54057 private $foreground;
54058 private $background;
54059 private $options = array();
54060
54061
54062
54063
54064
54065
54066
54067
54068 public function __construct($foreground = null, $background = null, array $options = array())
54069 {
54070 if (null !== $foreground) {
54071 $this->setForeground($foreground);
54072 }
54073 if (null !== $background) {
54074 $this->setBackground($background);
54075 }
54076 if (\count($options)) {
54077 $this->setOptions($options);
54078 }
54079 }
54080
54081
54082
54083
54084
54085
54086
54087
54088 public function setForeground($color = null)
54089 {
54090 if (null === $color) {
54091 $this->foreground = null;
54092
54093 return;
54094 }
54095
54096 if (!isset(static::$availableForegroundColors[$color])) {
54097 throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors))));
54098 }
54099
54100 $this->foreground = static::$availableForegroundColors[$color];
54101 }
54102
54103
54104
54105
54106
54107
54108
54109
54110 public function setBackground($color = null)
54111 {
54112 if (null === $color) {
54113 $this->background = null;
54114
54115 return;
54116 }
54117
54118 if (!isset(static::$availableBackgroundColors[$color])) {
54119 throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors))));
54120 }
54121
54122 $this->background = static::$availableBackgroundColors[$color];
54123 }
54124
54125
54126
54127
54128
54129
54130
54131
54132 public function setOption($option)
54133 {
54134 if (!isset(static::$availableOptions[$option])) {
54135 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
54136 }
54137
54138 if (!\in_array(static::$availableOptions[$option], $this->options)) {
54139 $this->options[] = static::$availableOptions[$option];
54140 }
54141 }
54142
54143
54144
54145
54146
54147
54148
54149
54150 public function unsetOption($option)
54151 {
54152 if (!isset(static::$availableOptions[$option])) {
54153 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
54154 }
54155
54156 $pos = array_search(static::$availableOptions[$option], $this->options);
54157 if (false !== $pos) {
54158 unset($this->options[$pos]);
54159 }
54160 }
54161
54162
54163
54164
54165 public function setOptions(array $options)
54166 {
54167 $this->options = array();
54168
54169 foreach ($options as $option) {
54170 $this->setOption($option);
54171 }
54172 }
54173
54174
54175
54176
54177
54178
54179
54180
54181 public function apply($text)
54182 {
54183 $setCodes = array();
54184 $unsetCodes = array();
54185
54186 if (null !== $this->foreground) {
54187 $setCodes[] = $this->foreground['set'];
54188 $unsetCodes[] = $this->foreground['unset'];
54189 }
54190 if (null !== $this->background) {
54191 $setCodes[] = $this->background['set'];
54192 $unsetCodes[] = $this->background['unset'];
54193 }
54194 if (\count($this->options)) {
54195 foreach ($this->options as $option) {
54196 $setCodes[] = $option['set'];
54197 $unsetCodes[] = $option['unset'];
54198 }
54199 }
54200
54201 if (0 === \count($setCodes)) {
54202 return $text;
54203 }
54204
54205 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
54206 }
54207 }
54208 <?php
54209
54210
54211
54212
54213
54214
54215
54216
54217
54218
54219 namespace Symfony\Component\Console\Formatter;
54220
54221
54222
54223
54224
54225
54226 interface OutputFormatterStyleInterface
54227 {
54228
54229
54230
54231
54232
54233 public function setForeground($color = null);
54234
54235
54236
54237
54238
54239
54240 public function setBackground($color = null);
54241
54242
54243
54244
54245
54246
54247 public function setOption($option);
54248
54249
54250
54251
54252
54253
54254 public function unsetOption($option);
54255
54256
54257
54258
54259 public function setOptions(array $options);
54260
54261
54262
54263
54264
54265
54266
54267
54268 public function apply($text);
54269 }
54270 <?php
54271
54272
54273
54274
54275
54276
54277
54278
54279
54280
54281 namespace Symfony\Component\Console\Formatter;
54282
54283 use Symfony\Component\Console\Exception\InvalidArgumentException;
54284
54285
54286
54287
54288 class OutputFormatterStyleStack
54289 {
54290
54291
54292
54293 private $styles;
54294
54295 private $emptyStyle;
54296
54297 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
54298 {
54299 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
54300 $this->reset();
54301 }
54302
54303
54304
54305
54306 public function reset()
54307 {
54308 $this->styles = array();
54309 }
54310
54311
54312
54313
54314 public function push(OutputFormatterStyleInterface $style)
54315 {
54316 $this->styles[] = $style;
54317 }
54318
54319
54320
54321
54322
54323
54324
54325
54326 public function pop(OutputFormatterStyleInterface $style = null)
54327 {
54328 if (empty($this->styles)) {
54329 return $this->emptyStyle;
54330 }
54331
54332 if (null === $style) {
54333 return array_pop($this->styles);
54334 }
54335
54336 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
54337 if ($style->apply('') === $stackedStyle->apply('')) {
54338 $this->styles = \array_slice($this->styles, 0, $index);
54339
54340 return $stackedStyle;
54341 }
54342 }
54343
54344 throw new InvalidArgumentException('Incorrectly nested style tag found.');
54345 }
54346
54347
54348
54349
54350
54351
54352 public function getCurrent()
54353 {
54354 if (empty($this->styles)) {
54355 return $this->emptyStyle;
54356 }
54357
54358 return $this->styles[\count($this->styles) - 1];
54359 }
54360
54361
54362
54363
54364 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
54365 {
54366 $this->emptyStyle = $emptyStyle;
54367
54368 return $this;
54369 }
54370
54371
54372
54373
54374 public function getEmptyStyle()
54375 {
54376 return $this->emptyStyle;
54377 }
54378 }
54379 <?php
54380
54381
54382
54383
54384
54385
54386
54387
54388
54389
54390 namespace Symfony\Component\Console\Helper;
54391
54392
54393
54394
54395
54396
54397
54398
54399 class DebugFormatterHelper extends Helper
54400 {
54401 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
54402 private $started = array();
54403 private $count = -1;
54404
54405
54406
54407
54408
54409
54410
54411
54412
54413
54414 public function start($id, $message, $prefix = 'RUN')
54415 {
54416 $this->started[$id] = array('border' => ++$this->count % \count($this->colors));
54417
54418 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
54419 }
54420
54421
54422
54423
54424
54425
54426
54427
54428
54429
54430
54431
54432 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
54433 {
54434 $message = '';
54435
54436 if ($error) {
54437 if (isset($this->started[$id]['out'])) {
54438 $message .= "\n";
54439 unset($this->started[$id]['out']);
54440 }
54441 if (!isset($this->started[$id]['err'])) {
54442 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
54443 $this->started[$id]['err'] = true;
54444 }
54445
54446 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
54447 } else {
54448 if (isset($this->started[$id]['err'])) {
54449 $message .= "\n";
54450 unset($this->started[$id]['err']);
54451 }
54452 if (!isset($this->started[$id]['out'])) {
54453 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
54454 $this->started[$id]['out'] = true;
54455 }
54456
54457 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
54458 }
54459
54460 return $message;
54461 }
54462
54463
54464
54465
54466
54467
54468
54469
54470
54471
54472
54473 public function stop($id, $message, $successful, $prefix = 'RES')
54474 {
54475 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
54476
54477 if ($successful) {
54478 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
54479 }
54480
54481 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
54482
54483 unset($this->started[$id]['out'], $this->started[$id]['err']);
54484
54485 return $message;
54486 }
54487
54488
54489
54490
54491
54492
54493 private function getBorder($id)
54494 {
54495 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
54496 }
54497
54498
54499
54500
54501 public function getName()
54502 {
54503 return 'debug_formatter';
54504 }
54505 }
54506 <?php
54507
54508
54509
54510
54511
54512
54513
54514
54515
54516
54517 namespace Symfony\Component\Console\Helper;
54518
54519 use Symfony\Component\Console\Descriptor\DescriptorInterface;
54520 use Symfony\Component\Console\Descriptor\JsonDescriptor;
54521 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
54522 use Symfony\Component\Console\Descriptor\TextDescriptor;
54523 use Symfony\Component\Console\Descriptor\XmlDescriptor;
54524 use Symfony\Component\Console\Exception\InvalidArgumentException;
54525 use Symfony\Component\Console\Output\OutputInterface;
54526
54527
54528
54529
54530
54531
54532 class DescriptorHelper extends Helper
54533 {
54534
54535
54536
54537 private $descriptors = array();
54538
54539 public function __construct()
54540 {
54541 $this
54542 ->register('txt', new TextDescriptor())
54543 ->register('xml', new XmlDescriptor())
54544 ->register('json', new JsonDescriptor())
54545 ->register('md', new MarkdownDescriptor())
54546 ;
54547 }
54548
54549
54550
54551
54552
54553
54554
54555
54556
54557
54558
54559
54560
54561
54562 public function describe(OutputInterface $output, $object, array $options = array())
54563 {
54564 $options = array_merge(array(
54565 'raw_text' => false,
54566 'format' => 'txt',
54567 ), $options);
54568
54569 if (!isset($this->descriptors[$options['format']])) {
54570 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
54571 }
54572
54573 $descriptor = $this->descriptors[$options['format']];
54574 $descriptor->describe($output, $object, $options);
54575 }
54576
54577
54578
54579
54580
54581
54582
54583
54584
54585 public function register($format, DescriptorInterface $descriptor)
54586 {
54587 $this->descriptors[$format] = $descriptor;
54588
54589 return $this;
54590 }
54591
54592
54593
54594
54595 public function getName()
54596 {
54597 return 'descriptor';
54598 }
54599 }
54600 <?php
54601
54602
54603
54604
54605
54606
54607
54608
54609
54610
54611 namespace Symfony\Component\Console\Helper;
54612
54613 use Symfony\Component\Console\Exception\InvalidArgumentException;
54614 use Symfony\Component\Console\Exception\RuntimeException;
54615 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
54616 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54617 use Symfony\Component\Console\Output\OutputInterface;
54618
54619
54620
54621
54622
54623
54624
54625
54626
54627 class DialogHelper extends InputAwareHelper
54628 {
54629 private $inputStream;
54630 private static $shell;
54631 private static $stty;
54632
54633 public function __construct($triggerDeprecationError = true)
54634 {
54635 if ($triggerDeprecationError) {
54636 @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
54637 }
54638 }
54639
54640
54641
54642
54643
54644
54645
54646
54647
54648
54649
54650
54651
54652
54653
54654
54655 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
54656 {
54657 if ($output instanceof ConsoleOutputInterface) {
54658 $output = $output->getErrorOutput();
54659 }
54660
54661 $width = max(array_map('strlen', array_keys($choices)));
54662
54663 $messages = (array) $question;
54664 foreach ($choices as $key => $value) {
54665 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
54666 }
54667
54668 $output->writeln($messages);
54669
54670 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
54671
54672  $selectedChoices = str_replace(' ', '', $picked);
54673
54674 if ($multiselect) {
54675
54676  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
54677 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
54678 }
54679 $selectedChoices = explode(',', $selectedChoices);
54680 } else {
54681 $selectedChoices = array($picked);
54682 }
54683
54684 $multiselectChoices = array();
54685
54686 foreach ($selectedChoices as $value) {
54687 if (empty($choices[$value])) {
54688 throw new InvalidArgumentException(sprintf($errorMessage, $value));
54689 }
54690 $multiselectChoices[] = $value;
54691 }
54692
54693 if ($multiselect) {
54694 return $multiselectChoices;
54695 }
54696
54697 return $picked;
54698 }, $attempts, $default);
54699
54700 return $result;
54701 }
54702
54703
54704
54705
54706
54707
54708
54709
54710
54711
54712
54713
54714
54715 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
54716 {
54717 if ($this->input && !$this->input->isInteractive()) {
54718 return $default;
54719 }
54720
54721 if ($output instanceof ConsoleOutputInterface) {
54722 $output = $output->getErrorOutput();
54723 }
54724
54725 $output->write($question);
54726
54727 $inputStream = $this->inputStream ?: STDIN;
54728
54729 if (null === $autocomplete || !$this->hasSttyAvailable()) {
54730 $ret = fgets($inputStream, 4096);
54731 if (false === $ret) {
54732 throw new RuntimeException('Aborted');
54733 }
54734 $ret = trim($ret);
54735 } else {
54736 $ret = '';
54737
54738 $i = 0;
54739 $ofs = -1;
54740 $matches = $autocomplete;
54741 $numMatches = \count($matches);
54742
54743 $sttyMode = shell_exec('stty -g');
54744
54745
54746  shell_exec('stty -icanon -echo');
54747
54748
54749  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
54750
54751
54752  while (!feof($inputStream)) {
54753 $c = fread($inputStream, 1);
54754
54755
54756  if ("\177" === $c) {
54757 if (0 === $numMatches && 0 !== $i) {
54758 --$i;
54759
54760  $output->write("\033[1D");
54761 }
54762
54763 if (0 === $i) {
54764 $ofs = -1;
54765 $matches = $autocomplete;
54766 $numMatches = \count($matches);
54767 } else {
54768 $numMatches = 0;
54769 }
54770
54771
54772  $ret = substr($ret, 0, $i);
54773 } elseif ("\033" === $c) {
54774
54775  $c .= fread($inputStream, 2);
54776
54777
54778  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
54779 if ('A' === $c[2] && -1 === $ofs) {
54780 $ofs = 0;
54781 }
54782
54783 if (0 === $numMatches) {
54784 continue;
54785 }
54786
54787 $ofs += ('A' === $c[2]) ? -1 : 1;
54788 $ofs = ($numMatches + $ofs) % $numMatches;
54789 }
54790 } elseif (\ord($c) < 32) {
54791 if ("\t" === $c || "\n" === $c) {
54792 if ($numMatches > 0 && -1 !== $ofs) {
54793 $ret = $matches[$ofs];
54794
54795  $output->write(substr($ret, $i));
54796 $i = \strlen($ret);
54797 }
54798
54799 if ("\n" === $c) {
54800 $output->write($c);
54801 break;
54802 }
54803
54804 $numMatches = 0;
54805 }
54806
54807 continue;
54808 } else {
54809 $output->write($c);
54810 $ret .= $c;
54811 ++$i;
54812
54813 $numMatches = 0;
54814 $ofs = 0;
54815
54816 foreach ($autocomplete as $value) {
54817
54818  if (0 === strpos($value, $ret) && $i !== \strlen($value)) {
54819 $matches[$numMatches++] = $value;
54820 }
54821 }
54822 }
54823
54824
54825  $output->write("\033[K");
54826
54827 if ($numMatches > 0 && -1 !== $ofs) {
54828
54829  $output->write("\0337");
54830
54831  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
54832
54833  $output->write("\0338");
54834 }
54835 }
54836
54837
54838  shell_exec(sprintf('stty %s', $sttyMode));
54839 }
54840
54841 return \strlen($ret) > 0 ? $ret : $default;
54842 }
54843
54844
54845
54846
54847
54848
54849
54850
54851
54852
54853
54854
54855 public function askConfirmation(OutputInterface $output, $question, $default = true)
54856 {
54857 $answer = 'z';
54858 while ($answer && !\in_array(strtolower($answer[0]), array('y', 'n'))) {
54859 $answer = $this->ask($output, $question);
54860 }
54861
54862 if (false === $default) {
54863 return $answer && 'y' == strtolower($answer[0]);
54864 }
54865
54866 return !$answer || 'y' == strtolower($answer[0]);
54867 }
54868
54869
54870
54871
54872
54873
54874
54875
54876
54877
54878
54879
54880 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
54881 {
54882 if ($output instanceof ConsoleOutputInterface) {
54883 $output = $output->getErrorOutput();
54884 }
54885
54886 if ('\\' === \DIRECTORY_SEPARATOR) {
54887 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
54888
54889
54890  if ('phar:' === substr(__FILE__, 0, 5)) {
54891 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
54892 copy($exe, $tmpExe);
54893 $exe = $tmpExe;
54894 }
54895
54896 $output->write($question);
54897 $value = rtrim(shell_exec($exe));
54898 $output->writeln('');
54899
54900 if (isset($tmpExe)) {
54901 unlink($tmpExe);
54902 }
54903
54904 return $value;
54905 }
54906
54907 if ($this->hasSttyAvailable()) {
54908 $output->write($question);
54909
54910 $sttyMode = shell_exec('stty -g');
54911
54912 shell_exec('stty -echo');
54913 $value = fgets($this->inputStream ?: STDIN, 4096);
54914 shell_exec(sprintf('stty %s', $sttyMode));
54915
54916 if (false === $value) {
54917 throw new RuntimeException('Aborted');
54918 }
54919
54920 $value = trim($value);
54921 $output->writeln('');
54922
54923 return $value;
54924 }
54925
54926 if (false !== $shell = $this->getShell()) {
54927 $output->write($question);
54928 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
54929 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
54930 $value = rtrim(shell_exec($command));
54931 $output->writeln('');
54932
54933 return $value;
54934 }
54935
54936 if ($fallback) {
54937 return $this->ask($output, $question);
54938 }
54939
54940 throw new RuntimeException('Unable to hide the response');
54941 }
54942
54943
54944
54945
54946
54947
54948
54949
54950
54951
54952
54953
54954
54955
54956
54957
54958
54959
54960
54961 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
54962 {
54963 $that = $this;
54964
54965 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
54966 return $that->ask($output, $question, $default, $autocomplete);
54967 };
54968
54969 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
54970 }
54971
54972
54973
54974
54975
54976
54977
54978
54979
54980
54981
54982
54983
54984
54985
54986
54987
54988
54989
54990 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
54991 {
54992 $that = $this;
54993
54994 $interviewer = function () use ($output, $question, $fallback, $that) {
54995 return $that->askHiddenResponse($output, $question, $fallback);
54996 };
54997
54998 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
54999 }
55000
55001
55002
55003
55004
55005
55006
55007
55008 public function setInputStream($stream)
55009 {
55010 $this->inputStream = $stream;
55011 }
55012
55013
55014
55015
55016
55017
55018 public function getInputStream()
55019 {
55020 return $this->inputStream;
55021 }
55022
55023
55024
55025
55026 public function getName()
55027 {
55028 return 'dialog';
55029 }
55030
55031
55032
55033
55034
55035
55036 private function getShell()
55037 {
55038 if (null !== self::$shell) {
55039 return self::$shell;
55040 }
55041
55042 self::$shell = false;
55043
55044 if (file_exists('/usr/bin/env')) {
55045
55046  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
55047 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
55048 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
55049 self::$shell = $sh;
55050 break;
55051 }
55052 }
55053 }
55054
55055 return self::$shell;
55056 }
55057
55058 private function hasSttyAvailable()
55059 {
55060 if (null !== self::$stty) {
55061 return self::$stty;
55062 }
55063
55064 exec('stty 2>&1', $output, $exitcode);
55065
55066 return self::$stty = 0 === $exitcode;
55067 }
55068
55069
55070
55071
55072
55073
55074
55075
55076
55077
55078
55079
55080
55081 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
55082 {
55083 if ($output instanceof ConsoleOutputInterface) {
55084 $output = $output->getErrorOutput();
55085 }
55086
55087 $e = null;
55088 while (false === $attempts || $attempts--) {
55089 if (null !== $e) {
55090 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
55091 }
55092
55093 try {
55094 return \call_user_func($validator, $interviewer());
55095 } catch (\Exception $e) {
55096 }
55097 }
55098
55099 throw $e;
55100 }
55101 }
55102 <?php
55103
55104
55105
55106
55107
55108
55109
55110
55111
55112
55113 namespace Symfony\Component\Console\Helper;
55114
55115 use Symfony\Component\Console\Formatter\OutputFormatter;
55116
55117
55118
55119
55120
55121
55122 class FormatterHelper extends Helper
55123 {
55124
55125
55126
55127
55128
55129
55130
55131
55132
55133 public function formatSection($section, $message, $style = 'info')
55134 {
55135 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
55136 }
55137
55138
55139
55140
55141
55142
55143
55144
55145
55146
55147 public function formatBlock($messages, $style, $large = false)
55148 {
55149 if (!\is_array($messages)) {
55150 $messages = array($messages);
55151 }
55152
55153 $len = 0;
55154 $lines = array();
55155 foreach ($messages as $message) {
55156 $message = OutputFormatter::escape($message);
55157 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
55158 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
55159 }
55160
55161 $messages = $large ? array(str_repeat(' ', $len)) : array();
55162 for ($i = 0; isset($lines[$i]); ++$i) {
55163 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
55164 }
55165 if ($large) {
55166 $messages[] = str_repeat(' ', $len);
55167 }
55168
55169 for ($i = 0; isset($messages[$i]); ++$i) {
55170 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
55171 }
55172
55173 return implode("\n", $messages);
55174 }
55175
55176
55177
55178
55179 public function getName()
55180 {
55181 return 'formatter';
55182 }
55183 }
55184 <?php
55185
55186
55187
55188
55189
55190
55191
55192
55193
55194
55195 namespace Symfony\Component\Console\Helper;
55196
55197 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
55198
55199
55200
55201
55202
55203
55204 abstract class Helper implements HelperInterface
55205 {
55206 protected $helperSet = null;
55207
55208
55209
55210
55211 public function setHelperSet(HelperSet $helperSet = null)
55212 {
55213 $this->helperSet = $helperSet;
55214 }
55215
55216
55217
55218
55219 public function getHelperSet()
55220 {
55221 return $this->helperSet;
55222 }
55223
55224
55225
55226
55227
55228
55229
55230
55231 public static function strlen($string)
55232 {
55233 if (false === $encoding = mb_detect_encoding($string, null, true)) {
55234 return \strlen($string);
55235 }
55236
55237 return mb_strwidth($string, $encoding);
55238 }
55239
55240 public static function formatTime($secs)
55241 {
55242 static $timeFormats = array(
55243 array(0, '< 1 sec'),
55244 array(1, '1 sec'),
55245 array(2, 'secs', 1),
55246 array(60, '1 min'),
55247 array(120, 'mins', 60),
55248 array(3600, '1 hr'),
55249 array(7200, 'hrs', 3600),
55250 array(86400, '1 day'),
55251 array(172800, 'days', 86400),
55252 );
55253
55254 foreach ($timeFormats as $index => $format) {
55255 if ($secs >= $format[0]) {
55256 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
55257 || $index == \count($timeFormats) - 1
55258 ) {
55259 if (2 == \count($format)) {
55260 return $format[1];
55261 }
55262
55263 return floor($secs / $format[2]).' '.$format[1];
55264 }
55265 }
55266 }
55267 }
55268
55269 public static function formatMemory($memory)
55270 {
55271 if ($memory >= 1024 * 1024 * 1024) {
55272 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
55273 }
55274
55275 if ($memory >= 1024 * 1024) {
55276 return sprintf('%.1f MiB', $memory / 1024 / 1024);
55277 }
55278
55279 if ($memory >= 1024) {
55280 return sprintf('%d KiB', $memory / 1024);
55281 }
55282
55283 return sprintf('%d B', $memory);
55284 }
55285
55286 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
55287 {
55288 return self::strlen(self::removeDecoration($formatter, $string));
55289 }
55290
55291 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
55292 {
55293 $isDecorated = $formatter->isDecorated();
55294 $formatter->setDecorated(false);
55295
55296  $string = $formatter->format($string);
55297
55298  $string = preg_replace("/\033\[[^m]*m/", '', $string);
55299 $formatter->setDecorated($isDecorated);
55300
55301 return $string;
55302 }
55303 }
55304 <?php
55305
55306
55307
55308
55309
55310
55311
55312
55313
55314
55315 namespace Symfony\Component\Console\Helper;
55316
55317
55318
55319
55320
55321
55322 interface HelperInterface
55323 {
55324
55325
55326
55327 public function setHelperSet(HelperSet $helperSet = null);
55328
55329
55330
55331
55332
55333
55334 public function getHelperSet();
55335
55336
55337
55338
55339
55340
55341 public function getName();
55342 }
55343 <?php
55344
55345
55346
55347
55348
55349
55350
55351
55352
55353
55354 namespace Symfony\Component\Console\Helper;
55355
55356 use Symfony\Component\Console\Command\Command;
55357 use Symfony\Component\Console\Exception\InvalidArgumentException;
55358
55359
55360
55361
55362
55363
55364 class HelperSet implements \IteratorAggregate
55365 {
55366
55367
55368
55369 private $helpers = array();
55370 private $command;
55371
55372
55373
55374
55375 public function __construct(array $helpers = array())
55376 {
55377 foreach ($helpers as $alias => $helper) {
55378 $this->set($helper, \is_int($alias) ? null : $alias);
55379 }
55380 }
55381
55382
55383
55384
55385
55386
55387
55388 public function set(HelperInterface $helper, $alias = null)
55389 {
55390 $this->helpers[$helper->getName()] = $helper;
55391 if (null !== $alias) {
55392 $this->helpers[$alias] = $helper;
55393 }
55394
55395 $helper->setHelperSet($this);
55396 }
55397
55398
55399
55400
55401
55402
55403
55404
55405 public function has($name)
55406 {
55407 return isset($this->helpers[$name]);
55408 }
55409
55410
55411
55412
55413
55414
55415
55416
55417
55418
55419 public function get($name)
55420 {
55421 if (!$this->has($name)) {
55422 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
55423 }
55424
55425 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
55426 @trigger_error('"Symfony\Component\Console\Helper\DialogHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\QuestionHelper" instead.', E_USER_DEPRECATED);
55427 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
55428 @trigger_error('"Symfony\Component\Console\Helper\ProgressHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\ProgressBar" instead.', E_USER_DEPRECATED);
55429 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
55430 @trigger_error('"Symfony\Component\Console\Helper\TableHelper" is deprecated since Symfony 2.5 and will be removed in 3.0. Use "Symfony\Component\Console\Helper\Table" instead.', E_USER_DEPRECATED);
55431 }
55432
55433 return $this->helpers[$name];
55434 }
55435
55436 public function setCommand(Command $command = null)
55437 {
55438 $this->command = $command;
55439 }
55440
55441
55442
55443
55444
55445
55446 public function getCommand()
55447 {
55448 return $this->command;
55449 }
55450
55451
55452
55453
55454 public function getIterator()
55455 {
55456 return new \ArrayIterator($this->helpers);
55457 }
55458 }
55459 <?php
55460
55461
55462
55463
55464
55465
55466
55467
55468
55469
55470 namespace Symfony\Component\Console\Helper;
55471
55472 use Symfony\Component\Console\Input\InputAwareInterface;
55473 use Symfony\Component\Console\Input\InputInterface;
55474
55475
55476
55477
55478
55479
55480 abstract class InputAwareHelper extends Helper implements InputAwareInterface
55481 {
55482 protected $input;
55483
55484
55485
55486
55487 public function setInput(InputInterface $input)
55488 {
55489 $this->input = $input;
55490 }
55491 }
55492 <?php
55493
55494
55495
55496
55497
55498
55499
55500
55501
55502
55503 namespace Symfony\Component\Console\Helper;
55504
55505 use Symfony\Component\Console\Output\ConsoleOutputInterface;
55506 use Symfony\Component\Console\Output\OutputInterface;
55507 use Symfony\Component\Process\Exception\ProcessFailedException;
55508 use Symfony\Component\Process\Process;
55509 use Symfony\Component\Process\ProcessBuilder;
55510
55511
55512
55513
55514
55515
55516 class ProcessHelper extends Helper
55517 {
55518
55519
55520
55521
55522
55523
55524
55525
55526
55527
55528
55529
55530 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
55531 {
55532 if ($output instanceof ConsoleOutputInterface) {
55533 $output = $output->getErrorOutput();
55534 }
55535
55536 $formatter = $this->getHelperSet()->get('debug_formatter');
55537
55538 if (\is_array($cmd)) {
55539 $process = ProcessBuilder::create($cmd)->getProcess();
55540 } elseif ($cmd instanceof Process) {
55541 $process = $cmd;
55542 } else {
55543 $process = new Process($cmd);
55544 }
55545
55546 if ($verbosity <= $output->getVerbosity()) {
55547 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
55548 }
55549
55550 if ($output->isDebug()) {
55551 $callback = $this->wrapCallback($output, $process, $callback);
55552 }
55553
55554 $process->run($callback);
55555
55556 if ($verbosity <= $output->getVerbosity()) {
55557 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
55558 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
55559 }
55560
55561 if (!$process->isSuccessful() && null !== $error) {
55562 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
55563 }
55564
55565 return $process;
55566 }
55567
55568
55569
55570
55571
55572
55573
55574
55575
55576
55577
55578
55579
55580
55581
55582
55583
55584
55585
55586 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
55587 {
55588 $process = $this->run($output, $cmd, $error, $callback);
55589
55590 if (!$process->isSuccessful()) {
55591 throw new ProcessFailedException($process);
55592 }
55593
55594 return $process;
55595 }
55596
55597
55598
55599
55600
55601
55602
55603
55604
55605
55606 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
55607 {
55608 if ($output instanceof ConsoleOutputInterface) {
55609 $output = $output->getErrorOutput();
55610 }
55611
55612 $formatter = $this->getHelperSet()->get('debug_formatter');
55613
55614 $that = $this;
55615
55616 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
55617 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
55618
55619 if (null !== $callback) {
55620 \call_user_func($callback, $type, $buffer);
55621 }
55622 };
55623 }
55624
55625
55626
55627
55628
55629
55630 public function escapeString($str)
55631 {
55632 return str_replace('<', '\\<', $str);
55633 }
55634
55635
55636
55637
55638 public function getName()
55639 {
55640 return 'process';
55641 }
55642 }
55643 <?php
55644
55645
55646
55647
55648
55649
55650
55651
55652
55653
55654 namespace Symfony\Component\Console\Helper;
55655
55656 use Symfony\Component\Console\Exception\LogicException;
55657 use Symfony\Component\Console\Output\ConsoleOutputInterface;
55658 use Symfony\Component\Console\Output\OutputInterface;
55659
55660
55661
55662
55663
55664
55665
55666 class ProgressBar
55667 {
55668 private $barWidth = 28;
55669 private $barChar;
55670 private $emptyBarChar = '-';
55671 private $progressChar = '>';
55672 private $format;
55673 private $internalFormat;
55674 private $redrawFreq = 1;
55675 private $output;
55676 private $step = 0;
55677 private $max;
55678 private $startTime;
55679 private $stepWidth;
55680 private $percent = 0.0;
55681 private $formatLineCount;
55682 private $messages = array();
55683 private $overwrite = true;
55684 private $firstRun = true;
55685
55686 private static $formatters;
55687 private static $formats;
55688
55689
55690
55691
55692
55693 public function __construct(OutputInterface $output, $max = 0)
55694 {
55695 if ($output instanceof ConsoleOutputInterface) {
55696 $output = $output->getErrorOutput();
55697 }
55698
55699 $this->output = $output;
55700 $this->setMaxSteps($max);
55701
55702 if (!$this->output->isDecorated()) {
55703
55704  $this->overwrite = false;
55705
55706
55707  $this->setRedrawFrequency($max / 10);
55708 }
55709
55710 $this->startTime = time();
55711 }
55712
55713
55714
55715
55716
55717
55718
55719
55720
55721 public static function setPlaceholderFormatterDefinition($name, $callable)
55722 {
55723 if (!self::$formatters) {
55724 self::$formatters = self::initPlaceholderFormatters();
55725 }
55726
55727 self::$formatters[$name] = $callable;
55728 }
55729
55730
55731
55732
55733
55734
55735
55736
55737 public static function getPlaceholderFormatterDefinition($name)
55738 {
55739 if (!self::$formatters) {
55740 self::$formatters = self::initPlaceholderFormatters();
55741 }
55742
55743 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
55744 }
55745
55746
55747
55748
55749
55750
55751
55752
55753
55754 public static function setFormatDefinition($name, $format)
55755 {
55756 if (!self::$formats) {
55757 self::$formats = self::initFormats();
55758 }
55759
55760 self::$formats[$name] = $format;
55761 }
55762
55763
55764
55765
55766
55767
55768
55769
55770 public static function getFormatDefinition($name)
55771 {
55772 if (!self::$formats) {
55773 self::$formats = self::initFormats();
55774 }
55775
55776 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
55777 }
55778
55779
55780
55781
55782
55783
55784
55785
55786
55787
55788
55789 public function setMessage($message, $name = 'message')
55790 {
55791 $this->messages[$name] = $message;
55792 }
55793
55794 public function getMessage($name = 'message')
55795 {
55796 return $this->messages[$name];
55797 }
55798
55799
55800
55801
55802
55803
55804 public function getStartTime()
55805 {
55806 return $this->startTime;
55807 }
55808
55809
55810
55811
55812
55813
55814 public function getMaxSteps()
55815 {
55816 return $this->max;
55817 }
55818
55819
55820
55821
55822
55823
55824
55825
55826 public function getStep()
55827 {
55828 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the getProgress() method instead.', E_USER_DEPRECATED);
55829
55830 return $this->getProgress();
55831 }
55832
55833
55834
55835
55836
55837
55838 public function getProgress()
55839 {
55840 return $this->step;
55841 }
55842
55843
55844
55845
55846
55847
55848
55849
55850 public function getStepWidth()
55851 {
55852 return $this->stepWidth;
55853 }
55854
55855
55856
55857
55858
55859
55860 public function getProgressPercent()
55861 {
55862 return $this->percent;
55863 }
55864
55865
55866
55867
55868
55869
55870 public function setBarWidth($size)
55871 {
55872 $this->barWidth = (int) $size;
55873 }
55874
55875
55876
55877
55878
55879
55880 public function getBarWidth()
55881 {
55882 return $this->barWidth;
55883 }
55884
55885
55886
55887
55888
55889
55890 public function setBarCharacter($char)
55891 {
55892 $this->barChar = $char;
55893 }
55894
55895
55896
55897
55898
55899
55900 public function getBarCharacter()
55901 {
55902 if (null === $this->barChar) {
55903 return $this->max ? '=' : $this->emptyBarChar;
55904 }
55905
55906 return $this->barChar;
55907 }
55908
55909
55910
55911
55912
55913
55914 public function setEmptyBarCharacter($char)
55915 {
55916 $this->emptyBarChar = $char;
55917 }
55918
55919
55920
55921
55922
55923
55924 public function getEmptyBarCharacter()
55925 {
55926 return $this->emptyBarChar;
55927 }
55928
55929
55930
55931
55932
55933
55934 public function setProgressCharacter($char)
55935 {
55936 $this->progressChar = $char;
55937 }
55938
55939
55940
55941
55942
55943
55944 public function getProgressCharacter()
55945 {
55946 return $this->progressChar;
55947 }
55948
55949
55950
55951
55952
55953
55954 public function setFormat($format)
55955 {
55956 $this->format = null;
55957 $this->internalFormat = $format;
55958 }
55959
55960
55961
55962
55963
55964
55965 public function setRedrawFrequency($freq)
55966 {
55967 $this->redrawFreq = max((int) $freq, 1);
55968 }
55969
55970
55971
55972
55973
55974
55975 public function start($max = null)
55976 {
55977 $this->startTime = time();
55978 $this->step = 0;
55979 $this->percent = 0.0;
55980
55981 if (null !== $max) {
55982 $this->setMaxSteps($max);
55983 }
55984
55985 $this->display();
55986 }
55987
55988
55989
55990
55991
55992
55993
55994
55995 public function advance($step = 1)
55996 {
55997 $this->setProgress($this->step + $step);
55998 }
55999
56000
56001
56002
56003
56004
56005
56006
56007
56008
56009 public function setCurrent($step)
56010 {
56011 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the setProgress() method instead.', E_USER_DEPRECATED);
56012
56013 $this->setProgress($step);
56014 }
56015
56016
56017
56018
56019
56020
56021 public function setOverwrite($overwrite)
56022 {
56023 $this->overwrite = (bool) $overwrite;
56024 }
56025
56026
56027
56028
56029
56030
56031
56032
56033 public function setProgress($step)
56034 {
56035 $step = (int) $step;
56036 if ($step < $this->step) {
56037 throw new LogicException('You can\'t regress the progress bar.');
56038 }
56039
56040 if ($this->max && $step > $this->max) {
56041 $this->max = $step;
56042 }
56043
56044 $prevPeriod = (int) ($this->step / $this->redrawFreq);
56045 $currPeriod = (int) ($step / $this->redrawFreq);
56046 $this->step = $step;
56047 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
56048 if ($prevPeriod !== $currPeriod || $this->max === $step) {
56049 $this->display();
56050 }
56051 }
56052
56053
56054
56055
56056 public function finish()
56057 {
56058 if (!$this->max) {
56059 $this->max = $this->step;
56060 }
56061
56062 if ($this->step === $this->max && !$this->overwrite) {
56063
56064  return;
56065 }
56066
56067 $this->setProgress($this->max);
56068 }
56069
56070
56071
56072
56073 public function display()
56074 {
56075 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
56076 return;
56077 }
56078
56079 if (null === $this->format) {
56080 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
56081 }
56082
56083
56084  $self = $this;
56085 $output = $this->output;
56086 $messages = $this->messages;
56087 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
56088 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
56089 $text = \call_user_func($formatter, $self, $output);
56090 } elseif (isset($messages[$matches[1]])) {
56091 $text = $messages[$matches[1]];
56092 } else {
56093 return $matches[0];
56094 }
56095
56096 if (isset($matches[2])) {
56097 $text = sprintf('%'.$matches[2], $text);
56098 }
56099
56100 return $text;
56101 }, $this->format));
56102 }
56103
56104
56105
56106
56107
56108
56109
56110
56111 public function clear()
56112 {
56113 if (!$this->overwrite) {
56114 return;
56115 }
56116
56117 if (null === $this->format) {
56118 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
56119 }
56120
56121 $this->overwrite('');
56122 }
56123
56124
56125
56126
56127
56128
56129 private function setRealFormat($format)
56130 {
56131
56132  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
56133 $this->format = self::getFormatDefinition($format.'_nomax');
56134 } elseif (null !== self::getFormatDefinition($format)) {
56135 $this->format = self::getFormatDefinition($format);
56136 } else {
56137 $this->format = $format;
56138 }
56139
56140 $this->formatLineCount = substr_count($this->format, "\n");
56141 }
56142
56143
56144
56145
56146
56147
56148 private function setMaxSteps($max)
56149 {
56150 $this->max = max(0, (int) $max);
56151 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
56152 }
56153
56154
56155
56156
56157
56158
56159 private function overwrite($message)
56160 {
56161 if ($this->overwrite) {
56162 if (!$this->firstRun) {
56163
56164  $this->output->write("\x0D");
56165
56166
56167  $this->output->write("\x1B[2K");
56168
56169
56170  if ($this->formatLineCount > 0) {
56171 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
56172 }
56173 }
56174 } elseif ($this->step > 0) {
56175 $this->output->writeln('');
56176 }
56177
56178 $this->firstRun = false;
56179
56180 $this->output->write($message);
56181 }
56182
56183 private function determineBestFormat()
56184 {
56185 switch ($this->output->getVerbosity()) {
56186
56187  case OutputInterface::VERBOSITY_VERBOSE:
56188 return $this->max ? 'verbose' : 'verbose_nomax';
56189 case OutputInterface::VERBOSITY_VERY_VERBOSE:
56190 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
56191 case OutputInterface::VERBOSITY_DEBUG:
56192 return $this->max ? 'debug' : 'debug_nomax';
56193 default:
56194 return $this->max ? 'normal' : 'normal_nomax';
56195 }
56196 }
56197
56198 private static function initPlaceholderFormatters()
56199 {
56200 return array(
56201 'bar' => function (ProgressBar $bar, OutputInterface $output) {
56202 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
56203 $display = str_repeat($bar->getBarCharacter(), $completeBars);
56204 if ($completeBars < $bar->getBarWidth()) {
56205 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
56206 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
56207 }
56208
56209 return $display;
56210 },
56211 'elapsed' => function (ProgressBar $bar) {
56212 return Helper::formatTime(time() - $bar->getStartTime());
56213 },
56214 'remaining' => function (ProgressBar $bar) {
56215 if (!$bar->getMaxSteps()) {
56216 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
56217 }
56218
56219 if (!$bar->getProgress()) {
56220 $remaining = 0;
56221 } else {
56222 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
56223 }
56224
56225 return Helper::formatTime($remaining);
56226 },
56227 'estimated' => function (ProgressBar $bar) {
56228 if (!$bar->getMaxSteps()) {
56229 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
56230 }
56231
56232 if (!$bar->getProgress()) {
56233 $estimated = 0;
56234 } else {
56235 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
56236 }
56237
56238 return Helper::formatTime($estimated);
56239 },
56240 'memory' => function (ProgressBar $bar) {
56241 return Helper::formatMemory(memory_get_usage(true));
56242 },
56243 'current' => function (ProgressBar $bar) {
56244 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
56245 },
56246 'max' => function (ProgressBar $bar) {
56247 return $bar->getMaxSteps();
56248 },
56249 'percent' => function (ProgressBar $bar) {
56250 return floor($bar->getProgressPercent() * 100);
56251 },
56252 );
56253 }
56254
56255 private static function initFormats()
56256 {
56257 return array(
56258 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
56259 'normal_nomax' => ' %current% [%bar%]',
56260
56261 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
56262 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
56263
56264 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
56265 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
56266
56267 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
56268 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
56269 );
56270 }
56271 }
56272 <?php
56273
56274
56275
56276
56277
56278
56279
56280
56281
56282
56283 namespace Symfony\Component\Console\Helper;
56284
56285 use Symfony\Component\Console\Exception\LogicException;
56286 use Symfony\Component\Console\Output\ConsoleOutputInterface;
56287 use Symfony\Component\Console\Output\NullOutput;
56288 use Symfony\Component\Console\Output\OutputInterface;
56289
56290
56291
56292
56293
56294
56295
56296
56297
56298
56299 class ProgressHelper extends Helper
56300 {
56301 const FORMAT_QUIET = ' %percent%%';
56302 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
56303 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
56304 const FORMAT_QUIET_NOMAX = ' %current%';
56305 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
56306 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
56307
56308
56309  private $barWidth = 28;
56310 private $barChar = '=';
56311 private $emptyBarChar = '-';
56312 private $progressChar = '>';
56313 private $format = null;
56314 private $redrawFreq = 1;
56315
56316 private $lastMessagesLength;
56317 private $barCharOriginal;
56318
56319
56320
56321
56322 private $output;
56323
56324
56325
56326
56327
56328
56329 private $current;
56330
56331
56332
56333
56334
56335
56336 private $max;
56337
56338
56339
56340
56341
56342
56343 private $startTime;
56344
56345
56346
56347
56348
56349
56350 private $defaultFormatVars = array(
56351 'current',
56352 'max',
56353 'bar',
56354 'percent',
56355 'elapsed',
56356 );
56357
56358
56359
56360
56361
56362
56363 private $formatVars;
56364
56365
56366
56367
56368
56369
56370 private $widths = array(
56371 'current' => 4,
56372 'max' => 4,
56373 'percent' => 3,
56374 'elapsed' => 6,
56375 );
56376
56377
56378
56379
56380
56381
56382 private $timeFormats = array(
56383 array(0, '???'),
56384 array(2, '1 sec'),
56385 array(59, 'secs', 1),
56386 array(60, '1 min'),
56387 array(3600, 'mins', 60),
56388 array(5400, '1 hr'),
56389 array(86400, 'hrs', 3600),
56390 array(129600, '1 day'),
56391 array(604800, 'days', 86400),
56392 );
56393
56394 public function __construct($triggerDeprecationError = true)
56395 {
56396 if ($triggerDeprecationError) {
56397 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\ProgressBar class instead.', E_USER_DEPRECATED);
56398 }
56399 }
56400
56401
56402
56403
56404
56405
56406 public function setBarWidth($size)
56407 {
56408 $this->barWidth = (int) $size;
56409 }
56410
56411
56412
56413
56414
56415
56416 public function setBarCharacter($char)
56417 {
56418 $this->barChar = $char;
56419 }
56420
56421
56422
56423
56424
56425
56426 public function setEmptyBarCharacter($char)
56427 {
56428 $this->emptyBarChar = $char;
56429 }
56430
56431
56432
56433
56434
56435
56436 public function setProgressCharacter($char)
56437 {
56438 $this->progressChar = $char;
56439 }
56440
56441
56442
56443
56444
56445
56446 public function setFormat($format)
56447 {
56448 $this->format = $format;
56449 }
56450
56451
56452
56453
56454
56455
56456 public function setRedrawFrequency($freq)
56457 {
56458 $this->redrawFreq = (int) $freq;
56459 }
56460
56461
56462
56463
56464
56465
56466
56467 public function start(OutputInterface $output, $max = null)
56468 {
56469 if ($output instanceof ConsoleOutputInterface) {
56470 $output = $output->getErrorOutput();
56471 }
56472
56473 $this->startTime = time();
56474 $this->current = 0;
56475 $this->max = (int) $max;
56476
56477
56478  $this->output = $output->isDecorated() ? $output : new NullOutput();
56479 $this->lastMessagesLength = 0;
56480 $this->barCharOriginal = '';
56481
56482 if (null === $this->format) {
56483 switch ($output->getVerbosity()) {
56484 case OutputInterface::VERBOSITY_QUIET:
56485 $this->format = self::FORMAT_QUIET_NOMAX;
56486 if ($this->max > 0) {
56487 $this->format = self::FORMAT_QUIET;
56488 }
56489 break;
56490 case OutputInterface::VERBOSITY_VERBOSE:
56491 case OutputInterface::VERBOSITY_VERY_VERBOSE:
56492 case OutputInterface::VERBOSITY_DEBUG:
56493 $this->format = self::FORMAT_VERBOSE_NOMAX;
56494 if ($this->max > 0) {
56495 $this->format = self::FORMAT_VERBOSE;
56496 }
56497 break;
56498 default:
56499 $this->format = self::FORMAT_NORMAL_NOMAX;
56500 if ($this->max > 0) {
56501 $this->format = self::FORMAT_NORMAL;
56502 }
56503 break;
56504 }
56505 }
56506
56507 $this->initialize();
56508 }
56509
56510
56511
56512
56513
56514
56515
56516
56517
56518 public function advance($step = 1, $redraw = false)
56519 {
56520 $this->setCurrent($this->current + $step, $redraw);
56521 }
56522
56523
56524
56525
56526
56527
56528
56529
56530
56531 public function setCurrent($current, $redraw = false)
56532 {
56533 if (null === $this->startTime) {
56534 throw new LogicException('You must start the progress bar before calling setCurrent().');
56535 }
56536
56537 $current = (int) $current;
56538
56539 if ($current < $this->current) {
56540 throw new LogicException('You can\'t regress the progress bar');
56541 }
56542
56543 if (0 === $this->current) {
56544 $redraw = true;
56545 }
56546
56547 $prevPeriod = (int) ($this->current / $this->redrawFreq);
56548
56549 $this->current = $current;
56550
56551 $currPeriod = (int) ($this->current / $this->redrawFreq);
56552 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
56553 $this->display();
56554 }
56555 }
56556
56557
56558
56559
56560
56561
56562
56563
56564 public function display($finish = false)
56565 {
56566 if (null === $this->startTime) {
56567 throw new LogicException('You must start the progress bar before calling display().');
56568 }
56569
56570 $message = $this->format;
56571 foreach ($this->generate($finish) as $name => $value) {
56572 $message = str_replace("%{$name}%", $value, $message);
56573 }
56574 $this->overwrite($this->output, $message);
56575 }
56576
56577
56578
56579
56580
56581
56582
56583
56584 public function clear()
56585 {
56586 $this->overwrite($this->output, '');
56587 }
56588
56589
56590
56591
56592 public function finish()
56593 {
56594 if (null === $this->startTime) {
56595 throw new LogicException('You must start the progress bar before calling finish().');
56596 }
56597
56598 if (null !== $this->startTime) {
56599 if (!$this->max) {
56600 $this->barChar = $this->barCharOriginal;
56601 $this->display(true);
56602 }
56603 $this->startTime = null;
56604 $this->output->writeln('');
56605 $this->output = null;
56606 }
56607 }
56608
56609
56610
56611
56612 private function initialize()
56613 {
56614 $this->formatVars = array();
56615 foreach ($this->defaultFormatVars as $var) {
56616 if (false !== strpos($this->format, "%{$var}%")) {
56617 $this->formatVars[$var] = true;
56618 }
56619 }
56620
56621 if ($this->max > 0) {
56622 $this->widths['max'] = $this->strlen($this->max);
56623 $this->widths['current'] = $this->widths['max'];
56624 } else {
56625 $this->barCharOriginal = $this->barChar;
56626 $this->barChar = $this->emptyBarChar;
56627 }
56628 }
56629
56630
56631
56632
56633
56634
56635
56636
56637 private function generate($finish = false)
56638 {
56639 $vars = array();
56640 $percent = 0;
56641 if ($this->max > 0) {
56642 $percent = (float) $this->current / $this->max;
56643 }
56644
56645 if (isset($this->formatVars['bar'])) {
56646 if ($this->max > 0) {
56647 $completeBars = floor($percent * $this->barWidth);
56648 } else {
56649 if (!$finish) {
56650 $completeBars = floor($this->current % $this->barWidth);
56651 } else {
56652 $completeBars = $this->barWidth;
56653 }
56654 }
56655
56656 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
56657 $bar = str_repeat($this->barChar, $completeBars);
56658 if ($completeBars < $this->barWidth) {
56659 $bar .= $this->progressChar;
56660 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
56661 }
56662
56663 $vars['bar'] = $bar;
56664 }
56665
56666 if (isset($this->formatVars['elapsed'])) {
56667 $elapsed = time() - $this->startTime;
56668 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
56669 }
56670
56671 if (isset($this->formatVars['current'])) {
56672 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
56673 }
56674
56675 if (isset($this->formatVars['max'])) {
56676 $vars['max'] = $this->max;
56677 }
56678
56679 if (isset($this->formatVars['percent'])) {
56680 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
56681 }
56682
56683 return $vars;
56684 }
56685
56686
56687
56688
56689
56690
56691
56692
56693 private function humaneTime($secs)
56694 {
56695 $text = '';
56696 foreach ($this->timeFormats as $format) {
56697 if ($secs < $format[0]) {
56698 if (2 == \count($format)) {
56699 $text = $format[1];
56700 break;
56701 } else {
56702 $text = ceil($secs / $format[2]).' '.$format[1];
56703 break;
56704 }
56705 }
56706 }
56707
56708 return $text;
56709 }
56710
56711
56712
56713
56714
56715
56716
56717 private function overwrite(OutputInterface $output, $message)
56718 {
56719 $length = $this->strlen($message);
56720
56721
56722  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
56723 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
56724 }
56725
56726
56727  $output->write("\x0D");
56728 $output->write($message);
56729
56730 $this->lastMessagesLength = $this->strlen($message);
56731 }
56732
56733
56734
56735
56736 public function getName()
56737 {
56738 return 'progress';
56739 }
56740 }
56741 <?php
56742
56743
56744
56745
56746
56747
56748
56749
56750
56751
56752 namespace Symfony\Component\Console\Helper;
56753
56754 use Symfony\Component\Console\Exception\InvalidArgumentException;
56755 use Symfony\Component\Console\Exception\LogicException;
56756 use Symfony\Component\Console\Output\OutputInterface;
56757
56758
56759
56760
56761 class ProgressIndicator
56762 {
56763 private $output;
56764 private $startTime;
56765 private $format;
56766 private $message;
56767 private $indicatorValues;
56768 private $indicatorCurrent;
56769 private $indicatorChangeInterval;
56770 private $indicatorUpdateTime;
56771 private $started = false;
56772
56773 private static $formatters;
56774 private static $formats;
56775
56776
56777
56778
56779
56780
56781
56782 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
56783 {
56784 $this->output = $output;
56785
56786 if (null === $format) {
56787 $format = $this->determineBestFormat();
56788 }
56789
56790 if (null === $indicatorValues) {
56791 $indicatorValues = array('-', '\\', '|', '/');
56792 }
56793
56794 $indicatorValues = array_values($indicatorValues);
56795
56796 if (2 > \count($indicatorValues)) {
56797 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
56798 }
56799
56800 $this->format = self::getFormatDefinition($format);
56801 $this->indicatorChangeInterval = $indicatorChangeInterval;
56802 $this->indicatorValues = $indicatorValues;
56803 $this->startTime = time();
56804 }
56805
56806
56807
56808
56809
56810
56811 public function setMessage($message)
56812 {
56813 $this->message = $message;
56814
56815 $this->display();
56816 }
56817
56818
56819
56820
56821
56822
56823
56824
56825 public function getMessage()
56826 {
56827 return $this->message;
56828 }
56829
56830
56831
56832
56833
56834
56835
56836
56837 public function getStartTime()
56838 {
56839 return $this->startTime;
56840 }
56841
56842
56843
56844
56845
56846
56847
56848
56849 public function getCurrentValue()
56850 {
56851 return $this->indicatorValues[$this->indicatorCurrent % \count($this->indicatorValues)];
56852 }
56853
56854
56855
56856
56857
56858
56859 public function start($message)
56860 {
56861 if ($this->started) {
56862 throw new LogicException('Progress indicator already started.');
56863 }
56864
56865 $this->message = $message;
56866 $this->started = true;
56867 $this->startTime = time();
56868 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
56869 $this->indicatorCurrent = 0;
56870
56871 $this->display();
56872 }
56873
56874
56875
56876
56877 public function advance()
56878 {
56879 if (!$this->started) {
56880 throw new LogicException('Progress indicator has not yet been started.');
56881 }
56882
56883 if (!$this->output->isDecorated()) {
56884 return;
56885 }
56886
56887 $currentTime = $this->getCurrentTimeInMilliseconds();
56888
56889 if ($currentTime < $this->indicatorUpdateTime) {
56890 return;
56891 }
56892
56893 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
56894 ++$this->indicatorCurrent;
56895
56896 $this->display();
56897 }
56898
56899
56900
56901
56902
56903
56904 public function finish($message)
56905 {
56906 if (!$this->started) {
56907 throw new LogicException('Progress indicator has not yet been started.');
56908 }
56909
56910 $this->message = $message;
56911 $this->display();
56912 $this->output->writeln('');
56913 $this->started = false;
56914 }
56915
56916
56917
56918
56919
56920
56921
56922
56923 public static function getFormatDefinition($name)
56924 {
56925 if (!self::$formats) {
56926 self::$formats = self::initFormats();
56927 }
56928
56929 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
56930 }
56931
56932
56933
56934
56935
56936
56937
56938
56939
56940 public static function setPlaceholderFormatterDefinition($name, $callable)
56941 {
56942 if (!self::$formatters) {
56943 self::$formatters = self::initPlaceholderFormatters();
56944 }
56945
56946 self::$formatters[$name] = $callable;
56947 }
56948
56949
56950
56951
56952
56953
56954
56955
56956 public static function getPlaceholderFormatterDefinition($name)
56957 {
56958 if (!self::$formatters) {
56959 self::$formatters = self::initPlaceholderFormatters();
56960 }
56961
56962 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
56963 }
56964
56965 private function display()
56966 {
56967 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
56968 return;
56969 }
56970
56971 $self = $this;
56972
56973 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
56974 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
56975 return \call_user_func($formatter, $self);
56976 }
56977
56978 return $matches[0];
56979 }, $this->format));
56980 }
56981
56982 private function determineBestFormat()
56983 {
56984 switch ($this->output->getVerbosity()) {
56985
56986  case OutputInterface::VERBOSITY_VERBOSE:
56987 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
56988 case OutputInterface::VERBOSITY_VERY_VERBOSE:
56989 case OutputInterface::VERBOSITY_DEBUG:
56990 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
56991 default:
56992 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
56993 }
56994 }
56995
56996
56997
56998
56999
57000
57001 private function overwrite($message)
57002 {
57003 if ($this->output->isDecorated()) {
57004 $this->output->write("\x0D\x1B[2K");
57005 $this->output->write($message);
57006 } else {
57007 $this->output->writeln($message);
57008 }
57009 }
57010
57011 private function getCurrentTimeInMilliseconds()
57012 {
57013 return round(microtime(true) * 1000);
57014 }
57015
57016 private static function initPlaceholderFormatters()
57017 {
57018 return array(
57019 'indicator' => function (ProgressIndicator $indicator) {
57020 return $indicator->getCurrentValue();
57021 },
57022 'message' => function (ProgressIndicator $indicator) {
57023 return $indicator->getMessage();
57024 },
57025 'elapsed' => function (ProgressIndicator $indicator) {
57026 return Helper::formatTime(time() - $indicator->getStartTime());
57027 },
57028 'memory' => function () {
57029 return Helper::formatMemory(memory_get_usage(true));
57030 },
57031 );
57032 }
57033
57034 private static function initFormats()
57035 {
57036 return array(
57037 'normal' => ' %indicator% %message%',
57038 'normal_no_ansi' => ' %message%',
57039
57040 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
57041 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
57042
57043 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
57044 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
57045 );
57046 }
57047 }
57048 <?php
57049
57050
57051
57052
57053
57054
57055
57056
57057
57058
57059 namespace Symfony\Component\Console\Helper;
57060
57061 use Symfony\Component\Console\Exception\InvalidArgumentException;
57062 use Symfony\Component\Console\Exception\RuntimeException;
57063 use Symfony\Component\Console\Formatter\OutputFormatter;
57064 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
57065 use Symfony\Component\Console\Input\InputInterface;
57066 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57067 use Symfony\Component\Console\Output\OutputInterface;
57068 use Symfony\Component\Console\Question\ChoiceQuestion;
57069 use Symfony\Component\Console\Question\Question;
57070
57071
57072
57073
57074
57075
57076 class QuestionHelper extends Helper
57077 {
57078 private $inputStream;
57079 private static $shell;
57080 private static $stty;
57081
57082
57083
57084
57085
57086
57087
57088
57089 public function ask(InputInterface $input, OutputInterface $output, Question $question)
57090 {
57091 if ($output instanceof ConsoleOutputInterface) {
57092 $output = $output->getErrorOutput();
57093 }
57094
57095 if (!$input->isInteractive()) {
57096 $default = $question->getDefault();
57097
57098 if (null !== $default && $question instanceof ChoiceQuestion) {
57099 $choices = $question->getChoices();
57100
57101 if (!$question->isMultiselect()) {
57102 return isset($choices[$default]) ? $choices[$default] : $default;
57103 }
57104
57105 $default = explode(',', $default);
57106 foreach ($default as $k => $v) {
57107 $v = trim($v);
57108 $default[$k] = isset($choices[$v]) ? $choices[$v] : $v;
57109 }
57110 }
57111
57112 return $default;
57113 }
57114
57115 if (!$question->getValidator()) {
57116 return $this->doAsk($output, $question);
57117 }
57118
57119 $that = $this;
57120
57121 $interviewer = function () use ($output, $question, $that) {
57122 return $that->doAsk($output, $question);
57123 };
57124
57125 return $this->validateAttempts($interviewer, $output, $question);
57126 }
57127
57128
57129
57130
57131
57132
57133
57134
57135
57136
57137 public function setInputStream($stream)
57138 {
57139 if (!\is_resource($stream)) {
57140 throw new InvalidArgumentException('Input stream must be a valid resource.');
57141 }
57142
57143 $this->inputStream = $stream;
57144 }
57145
57146
57147
57148
57149
57150
57151 public function getInputStream()
57152 {
57153 return $this->inputStream;
57154 }
57155
57156
57157
57158
57159 public function getName()
57160 {
57161 return 'question';
57162 }
57163
57164
57165
57166
57167
57168
57169
57170
57171
57172
57173 public function doAsk(OutputInterface $output, Question $question)
57174 {
57175 $this->writePrompt($output, $question);
57176
57177 $inputStream = $this->inputStream ?: STDIN;
57178 $autocomplete = $question->getAutocompleterValues();
57179
57180 if (null === $autocomplete || !$this->hasSttyAvailable()) {
57181 $ret = false;
57182 if ($question->isHidden()) {
57183 try {
57184 $ret = trim($this->getHiddenResponse($output, $inputStream));
57185 } catch (RuntimeException $e) {
57186 if (!$question->isHiddenFallback()) {
57187 throw $e;
57188 }
57189 }
57190 }
57191
57192 if (false === $ret) {
57193 $ret = fgets($inputStream, 4096);
57194 if (false === $ret) {
57195 throw new RuntimeException('Aborted');
57196 }
57197 $ret = trim($ret);
57198 }
57199 } else {
57200 $ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
57201 }
57202
57203 $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
57204
57205 if ($normalizer = $question->getNormalizer()) {
57206 return $normalizer($ret);
57207 }
57208
57209 return $ret;
57210 }
57211
57212
57213
57214
57215 protected function writePrompt(OutputInterface $output, Question $question)
57216 {
57217 $message = $question->getQuestion();
57218
57219 if ($question instanceof ChoiceQuestion) {
57220 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
57221
57222 $messages = (array) $question->getQuestion();
57223 foreach ($question->getChoices() as $key => $value) {
57224 $width = $maxWidth - $this->strlen($key);
57225 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
57226 }
57227
57228 $output->writeln($messages);
57229
57230 $message = $question->getPrompt();
57231 }
57232
57233 $output->write($message);
57234 }
57235
57236
57237
57238
57239 protected function writeError(OutputInterface $output, \Exception $error)
57240 {
57241 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
57242 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
57243 } else {
57244 $message = '<error>'.$error->getMessage().'</error>';
57245 }
57246
57247 $output->writeln($message);
57248 }
57249
57250
57251
57252
57253
57254
57255
57256
57257
57258
57259
57260 private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
57261 {
57262 $ret = '';
57263
57264 $i = 0;
57265 $ofs = -1;
57266 $matches = $autocomplete;
57267 $numMatches = \count($matches);
57268
57269 $sttyMode = shell_exec('stty -g');
57270
57271
57272  shell_exec('stty -icanon -echo');
57273
57274
57275  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
57276
57277
57278  while (!feof($inputStream)) {
57279 $c = fread($inputStream, 1);
57280
57281
57282  if ("\177" === $c) {
57283 if (0 === $numMatches && 0 !== $i) {
57284 --$i;
57285
57286  $output->write("\033[1D");
57287 }
57288
57289 if (0 === $i) {
57290 $ofs = -1;
57291 $matches = $autocomplete;
57292 $numMatches = \count($matches);
57293 } else {
57294 $numMatches = 0;
57295 }
57296
57297
57298  $ret = substr($ret, 0, $i);
57299 } elseif ("\033" === $c) {
57300
57301  $c .= fread($inputStream, 2);
57302
57303
57304  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
57305 if ('A' === $c[2] && -1 === $ofs) {
57306 $ofs = 0;
57307 }
57308
57309 if (0 === $numMatches) {
57310 continue;
57311 }
57312
57313 $ofs += ('A' === $c[2]) ? -1 : 1;
57314 $ofs = ($numMatches + $ofs) % $numMatches;
57315 }
57316 } elseif (\ord($c) < 32) {
57317 if ("\t" === $c || "\n" === $c) {
57318 if ($numMatches > 0 && -1 !== $ofs) {
57319 $ret = $matches[$ofs];
57320
57321  $output->write(substr($ret, $i));
57322 $i = \strlen($ret);
57323 }
57324
57325 if ("\n" === $c) {
57326 $output->write($c);
57327 break;
57328 }
57329
57330 $numMatches = 0;
57331 }
57332
57333 continue;
57334 } else {
57335 $output->write($c);
57336 $ret .= $c;
57337 ++$i;
57338
57339 $numMatches = 0;
57340 $ofs = 0;
57341
57342 foreach ($autocomplete as $value) {
57343
57344  if (0 === strpos($value, $ret)) {
57345 $matches[$numMatches++] = $value;
57346 }
57347 }
57348 }
57349
57350
57351  $output->write("\033[K");
57352
57353 if ($numMatches > 0 && -1 !== $ofs) {
57354
57355  $output->write("\0337");
57356
57357  $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
57358
57359  $output->write("\0338");
57360 }
57361 }
57362
57363
57364  shell_exec(sprintf('stty %s', $sttyMode));
57365
57366 return $ret;
57367 }
57368
57369
57370
57371
57372
57373
57374
57375
57376
57377
57378
57379 private function getHiddenResponse(OutputInterface $output, $inputStream)
57380 {
57381 if ('\\' === \DIRECTORY_SEPARATOR) {
57382 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
57383
57384
57385  if ('phar:' === substr(__FILE__, 0, 5)) {
57386 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
57387 copy($exe, $tmpExe);
57388 $exe = $tmpExe;
57389 }
57390
57391 $value = rtrim(shell_exec($exe));
57392 $output->writeln('');
57393
57394 if (isset($tmpExe)) {
57395 unlink($tmpExe);
57396 }
57397
57398 return $value;
57399 }
57400
57401 if ($this->hasSttyAvailable()) {
57402 $sttyMode = shell_exec('stty -g');
57403
57404 shell_exec('stty -echo');
57405 $value = fgets($inputStream, 4096);
57406 shell_exec(sprintf('stty %s', $sttyMode));
57407
57408 if (false === $value) {
57409 throw new RuntimeException('Aborted');
57410 }
57411
57412 $value = trim($value);
57413 $output->writeln('');
57414
57415 return $value;
57416 }
57417
57418 if (false !== $shell = $this->getShell()) {
57419 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
57420 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
57421 $value = rtrim(shell_exec($command));
57422 $output->writeln('');
57423
57424 return $value;
57425 }
57426
57427 throw new RuntimeException('Unable to hide the response.');
57428 }
57429
57430
57431
57432
57433
57434
57435
57436
57437
57438
57439
57440
57441 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
57442 {
57443 $error = null;
57444 $attempts = $question->getMaxAttempts();
57445 while (null === $attempts || $attempts--) {
57446 if (null !== $error) {
57447 $this->writeError($output, $error);
57448 }
57449
57450 try {
57451 return \call_user_func($question->getValidator(), $interviewer());
57452 } catch (RuntimeException $e) {
57453 throw $e;
57454 } catch (\Exception $error) {
57455 }
57456 }
57457
57458 throw $error;
57459 }
57460
57461
57462
57463
57464
57465
57466 private function getShell()
57467 {
57468 if (null !== self::$shell) {
57469 return self::$shell;
57470 }
57471
57472 self::$shell = false;
57473
57474 if (file_exists('/usr/bin/env')) {
57475
57476  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
57477 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
57478 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
57479 self::$shell = $sh;
57480 break;
57481 }
57482 }
57483 }
57484
57485 return self::$shell;
57486 }
57487
57488
57489
57490
57491
57492
57493 private function hasSttyAvailable()
57494 {
57495 if (null !== self::$stty) {
57496 return self::$stty;
57497 }
57498
57499 exec('stty 2>&1', $output, $exitcode);
57500
57501 return self::$stty = 0 === $exitcode;
57502 }
57503 }
57504 <?php
57505
57506
57507
57508
57509
57510
57511
57512
57513
57514
57515 namespace Symfony\Component\Console\Helper;
57516
57517 use Symfony\Component\Console\Exception\LogicException;
57518 use Symfony\Component\Console\Formatter\OutputFormatter;
57519 use Symfony\Component\Console\Input\InputInterface;
57520 use Symfony\Component\Console\Output\OutputInterface;
57521 use Symfony\Component\Console\Question\ChoiceQuestion;
57522 use Symfony\Component\Console\Question\ConfirmationQuestion;
57523 use Symfony\Component\Console\Question\Question;
57524 use Symfony\Component\Console\Style\SymfonyStyle;
57525
57526
57527
57528
57529
57530
57531 class SymfonyQuestionHelper extends QuestionHelper
57532 {
57533
57534
57535
57536 public function ask(InputInterface $input, OutputInterface $output, Question $question)
57537 {
57538 $validator = $question->getValidator();
57539 $question->setValidator(function ($value) use ($validator) {
57540 if (null !== $validator) {
57541 $value = $validator($value);
57542 } else {
57543
57544  if (!\is_array($value) && !\is_bool($value) && 0 === \strlen($value)) {
57545 throw new LogicException('A value is required.');
57546 }
57547 }
57548
57549 return $value;
57550 });
57551
57552 return parent::ask($input, $output, $question);
57553 }
57554
57555
57556
57557
57558 protected function writePrompt(OutputInterface $output, Question $question)
57559 {
57560 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
57561 $default = $question->getDefault();
57562
57563 switch (true) {
57564 case null === $default:
57565 $text = sprintf(' <info>%s</info>:', $text);
57566
57567 break;
57568
57569 case $question instanceof ConfirmationQuestion:
57570 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
57571
57572 break;
57573
57574 case $question instanceof ChoiceQuestion && $question->isMultiselect():
57575 $choices = $question->getChoices();
57576 $default = explode(',', $default);
57577
57578 foreach ($default as $key => $value) {
57579 $default[$key] = $choices[trim($value)];
57580 }
57581
57582 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
57583
57584 break;
57585
57586 case $question instanceof ChoiceQuestion:
57587 $choices = $question->getChoices();
57588 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default));
57589
57590 break;
57591
57592 default:
57593 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
57594 }
57595
57596 $output->writeln($text);
57597
57598 if ($question instanceof ChoiceQuestion) {
57599 $width = max(array_map('strlen', array_keys($question->getChoices())));
57600
57601 foreach ($question->getChoices() as $key => $value) {
57602 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
57603 }
57604 }
57605
57606 $output->write(' > ');
57607 }
57608
57609
57610
57611
57612 protected function writeError(OutputInterface $output, \Exception $error)
57613 {
57614 if ($output instanceof SymfonyStyle) {
57615 $output->newLine();
57616 $output->error($error->getMessage());
57617
57618 return;
57619 }
57620
57621 parent::writeError($output, $error);
57622 }
57623 }
57624 <?php
57625
57626
57627
57628
57629
57630
57631
57632
57633
57634
57635 namespace Symfony\Component\Console\Helper;
57636
57637 use Symfony\Component\Console\Exception\InvalidArgumentException;
57638 use Symfony\Component\Console\Output\OutputInterface;
57639
57640
57641
57642
57643
57644
57645
57646
57647
57648 class Table
57649 {
57650
57651
57652
57653 private $headers = array();
57654
57655
57656
57657
57658 private $rows = array();
57659
57660
57661
57662
57663 private $columnWidths = array();
57664
57665
57666
57667
57668
57669
57670 private $numberOfColumns;
57671
57672
57673
57674
57675 private $output;
57676
57677
57678
57679
57680 private $style;
57681
57682
57683
57684
57685 private $columnStyles = array();
57686
57687 private static $styles;
57688
57689 public function __construct(OutputInterface $output)
57690 {
57691 $this->output = $output;
57692
57693 if (!self::$styles) {
57694 self::$styles = self::initStyles();
57695 }
57696
57697 $this->setStyle('default');
57698 }
57699
57700
57701
57702
57703
57704
57705
57706 public static function setStyleDefinition($name, TableStyle $style)
57707 {
57708 if (!self::$styles) {
57709 self::$styles = self::initStyles();
57710 }
57711
57712 self::$styles[$name] = $style;
57713 }
57714
57715
57716
57717
57718
57719
57720
57721
57722 public static function getStyleDefinition($name)
57723 {
57724 if (!self::$styles) {
57725 self::$styles = self::initStyles();
57726 }
57727
57728 if (isset(self::$styles[$name])) {
57729 return self::$styles[$name];
57730 }
57731
57732 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
57733 }
57734
57735
57736
57737
57738
57739
57740
57741
57742 public function setStyle($name)
57743 {
57744 $this->style = $this->resolveStyle($name);
57745
57746 return $this;
57747 }
57748
57749
57750
57751
57752
57753
57754 public function getStyle()
57755 {
57756 return $this->style;
57757 }
57758
57759
57760
57761
57762
57763
57764
57765
57766
57767 public function setColumnStyle($columnIndex, $name)
57768 {
57769 $columnIndex = (int) $columnIndex;
57770
57771 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
57772
57773 return $this;
57774 }
57775
57776
57777
57778
57779
57780
57781
57782
57783
57784
57785 public function getColumnStyle($columnIndex)
57786 {
57787 if (isset($this->columnStyles[$columnIndex])) {
57788 return $this->columnStyles[$columnIndex];
57789 }
57790
57791 return $this->getStyle();
57792 }
57793
57794 public function setHeaders(array $headers)
57795 {
57796 $headers = array_values($headers);
57797 if (!empty($headers) && !\is_array($headers[0])) {
57798 $headers = array($headers);
57799 }
57800
57801 $this->headers = $headers;
57802
57803 return $this;
57804 }
57805
57806 public function setRows(array $rows)
57807 {
57808 $this->rows = array();
57809
57810 return $this->addRows($rows);
57811 }
57812
57813 public function addRows(array $rows)
57814 {
57815 foreach ($rows as $row) {
57816 $this->addRow($row);
57817 }
57818
57819 return $this;
57820 }
57821
57822 public function addRow($row)
57823 {
57824 if ($row instanceof TableSeparator) {
57825 $this->rows[] = $row;
57826
57827 return $this;
57828 }
57829
57830 if (!\is_array($row)) {
57831 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
57832 }
57833
57834 $this->rows[] = array_values($row);
57835
57836 return $this;
57837 }
57838
57839 public function setRow($column, array $row)
57840 {
57841 $this->rows[$column] = $row;
57842
57843 return $this;
57844 }
57845
57846
57847
57848
57849
57850
57851
57852
57853
57854
57855
57856
57857
57858
57859 public function render()
57860 {
57861 $this->calculateNumberOfColumns();
57862 $rows = $this->buildTableRows($this->rows);
57863 $headers = $this->buildTableRows($this->headers);
57864
57865 $this->calculateColumnsWidth(array_merge($headers, $rows));
57866
57867 $this->renderRowSeparator();
57868 if (!empty($headers)) {
57869 foreach ($headers as $header) {
57870 $this->renderRow($header, $this->style->getCellHeaderFormat());
57871 $this->renderRowSeparator();
57872 }
57873 }
57874 foreach ($rows as $row) {
57875 if ($row instanceof TableSeparator) {
57876 $this->renderRowSeparator();
57877 } else {
57878 $this->renderRow($row, $this->style->getCellRowFormat());
57879 }
57880 }
57881 if (!empty($rows)) {
57882 $this->renderRowSeparator();
57883 }
57884
57885 $this->cleanup();
57886 }
57887
57888
57889
57890
57891
57892
57893
57894
57895 private function renderRowSeparator()
57896 {
57897 if (0 === $count = $this->numberOfColumns) {
57898 return;
57899 }
57900
57901 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
57902 return;
57903 }
57904
57905 $markup = $this->style->getCrossingChar();
57906 for ($column = 0; $column < $count; ++$column) {
57907 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
57908 }
57909
57910 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
57911 }
57912
57913
57914
57915
57916 private function renderColumnSeparator()
57917 {
57918 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
57919 }
57920
57921
57922
57923
57924
57925
57926
57927
57928
57929
57930
57931 private function renderRow(array $row, $cellFormat)
57932 {
57933 if (empty($row)) {
57934 return;
57935 }
57936
57937 $rowContent = $this->renderColumnSeparator();
57938 foreach ($this->getRowColumns($row) as $column) {
57939 $rowContent .= $this->renderCell($row, $column, $cellFormat);
57940 $rowContent .= $this->renderColumnSeparator();
57941 }
57942 $this->output->writeln($rowContent);
57943 }
57944
57945
57946
57947
57948
57949
57950
57951
57952 private function renderCell(array $row, $column, $cellFormat)
57953 {
57954 $cell = isset($row[$column]) ? $row[$column] : '';
57955 $width = $this->columnWidths[$column];
57956 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
57957
57958  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
57959 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
57960 }
57961 }
57962
57963
57964  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
57965 $width += \strlen($cell) - mb_strwidth($cell, $encoding);
57966 }
57967
57968 $style = $this->getColumnStyle($column);
57969
57970 if ($cell instanceof TableSeparator) {
57971 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
57972 }
57973
57974 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
57975 $content = sprintf($style->getCellRowContentFormat(), $cell);
57976
57977 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
57978 }
57979
57980
57981
57982
57983 private function calculateNumberOfColumns()
57984 {
57985 if (null !== $this->numberOfColumns) {
57986 return;
57987 }
57988
57989 $columns = array(0);
57990 foreach (array_merge($this->headers, $this->rows) as $row) {
57991 if ($row instanceof TableSeparator) {
57992 continue;
57993 }
57994
57995 $columns[] = $this->getNumberOfColumns($row);
57996 }
57997
57998 $this->numberOfColumns = max($columns);
57999 }
58000
58001 private function buildTableRows($rows)
58002 {
58003 $unmergedRows = array();
58004 for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
58005 $rows = $this->fillNextRows($rows, $rowKey);
58006
58007
58008  foreach ($rows[$rowKey] as $column => $cell) {
58009 if (!strstr($cell, "\n")) {
58010 continue;
58011 }
58012 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
58013 foreach ($lines as $lineKey => $line) {
58014 if ($cell instanceof TableCell) {
58015 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
58016 }
58017 if (0 === $lineKey) {
58018 $rows[$rowKey][$column] = $line;
58019 } else {
58020 $unmergedRows[$rowKey][$lineKey][$column] = $line;
58021 }
58022 }
58023 }
58024 }
58025
58026 $tableRows = array();
58027 foreach ($rows as $rowKey => $row) {
58028 $tableRows[] = $this->fillCells($row);
58029 if (isset($unmergedRows[$rowKey])) {
58030 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
58031 }
58032 }
58033
58034 return $tableRows;
58035 }
58036
58037
58038
58039
58040
58041
58042
58043
58044
58045 private function fillNextRows(array $rows, $line)
58046 {
58047 $unmergedRows = array();
58048 foreach ($rows[$line] as $column => $cell) {
58049 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
58050 $nbLines = $cell->getRowspan() - 1;
58051 $lines = array($cell);
58052 if (strstr($cell, "\n")) {
58053 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
58054 $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
58055
58056 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
58057 unset($lines[0]);
58058 }
58059
58060
58061  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
58062 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
58063 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
58064 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
58065 if ($nbLines === $unmergedRowKey - $line) {
58066 break;
58067 }
58068 }
58069 }
58070 }
58071
58072 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
58073
58074  if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
58075 foreach ($unmergedRow as $cellKey => $cell) {
58076
58077  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
58078 }
58079 } else {
58080 $row = $this->copyRow($rows, $unmergedRowKey - 1);
58081 foreach ($unmergedRow as $column => $cell) {
58082 if (!empty($cell)) {
58083 $row[$column] = $unmergedRow[$column];
58084 }
58085 }
58086 array_splice($rows, $unmergedRowKey, 0, array($row));
58087 }
58088 }
58089
58090 return $rows;
58091 }
58092
58093
58094
58095
58096
58097
58098 private function fillCells($row)
58099 {
58100 $newRow = array();
58101 foreach ($row as $column => $cell) {
58102 $newRow[] = $cell;
58103 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
58104 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
58105
58106  $newRow[] = '';
58107 }
58108 }
58109 }
58110
58111 return $newRow ?: $row;
58112 }
58113
58114
58115
58116
58117
58118
58119
58120 private function copyRow(array $rows, $line)
58121 {
58122 $row = $rows[$line];
58123 foreach ($row as $cellKey => $cellValue) {
58124 $row[$cellKey] = '';
58125 if ($cellValue instanceof TableCell) {
58126 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
58127 }
58128 }
58129
58130 return $row;
58131 }
58132
58133
58134
58135
58136
58137
58138 private function getNumberOfColumns(array $row)
58139 {
58140 $columns = \count($row);
58141 foreach ($row as $column) {
58142 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
58143 }
58144
58145 return $columns;
58146 }
58147
58148
58149
58150
58151
58152
58153 private function getRowColumns(array $row)
58154 {
58155 $columns = range(0, $this->numberOfColumns - 1);
58156 foreach ($row as $cellKey => $cell) {
58157 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
58158
58159  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
58160 }
58161 }
58162
58163 return $columns;
58164 }
58165
58166
58167
58168
58169
58170
58171 private function calculateColumnsWidth($rows)
58172 {
58173 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
58174 $lengths = array();
58175 foreach ($rows as $row) {
58176 if ($row instanceof TableSeparator) {
58177 continue;
58178 }
58179
58180 foreach ($row as $i => $cell) {
58181 if ($cell instanceof TableCell) {
58182 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
58183 $textLength = Helper::strlen($textContent);
58184 if ($textLength > 0) {
58185 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
58186 foreach ($contentColumns as $position => $content) {
58187 $row[$i + $position] = $content;
58188 }
58189 }
58190 }
58191 }
58192
58193 $lengths[] = $this->getCellWidth($row, $column);
58194 }
58195
58196 $this->columnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2;
58197 }
58198 }
58199
58200
58201
58202
58203
58204
58205 private function getColumnSeparatorWidth()
58206 {
58207 return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
58208 }
58209
58210
58211
58212
58213
58214
58215
58216
58217
58218 private function getCellWidth(array $row, $column)
58219 {
58220 if (isset($row[$column])) {
58221 $cell = $row[$column];
58222 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
58223
58224 return $cellWidth;
58225 }
58226
58227 return 0;
58228 }
58229
58230
58231
58232
58233 private function cleanup()
58234 {
58235 $this->columnWidths = array();
58236 $this->numberOfColumns = null;
58237 }
58238
58239 private static function initStyles()
58240 {
58241 $borderless = new TableStyle();
58242 $borderless
58243 ->setHorizontalBorderChar('=')
58244 ->setVerticalBorderChar(' ')
58245 ->setCrossingChar(' ')
58246 ;
58247
58248 $compact = new TableStyle();
58249 $compact
58250 ->setHorizontalBorderChar('')
58251 ->setVerticalBorderChar(' ')
58252 ->setCrossingChar('')
58253 ->setCellRowContentFormat('%s')
58254 ;
58255
58256 $styleGuide = new TableStyle();
58257 $styleGuide
58258 ->setHorizontalBorderChar('-')
58259 ->setVerticalBorderChar(' ')
58260 ->setCrossingChar(' ')
58261 ->setCellHeaderFormat('%s')
58262 ;
58263
58264 return array(
58265 'default' => new TableStyle(),
58266 'borderless' => $borderless,
58267 'compact' => $compact,
58268 'symfony-style-guide' => $styleGuide,
58269 );
58270 }
58271
58272 private function resolveStyle($name)
58273 {
58274 if ($name instanceof TableStyle) {
58275 return $name;
58276 }
58277
58278 if (isset(self::$styles[$name])) {
58279 return self::$styles[$name];
58280 }
58281
58282 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
58283 }
58284 }
58285 <?php
58286
58287
58288
58289
58290
58291
58292
58293
58294
58295
58296 namespace Symfony\Component\Console\Helper;
58297
58298 use Symfony\Component\Console\Exception\InvalidArgumentException;
58299
58300
58301
58302
58303 class TableCell
58304 {
58305 private $value;
58306 private $options = array(
58307 'rowspan' => 1,
58308 'colspan' => 1,
58309 );
58310
58311
58312
58313
58314
58315 public function __construct($value = '', array $options = array())
58316 {
58317 if (is_numeric($value) && !\is_string($value)) {
58318 $value = (string) $value;
58319 }
58320
58321 $this->value = $value;
58322
58323
58324  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
58325 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
58326 }
58327
58328 $this->options = array_merge($this->options, $options);
58329 }
58330
58331
58332
58333
58334
58335
58336 public function __toString()
58337 {
58338 return $this->value;
58339 }
58340
58341
58342
58343
58344
58345
58346 public function getColspan()
58347 {
58348 return (int) $this->options['colspan'];
58349 }
58350
58351
58352
58353
58354
58355
58356 public function getRowspan()
58357 {
58358 return (int) $this->options['rowspan'];
58359 }
58360 }
58361 <?php
58362
58363
58364
58365
58366
58367
58368
58369
58370
58371
58372 namespace Symfony\Component\Console\Helper;
58373
58374 use Symfony\Component\Console\Exception\InvalidArgumentException;
58375 use Symfony\Component\Console\Output\NullOutput;
58376 use Symfony\Component\Console\Output\OutputInterface;
58377
58378
58379
58380
58381
58382
58383
58384
58385
58386
58387 class TableHelper extends Helper
58388 {
58389 const LAYOUT_DEFAULT = 0;
58390 const LAYOUT_BORDERLESS = 1;
58391 const LAYOUT_COMPACT = 2;
58392
58393 private $table;
58394
58395 public function __construct($triggerDeprecationError = true)
58396 {
58397 if ($triggerDeprecationError) {
58398 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\Table class instead.', E_USER_DEPRECATED);
58399 }
58400
58401 $this->table = new Table(new NullOutput());
58402 }
58403
58404
58405
58406
58407
58408
58409
58410
58411
58412
58413 public function setLayout($layout)
58414 {
58415 switch ($layout) {
58416 case self::LAYOUT_BORDERLESS:
58417 $this->table->setStyle('borderless');
58418 break;
58419
58420 case self::LAYOUT_COMPACT:
58421 $this->table->setStyle('compact');
58422 break;
58423
58424 case self::LAYOUT_DEFAULT:
58425 $this->table->setStyle('default');
58426 break;
58427
58428 default:
58429 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
58430 }
58431
58432 return $this;
58433 }
58434
58435 public function setHeaders(array $headers)
58436 {
58437 $this->table->setHeaders($headers);
58438
58439 return $this;
58440 }
58441
58442 public function setRows(array $rows)
58443 {
58444 $this->table->setRows($rows);
58445
58446 return $this;
58447 }
58448
58449 public function addRows(array $rows)
58450 {
58451 $this->table->addRows($rows);
58452
58453 return $this;
58454 }
58455
58456 public function addRow(array $row)
58457 {
58458 $this->table->addRow($row);
58459
58460 return $this;
58461 }
58462
58463 public function setRow($column, array $row)
58464 {
58465 $this->table->setRow($column, $row);
58466
58467 return $this;
58468 }
58469
58470
58471
58472
58473
58474
58475
58476
58477 public function setPaddingChar($paddingChar)
58478 {
58479 $this->table->getStyle()->setPaddingChar($paddingChar);
58480
58481 return $this;
58482 }
58483
58484
58485
58486
58487
58488
58489
58490
58491 public function setHorizontalBorderChar($horizontalBorderChar)
58492 {
58493 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
58494
58495 return $this;
58496 }
58497
58498
58499
58500
58501
58502
58503
58504
58505 public function setVerticalBorderChar($verticalBorderChar)
58506 {
58507 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
58508
58509 return $this;
58510 }
58511
58512
58513
58514
58515
58516
58517
58518
58519 public function setCrossingChar($crossingChar)
58520 {
58521 $this->table->getStyle()->setCrossingChar($crossingChar);
58522
58523 return $this;
58524 }
58525
58526
58527
58528
58529
58530
58531
58532
58533 public function setCellHeaderFormat($cellHeaderFormat)
58534 {
58535 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
58536
58537 return $this;
58538 }
58539
58540
58541
58542
58543
58544
58545
58546
58547 public function setCellRowFormat($cellRowFormat)
58548 {
58549 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
58550
58551 return $this;
58552 }
58553
58554
58555
58556
58557
58558
58559
58560
58561 public function setCellRowContentFormat($cellRowContentFormat)
58562 {
58563 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
58564
58565 return $this;
58566 }
58567
58568
58569
58570
58571
58572
58573
58574
58575 public function setBorderFormat($borderFormat)
58576 {
58577 $this->table->getStyle()->setBorderFormat($borderFormat);
58578
58579 return $this;
58580 }
58581
58582
58583
58584
58585
58586
58587
58588
58589 public function setPadType($padType)
58590 {
58591 $this->table->getStyle()->setPadType($padType);
58592
58593 return $this;
58594 }
58595
58596
58597
58598
58599
58600
58601
58602
58603
58604
58605
58606
58607
58608 public function render(OutputInterface $output)
58609 {
58610 $p = new \ReflectionProperty($this->table, 'output');
58611 $p->setAccessible(true);
58612 $p->setValue($this->table, $output);
58613
58614 $this->table->render();
58615 }
58616
58617
58618
58619
58620 public function getName()
58621 {
58622 return 'table';
58623 }
58624 }
58625 <?php
58626
58627
58628
58629
58630
58631
58632
58633
58634
58635
58636 namespace Symfony\Component\Console\Helper;
58637
58638
58639
58640
58641
58642
58643 class TableSeparator extends TableCell
58644 {
58645 public function __construct(array $options = array())
58646 {
58647 parent::__construct('', $options);
58648 }
58649 }
58650 <?php
58651
58652
58653
58654
58655
58656
58657
58658
58659
58660
58661 namespace Symfony\Component\Console\Helper;
58662
58663 use Symfony\Component\Console\Exception\InvalidArgumentException;
58664 use Symfony\Component\Console\Exception\LogicException;
58665
58666
58667
58668
58669
58670
58671
58672 class TableStyle
58673 {
58674 private $paddingChar = ' ';
58675 private $horizontalBorderChar = '-';
58676 private $verticalBorderChar = '|';
58677 private $crossingChar = '+';
58678 private $cellHeaderFormat = '<info>%s</info>';
58679 private $cellRowFormat = '%s';
58680 private $cellRowContentFormat = ' %s ';
58681 private $borderFormat = '%s';
58682 private $padType = STR_PAD_RIGHT;
58683
58684
58685
58686
58687
58688
58689
58690
58691 public function setPaddingChar($paddingChar)
58692 {
58693 if (!$paddingChar) {
58694 throw new LogicException('The padding char must not be empty');
58695 }
58696
58697 $this->paddingChar = $paddingChar;
58698
58699 return $this;
58700 }
58701
58702
58703
58704
58705
58706
58707 public function getPaddingChar()
58708 {
58709 return $this->paddingChar;
58710 }
58711
58712
58713
58714
58715
58716
58717
58718
58719 public function setHorizontalBorderChar($horizontalBorderChar)
58720 {
58721 $this->horizontalBorderChar = $horizontalBorderChar;
58722
58723 return $this;
58724 }
58725
58726
58727
58728
58729
58730
58731 public function getHorizontalBorderChar()
58732 {
58733 return $this->horizontalBorderChar;
58734 }
58735
58736
58737
58738
58739
58740
58741
58742
58743 public function setVerticalBorderChar($verticalBorderChar)
58744 {
58745 $this->verticalBorderChar = $verticalBorderChar;
58746
58747 return $this;
58748 }
58749
58750
58751
58752
58753
58754
58755 public function getVerticalBorderChar()
58756 {
58757 return $this->verticalBorderChar;
58758 }
58759
58760
58761
58762
58763
58764
58765
58766
58767 public function setCrossingChar($crossingChar)
58768 {
58769 $this->crossingChar = $crossingChar;
58770
58771 return $this;
58772 }
58773
58774
58775
58776
58777
58778
58779 public function getCrossingChar()
58780 {
58781 return $this->crossingChar;
58782 }
58783
58784
58785
58786
58787
58788
58789
58790
58791 public function setCellHeaderFormat($cellHeaderFormat)
58792 {
58793 $this->cellHeaderFormat = $cellHeaderFormat;
58794
58795 return $this;
58796 }
58797
58798
58799
58800
58801
58802
58803 public function getCellHeaderFormat()
58804 {
58805 return $this->cellHeaderFormat;
58806 }
58807
58808
58809
58810
58811
58812
58813
58814
58815 public function setCellRowFormat($cellRowFormat)
58816 {
58817 $this->cellRowFormat = $cellRowFormat;
58818
58819 return $this;
58820 }
58821
58822
58823
58824
58825
58826
58827 public function getCellRowFormat()
58828 {
58829 return $this->cellRowFormat;
58830 }
58831
58832
58833
58834
58835
58836
58837
58838
58839 public function setCellRowContentFormat($cellRowContentFormat)
58840 {
58841 $this->cellRowContentFormat = $cellRowContentFormat;
58842
58843 return $this;
58844 }
58845
58846
58847
58848
58849
58850
58851 public function getCellRowContentFormat()
58852 {
58853 return $this->cellRowContentFormat;
58854 }
58855
58856
58857
58858
58859
58860
58861
58862
58863 public function setBorderFormat($borderFormat)
58864 {
58865 $this->borderFormat = $borderFormat;
58866
58867 return $this;
58868 }
58869
58870
58871
58872
58873
58874
58875 public function getBorderFormat()
58876 {
58877 return $this->borderFormat;
58878 }
58879
58880
58881
58882
58883
58884
58885
58886
58887 public function setPadType($padType)
58888 {
58889 if (!\in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
58890 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
58891 }
58892
58893 $this->padType = $padType;
58894
58895 return $this;
58896 }
58897
58898
58899
58900
58901
58902
58903 public function getPadType()
58904 {
58905 return $this->padType;
58906 }
58907 }
58908 <?php
58909
58910
58911
58912
58913
58914
58915
58916
58917
58918
58919 namespace Symfony\Component\Console\Input;
58920
58921 use Symfony\Component\Console\Exception\RuntimeException;
58922
58923
58924
58925
58926
58927
58928
58929
58930
58931
58932
58933
58934
58935
58936
58937
58938
58939
58940
58941
58942
58943
58944
58945
58946
58947
58948 class ArgvInput extends Input
58949 {
58950 private $tokens;
58951 private $parsed;
58952
58953
58954
58955
58956
58957 public function __construct(array $argv = null, InputDefinition $definition = null)
58958 {
58959 if (null === $argv) {
58960 $argv = $_SERVER['argv'];
58961 }
58962
58963
58964  array_shift($argv);
58965
58966 $this->tokens = $argv;
58967
58968 parent::__construct($definition);
58969 }
58970
58971 protected function setTokens(array $tokens)
58972 {
58973 $this->tokens = $tokens;
58974 }
58975
58976
58977
58978
58979 protected function parse()
58980 {
58981 $parseOptions = true;
58982 $this->parsed = $this->tokens;
58983 while (null !== $token = array_shift($this->parsed)) {
58984 if ($parseOptions && '' == $token) {
58985 $this->parseArgument($token);
58986 } elseif ($parseOptions && '--' == $token) {
58987 $parseOptions = false;
58988 } elseif ($parseOptions && 0 === strpos($token, '--')) {
58989 $this->parseLongOption($token);
58990 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
58991 $this->parseShortOption($token);
58992 } else {
58993 $this->parseArgument($token);
58994 }
58995 }
58996 }
58997
58998
58999
59000
59001
59002
59003 private function parseShortOption($token)
59004 {
59005 $name = substr($token, 1);
59006
59007 if (\strlen($name) > 1) {
59008 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
59009
59010  $this->addShortOption($name[0], substr($name, 1));
59011 } else {
59012 $this->parseShortOptionSet($name);
59013 }
59014 } else {
59015 $this->addShortOption($name, null);
59016 }
59017 }
59018
59019
59020
59021
59022
59023
59024
59025
59026 private function parseShortOptionSet($name)
59027 {
59028 $len = \strlen($name);
59029 for ($i = 0; $i < $len; ++$i) {
59030 if (!$this->definition->hasShortcut($name[$i])) {
59031 $encoding = mb_detect_encoding($name, null, true);
59032 throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
59033 }
59034
59035 $option = $this->definition->getOptionForShortcut($name[$i]);
59036 if ($option->acceptValue()) {
59037 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
59038
59039 break;
59040 } else {
59041 $this->addLongOption($option->getName(), null);
59042 }
59043 }
59044 }
59045
59046
59047
59048
59049
59050
59051 private function parseLongOption($token)
59052 {
59053 $name = substr($token, 2);
59054
59055 if (false !== $pos = strpos($name, '=')) {
59056 if (0 === \strlen($value = substr($name, $pos + 1))) {
59057 array_unshift($this->parsed, null);
59058 }
59059 $this->addLongOption(substr($name, 0, $pos), $value);
59060 } else {
59061 $this->addLongOption($name, null);
59062 }
59063 }
59064
59065
59066
59067
59068
59069
59070
59071
59072 private function parseArgument($token)
59073 {
59074 $c = \count($this->arguments);
59075
59076
59077  if ($this->definition->hasArgument($c)) {
59078 $arg = $this->definition->getArgument($c);
59079 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
59080
59081
59082  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
59083 $arg = $this->definition->getArgument($c - 1);
59084 $this->arguments[$arg->getName()][] = $token;
59085
59086
59087  } else {
59088 $all = $this->definition->getArguments();
59089 if (\count($all)) {
59090 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
59091 }
59092
59093 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
59094 }
59095 }
59096
59097
59098
59099
59100
59101
59102
59103
59104
59105 private function addShortOption($shortcut, $value)
59106 {
59107 if (!$this->definition->hasShortcut($shortcut)) {
59108 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
59109 }
59110
59111 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
59112 }
59113
59114
59115
59116
59117
59118
59119
59120
59121
59122 private function addLongOption($name, $value)
59123 {
59124 if (!$this->definition->hasOption($name)) {
59125 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
59126 }
59127
59128 $option = $this->definition->getOption($name);
59129
59130
59131  if (!isset($value[0])) {
59132 $value = null;
59133 }
59134
59135 if (null !== $value && !$option->acceptValue()) {
59136 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
59137 }
59138
59139 if (null === $value && $option->acceptValue() && \count($this->parsed)) {
59140
59141  
59142  $next = array_shift($this->parsed);
59143 if (isset($next[0]) && '-' !== $next[0]) {
59144 $value = $next;
59145 } elseif (empty($next)) {
59146 $value = null;
59147 } else {
59148 array_unshift($this->parsed, $next);
59149 }
59150 }
59151
59152 if (null === $value) {
59153 if ($option->isValueRequired()) {
59154 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
59155 }
59156
59157 if (!$option->isArray()) {
59158 $value = $option->isValueOptional() ? $option->getDefault() : true;
59159 }
59160 }
59161
59162 if ($option->isArray()) {
59163 $this->options[$name][] = $value;
59164 } else {
59165 $this->options[$name] = $value;
59166 }
59167 }
59168
59169
59170
59171
59172 public function getFirstArgument()
59173 {
59174 foreach ($this->tokens as $token) {
59175 if ($token && '-' === $token[0]) {
59176 continue;
59177 }
59178
59179 return $token;
59180 }
59181 }
59182
59183
59184
59185
59186 public function hasParameterOption($values)
59187 {
59188 $values = (array) $values;
59189
59190 foreach ($this->tokens as $token) {
59191 foreach ($values as $value) {
59192
59193  
59194  
59195  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
59196 if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
59197 return true;
59198 }
59199 }
59200 }
59201
59202 return false;
59203 }
59204
59205
59206
59207
59208 public function getParameterOption($values, $default = false)
59209 {
59210 $values = (array) $values;
59211 $tokens = $this->tokens;
59212
59213 while (0 < \count($tokens)) {
59214 $token = array_shift($tokens);
59215
59216 foreach ($values as $value) {
59217 if ($token === $value) {
59218 return array_shift($tokens);
59219 }
59220
59221  
59222  
59223  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
59224 if ('' !== $leading && 0 === strpos($token, $leading)) {
59225 return substr($token, \strlen($leading));
59226 }
59227 }
59228 }
59229
59230 return $default;
59231 }
59232
59233
59234
59235
59236
59237
59238 public function __toString()
59239 {
59240 $self = $this;
59241 $tokens = array_map(function ($token) use ($self) {
59242 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
59243 return $match[1].$self->escapeToken($match[2]);
59244 }
59245
59246 if ($token && '-' !== $token[0]) {
59247 return $self->escapeToken($token);
59248 }
59249
59250 return $token;
59251 }, $this->tokens);
59252
59253 return implode(' ', $tokens);
59254 }
59255 }
59256 <?php
59257
59258
59259
59260
59261
59262
59263
59264
59265
59266
59267 namespace Symfony\Component\Console\Input;
59268
59269 use Symfony\Component\Console\Exception\InvalidArgumentException;
59270 use Symfony\Component\Console\Exception\InvalidOptionException;
59271
59272
59273
59274
59275
59276
59277
59278
59279
59280
59281 class ArrayInput extends Input
59282 {
59283 private $parameters;
59284
59285 public function __construct(array $parameters, InputDefinition $definition = null)
59286 {
59287 $this->parameters = $parameters;
59288
59289 parent::__construct($definition);
59290 }
59291
59292
59293
59294
59295 public function getFirstArgument()
59296 {
59297 foreach ($this->parameters as $key => $value) {
59298 if ($key && '-' === $key[0]) {
59299 continue;
59300 }
59301
59302 return $value;
59303 }
59304 }
59305
59306
59307
59308
59309 public function hasParameterOption($values)
59310 {
59311 $values = (array) $values;
59312
59313 foreach ($this->parameters as $k => $v) {
59314 if (!\is_int($k)) {
59315 $v = $k;
59316 }
59317
59318 if (\in_array($v, $values)) {
59319 return true;
59320 }
59321 }
59322
59323 return false;
59324 }
59325
59326
59327
59328
59329 public function getParameterOption($values, $default = false)
59330 {
59331 $values = (array) $values;
59332
59333 foreach ($this->parameters as $k => $v) {
59334 if (\is_int($k)) {
59335 if (\in_array($v, $values)) {
59336 return true;
59337 }
59338 } elseif (\in_array($k, $values)) {
59339 return $v;
59340 }
59341 }
59342
59343 return $default;
59344 }
59345
59346
59347
59348
59349
59350
59351 public function __toString()
59352 {
59353 $params = array();
59354 foreach ($this->parameters as $param => $val) {
59355 if ($param && '-' === $param[0]) {
59356 if (\is_array($val)) {
59357 foreach ($val as $v) {
59358 $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
59359 }
59360 } else {
59361 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
59362 }
59363 } else {
59364 $params[] = \is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val);
59365 }
59366 }
59367
59368 return implode(' ', $params);
59369 }
59370
59371
59372
59373
59374 protected function parse()
59375 {
59376 foreach ($this->parameters as $key => $value) {
59377 if (0 === strpos($key, '--')) {
59378 $this->addLongOption(substr($key, 2), $value);
59379 } elseif ('-' === $key[0]) {
59380 $this->addShortOption(substr($key, 1), $value);
59381 } else {
59382 $this->addArgument($key, $value);
59383 }
59384 }
59385 }
59386
59387
59388
59389
59390
59391
59392
59393
59394
59395 private function addShortOption($shortcut, $value)
59396 {
59397 if (!$this->definition->hasShortcut($shortcut)) {
59398 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
59399 }
59400
59401 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
59402 }
59403
59404
59405
59406
59407
59408
59409
59410
59411
59412
59413 private function addLongOption($name, $value)
59414 {
59415 if (!$this->definition->hasOption($name)) {
59416 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
59417 }
59418
59419 $option = $this->definition->getOption($name);
59420
59421 if (null === $value) {
59422 if ($option->isValueRequired()) {
59423 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
59424 }
59425
59426 $value = $option->isValueOptional() ? $option->getDefault() : true;
59427 }
59428
59429 $this->options[$name] = $value;
59430 }
59431
59432
59433
59434
59435
59436
59437
59438
59439
59440 private function addArgument($name, $value)
59441 {
59442 if (!$this->definition->hasArgument($name)) {
59443 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59444 }
59445
59446 $this->arguments[$name] = $value;
59447 }
59448 }
59449 <?php
59450
59451
59452
59453
59454
59455
59456
59457
59458
59459
59460 namespace Symfony\Component\Console\Input;
59461
59462 use Symfony\Component\Console\Exception\InvalidArgumentException;
59463 use Symfony\Component\Console\Exception\RuntimeException;
59464
59465
59466
59467
59468
59469
59470
59471
59472
59473
59474
59475
59476 abstract class Input implements InputInterface
59477 {
59478 protected $definition;
59479 protected $options = array();
59480 protected $arguments = array();
59481 protected $interactive = true;
59482
59483 public function __construct(InputDefinition $definition = null)
59484 {
59485 if (null === $definition) {
59486 $this->definition = new InputDefinition();
59487 } else {
59488 $this->bind($definition);
59489 $this->validate();
59490 }
59491 }
59492
59493
59494
59495
59496 public function bind(InputDefinition $definition)
59497 {
59498 $this->arguments = array();
59499 $this->options = array();
59500 $this->definition = $definition;
59501
59502 $this->parse();
59503 }
59504
59505
59506
59507
59508 abstract protected function parse();
59509
59510
59511
59512
59513 public function validate()
59514 {
59515 $definition = $this->definition;
59516 $givenArguments = $this->arguments;
59517
59518 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
59519 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
59520 });
59521
59522 if (\count($missingArguments) > 0) {
59523 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
59524 }
59525 }
59526
59527
59528
59529
59530 public function isInteractive()
59531 {
59532 return $this->interactive;
59533 }
59534
59535
59536
59537
59538 public function setInteractive($interactive)
59539 {
59540 $this->interactive = (bool) $interactive;
59541 }
59542
59543
59544
59545
59546 public function getArguments()
59547 {
59548 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
59549 }
59550
59551
59552
59553
59554 public function getArgument($name)
59555 {
59556 if (!$this->definition->hasArgument($name)) {
59557 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59558 }
59559
59560 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
59561 }
59562
59563
59564
59565
59566 public function setArgument($name, $value)
59567 {
59568 if (!$this->definition->hasArgument($name)) {
59569 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59570 }
59571
59572 $this->arguments[$name] = $value;
59573 }
59574
59575
59576
59577
59578 public function hasArgument($name)
59579 {
59580 return $this->definition->hasArgument($name);
59581 }
59582
59583
59584
59585
59586 public function getOptions()
59587 {
59588 return array_merge($this->definition->getOptionDefaults(), $this->options);
59589 }
59590
59591
59592
59593
59594 public function getOption($name)
59595 {
59596 if (!$this->definition->hasOption($name)) {
59597 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
59598 }
59599
59600 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
59601 }
59602
59603
59604
59605
59606 public function setOption($name, $value)
59607 {
59608 if (!$this->definition->hasOption($name)) {
59609 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
59610 }
59611
59612 $this->options[$name] = $value;
59613 }
59614
59615
59616
59617
59618 public function hasOption($name)
59619 {
59620 return $this->definition->hasOption($name);
59621 }
59622
59623
59624
59625
59626
59627
59628
59629
59630 public function escapeToken($token)
59631 {
59632 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
59633 }
59634 }
59635 <?php
59636
59637
59638
59639
59640
59641
59642
59643
59644
59645
59646 namespace Symfony\Component\Console\Input;
59647
59648 use Symfony\Component\Console\Exception\InvalidArgumentException;
59649 use Symfony\Component\Console\Exception\LogicException;
59650
59651
59652
59653
59654
59655
59656 class InputArgument
59657 {
59658 const REQUIRED = 1;
59659 const OPTIONAL = 2;
59660 const IS_ARRAY = 4;
59661
59662 private $name;
59663 private $mode;
59664 private $default;
59665 private $description;
59666
59667
59668
59669
59670
59671
59672
59673
59674
59675 public function __construct($name, $mode = null, $description = '', $default = null)
59676 {
59677 if (null === $mode) {
59678 $mode = self::OPTIONAL;
59679 } elseif (!\is_int($mode) || $mode > 7 || $mode < 1) {
59680 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
59681 }
59682
59683 $this->name = $name;
59684 $this->mode = $mode;
59685 $this->description = $description;
59686
59687 $this->setDefault($default);
59688 }
59689
59690
59691
59692
59693
59694
59695 public function getName()
59696 {
59697 return $this->name;
59698 }
59699
59700
59701
59702
59703
59704
59705 public function isRequired()
59706 {
59707 return self::REQUIRED === (self::REQUIRED & $this->mode);
59708 }
59709
59710
59711
59712
59713
59714
59715 public function isArray()
59716 {
59717 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
59718 }
59719
59720
59721
59722
59723
59724
59725
59726
59727 public function setDefault($default = null)
59728 {
59729 if (self::REQUIRED === $this->mode && null !== $default) {
59730 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
59731 }
59732
59733 if ($this->isArray()) {
59734 if (null === $default) {
59735 $default = array();
59736 } elseif (!\is_array($default)) {
59737 throw new LogicException('A default value for an array argument must be an array.');
59738 }
59739 }
59740
59741 $this->default = $default;
59742 }
59743
59744
59745
59746
59747
59748
59749 public function getDefault()
59750 {
59751 return $this->default;
59752 }
59753
59754
59755
59756
59757
59758
59759 public function getDescription()
59760 {
59761 return $this->description;
59762 }
59763 }
59764 <?php
59765
59766
59767
59768
59769
59770
59771
59772
59773
59774
59775 namespace Symfony\Component\Console\Input;
59776
59777
59778
59779
59780
59781
59782
59783 interface InputAwareInterface
59784 {
59785
59786
59787
59788 public function setInput(InputInterface $input);
59789 }
59790 <?php
59791
59792
59793
59794
59795
59796
59797
59798
59799
59800
59801 namespace Symfony\Component\Console\Input;
59802
59803 use Symfony\Component\Console\Descriptor\TextDescriptor;
59804 use Symfony\Component\Console\Descriptor\XmlDescriptor;
59805 use Symfony\Component\Console\Exception\InvalidArgumentException;
59806 use Symfony\Component\Console\Exception\LogicException;
59807 use Symfony\Component\Console\Output\BufferedOutput;
59808
59809
59810
59811
59812
59813
59814
59815
59816
59817
59818
59819
59820
59821 class InputDefinition
59822 {
59823 private $arguments;
59824 private $requiredCount;
59825 private $hasAnArrayArgument = false;
59826 private $hasOptional;
59827 private $options;
59828 private $shortcuts;
59829
59830
59831
59832
59833 public function __construct(array $definition = array())
59834 {
59835 $this->setDefinition($definition);
59836 }
59837
59838
59839
59840
59841 public function setDefinition(array $definition)
59842 {
59843 $arguments = array();
59844 $options = array();
59845 foreach ($definition as $item) {
59846 if ($item instanceof InputOption) {
59847 $options[] = $item;
59848 } else {
59849 $arguments[] = $item;
59850 }
59851 }
59852
59853 $this->setArguments($arguments);
59854 $this->setOptions($options);
59855 }
59856
59857
59858
59859
59860
59861
59862 public function setArguments($arguments = array())
59863 {
59864 $this->arguments = array();
59865 $this->requiredCount = 0;
59866 $this->hasOptional = false;
59867 $this->hasAnArrayArgument = false;
59868 $this->addArguments($arguments);
59869 }
59870
59871
59872
59873
59874
59875
59876 public function addArguments($arguments = array())
59877 {
59878 if (null !== $arguments) {
59879 foreach ($arguments as $argument) {
59880 $this->addArgument($argument);
59881 }
59882 }
59883 }
59884
59885
59886
59887
59888 public function addArgument(InputArgument $argument)
59889 {
59890 if (isset($this->arguments[$argument->getName()])) {
59891 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
59892 }
59893
59894 if ($this->hasAnArrayArgument) {
59895 throw new LogicException('Cannot add an argument after an array argument.');
59896 }
59897
59898 if ($argument->isRequired() && $this->hasOptional) {
59899 throw new LogicException('Cannot add a required argument after an optional one.');
59900 }
59901
59902 if ($argument->isArray()) {
59903 $this->hasAnArrayArgument = true;
59904 }
59905
59906 if ($argument->isRequired()) {
59907 ++$this->requiredCount;
59908 } else {
59909 $this->hasOptional = true;
59910 }
59911
59912 $this->arguments[$argument->getName()] = $argument;
59913 }
59914
59915
59916
59917
59918
59919
59920
59921
59922
59923
59924 public function getArgument($name)
59925 {
59926 if (!$this->hasArgument($name)) {
59927 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59928 }
59929
59930 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
59931
59932 return $arguments[$name];
59933 }
59934
59935
59936
59937
59938
59939
59940
59941
59942 public function hasArgument($name)
59943 {
59944 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
59945
59946 return isset($arguments[$name]);
59947 }
59948
59949
59950
59951
59952
59953
59954 public function getArguments()
59955 {
59956 return $this->arguments;
59957 }
59958
59959
59960
59961
59962
59963
59964 public function getArgumentCount()
59965 {
59966 return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments);
59967 }
59968
59969
59970
59971
59972
59973
59974 public function getArgumentRequiredCount()
59975 {
59976 return $this->requiredCount;
59977 }
59978
59979
59980
59981
59982
59983
59984 public function getArgumentDefaults()
59985 {
59986 $values = array();
59987 foreach ($this->arguments as $argument) {
59988 $values[$argument->getName()] = $argument->getDefault();
59989 }
59990
59991 return $values;
59992 }
59993
59994
59995
59996
59997
59998
59999 public function setOptions($options = array())
60000 {
60001 $this->options = array();
60002 $this->shortcuts = array();
60003 $this->addOptions($options);
60004 }
60005
60006
60007
60008
60009
60010
60011 public function addOptions($options = array())
60012 {
60013 foreach ($options as $option) {
60014 $this->addOption($option);
60015 }
60016 }
60017
60018
60019
60020
60021 public function addOption(InputOption $option)
60022 {
60023 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
60024 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
60025 }
60026
60027 if ($option->getShortcut()) {
60028 foreach (explode('|', $option->getShortcut()) as $shortcut) {
60029 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
60030 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
60031 }
60032 }
60033 }
60034
60035 $this->options[$option->getName()] = $option;
60036 if ($option->getShortcut()) {
60037 foreach (explode('|', $option->getShortcut()) as $shortcut) {
60038 $this->shortcuts[$shortcut] = $option->getName();
60039 }
60040 }
60041 }
60042
60043
60044
60045
60046
60047
60048
60049
60050
60051
60052 public function getOption($name)
60053 {
60054 if (!$this->hasOption($name)) {
60055 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
60056 }
60057
60058 return $this->options[$name];
60059 }
60060
60061
60062
60063
60064
60065
60066
60067
60068
60069
60070
60071 public function hasOption($name)
60072 {
60073 return isset($this->options[$name]);
60074 }
60075
60076
60077
60078
60079
60080
60081 public function getOptions()
60082 {
60083 return $this->options;
60084 }
60085
60086
60087
60088
60089
60090
60091
60092
60093 public function hasShortcut($name)
60094 {
60095 return isset($this->shortcuts[$name]);
60096 }
60097
60098
60099
60100
60101
60102
60103
60104
60105 public function getOptionForShortcut($shortcut)
60106 {
60107 return $this->getOption($this->shortcutToName($shortcut));
60108 }
60109
60110
60111
60112
60113
60114
60115 public function getOptionDefaults()
60116 {
60117 $values = array();
60118 foreach ($this->options as $option) {
60119 $values[$option->getName()] = $option->getDefault();
60120 }
60121
60122 return $values;
60123 }
60124
60125
60126
60127
60128
60129
60130
60131
60132
60133
60134 private function shortcutToName($shortcut)
60135 {
60136 if (!isset($this->shortcuts[$shortcut])) {
60137 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
60138 }
60139
60140 return $this->shortcuts[$shortcut];
60141 }
60142
60143
60144
60145
60146
60147
60148
60149
60150 public function getSynopsis($short = false)
60151 {
60152 $elements = array();
60153
60154 if ($short && $this->getOptions()) {
60155 $elements[] = '[options]';
60156 } elseif (!$short) {
60157 foreach ($this->getOptions() as $option) {
60158 $value = '';
60159 if ($option->acceptValue()) {
60160 $value = sprintf(
60161 ' %s%s%s',
60162 $option->isValueOptional() ? '[' : '',
60163 strtoupper($option->getName()),
60164 $option->isValueOptional() ? ']' : ''
60165 );
60166 }
60167
60168 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
60169 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
60170 }
60171 }
60172
60173 if (\count($elements) && $this->getArguments()) {
60174 $elements[] = '[--]';
60175 }
60176
60177 foreach ($this->getArguments() as $argument) {
60178 $element = '<'.$argument->getName().'>';
60179 if (!$argument->isRequired()) {
60180 $element = '['.$element.']';
60181 } elseif ($argument->isArray()) {
60182 $element .= ' ('.$element.')';
60183 }
60184
60185 if ($argument->isArray()) {
60186 $element .= '...';
60187 }
60188
60189 $elements[] = $element;
60190 }
60191
60192 return implode(' ', $elements);
60193 }
60194
60195
60196
60197
60198
60199
60200
60201
60202 public function asText()
60203 {
60204 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
60205
60206 $descriptor = new TextDescriptor();
60207 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
60208 $descriptor->describe($output, $this, array('raw_output' => true));
60209
60210 return $output->fetch();
60211 }
60212
60213
60214
60215
60216
60217
60218
60219
60220
60221
60222 public function asXml($asDom = false)
60223 {
60224 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
60225
60226 $descriptor = new XmlDescriptor();
60227
60228 if ($asDom) {
60229 return $descriptor->getInputDefinitionDocument($this);
60230 }
60231
60232 $output = new BufferedOutput();
60233 $descriptor->describe($output, $this);
60234
60235 return $output->fetch();
60236 }
60237 }
60238 <?php
60239
60240
60241
60242
60243
60244
60245
60246
60247
60248
60249 namespace Symfony\Component\Console\Input;
60250
60251 use Symfony\Component\Console\Exception\InvalidArgumentException;
60252 use Symfony\Component\Console\Exception\RuntimeException;
60253
60254
60255
60256
60257
60258
60259 interface InputInterface
60260 {
60261
60262
60263
60264
60265
60266 public function getFirstArgument();
60267
60268
60269
60270
60271
60272
60273
60274
60275
60276
60277
60278
60279
60280 public function hasParameterOption($values);
60281
60282
60283
60284
60285
60286
60287
60288
60289
60290
60291
60292
60293
60294
60295 public function getParameterOption($values, $default = false);
60296
60297
60298
60299
60300
60301
60302 public function bind(InputDefinition $definition);
60303
60304
60305
60306
60307
60308
60309 public function validate();
60310
60311
60312
60313
60314
60315
60316 public function getArguments();
60317
60318
60319
60320
60321
60322
60323
60324
60325
60326
60327 public function getArgument($name);
60328
60329
60330
60331
60332
60333
60334
60335
60336
60337 public function setArgument($name, $value);
60338
60339
60340
60341
60342
60343
60344
60345
60346 public function hasArgument($name);
60347
60348
60349
60350
60351
60352
60353 public function getOptions();
60354
60355
60356
60357
60358
60359
60360
60361
60362
60363
60364 public function getOption($name);
60365
60366
60367
60368
60369
60370
60371
60372
60373
60374 public function setOption($name, $value);
60375
60376
60377
60378
60379
60380
60381
60382
60383 public function hasOption($name);
60384
60385
60386
60387
60388
60389
60390 public function isInteractive();
60391
60392
60393
60394
60395
60396
60397 public function setInteractive($interactive);
60398 }
60399 <?php
60400
60401
60402
60403
60404
60405
60406
60407
60408
60409
60410 namespace Symfony\Component\Console\Input;
60411
60412 use Symfony\Component\Console\Exception\InvalidArgumentException;
60413 use Symfony\Component\Console\Exception\LogicException;
60414
60415
60416
60417
60418
60419
60420 class InputOption
60421 {
60422 const VALUE_NONE = 1;
60423 const VALUE_REQUIRED = 2;
60424 const VALUE_OPTIONAL = 4;
60425 const VALUE_IS_ARRAY = 8;
60426
60427 private $name;
60428 private $shortcut;
60429 private $mode;
60430 private $default;
60431 private $description;
60432
60433
60434
60435
60436
60437
60438
60439
60440
60441
60442 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
60443 {
60444 if (0 === strpos($name, '--')) {
60445 $name = substr($name, 2);
60446 }
60447
60448 if (empty($name)) {
60449 throw new InvalidArgumentException('An option name cannot be empty.');
60450 }
60451
60452 if (empty($shortcut)) {
60453 $shortcut = null;
60454 }
60455
60456 if (null !== $shortcut) {
60457 if (\is_array($shortcut)) {
60458 $shortcut = implode('|', $shortcut);
60459 }
60460 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
60461 $shortcuts = array_filter($shortcuts);
60462 $shortcut = implode('|', $shortcuts);
60463
60464 if (empty($shortcut)) {
60465 throw new InvalidArgumentException('An option shortcut cannot be empty.');
60466 }
60467 }
60468
60469 if (null === $mode) {
60470 $mode = self::VALUE_NONE;
60471 } elseif (!\is_int($mode) || $mode > 15 || $mode < 1) {
60472 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
60473 }
60474
60475 $this->name = $name;
60476 $this->shortcut = $shortcut;
60477 $this->mode = $mode;
60478 $this->description = $description;
60479
60480 if ($this->isArray() && !$this->acceptValue()) {
60481 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
60482 }
60483
60484 $this->setDefault($default);
60485 }
60486
60487
60488
60489
60490
60491
60492 public function getShortcut()
60493 {
60494 return $this->shortcut;
60495 }
60496
60497
60498
60499
60500
60501
60502 public function getName()
60503 {
60504 return $this->name;
60505 }
60506
60507
60508
60509
60510
60511
60512 public function acceptValue()
60513 {
60514 return $this->isValueRequired() || $this->isValueOptional();
60515 }
60516
60517
60518
60519
60520
60521
60522 public function isValueRequired()
60523 {
60524 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
60525 }
60526
60527
60528
60529
60530
60531
60532 public function isValueOptional()
60533 {
60534 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
60535 }
60536
60537
60538
60539
60540
60541
60542 public function isArray()
60543 {
60544 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
60545 }
60546
60547
60548
60549
60550
60551
60552
60553
60554 public function setDefault($default = null)
60555 {
60556 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
60557 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
60558 }
60559
60560 if ($this->isArray()) {
60561 if (null === $default) {
60562 $default = array();
60563 } elseif (!\is_array($default)) {
60564 throw new LogicException('A default value for an array option must be an array.');
60565 }
60566 }
60567
60568 $this->default = $this->acceptValue() ? $default : false;
60569 }
60570
60571
60572
60573
60574
60575
60576 public function getDefault()
60577 {
60578 return $this->default;
60579 }
60580
60581
60582
60583
60584
60585
60586 public function getDescription()
60587 {
60588 return $this->description;
60589 }
60590
60591
60592
60593
60594
60595
60596 public function equals(self $option)
60597 {
60598 return $option->getName() === $this->getName()
60599 && $option->getShortcut() === $this->getShortcut()
60600 && $option->getDefault() === $this->getDefault()
60601 && $option->isArray() === $this->isArray()
60602 && $option->isValueRequired() === $this->isValueRequired()
60603 && $option->isValueOptional() === $this->isValueOptional()
60604 ;
60605 }
60606 }
60607 <?php
60608
60609
60610
60611
60612
60613
60614
60615
60616
60617
60618 namespace Symfony\Component\Console\Input;
60619
60620 use Symfony\Component\Console\Exception\InvalidArgumentException;
60621
60622
60623
60624
60625
60626
60627
60628
60629
60630
60631 class StringInput extends ArgvInput
60632 {
60633 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
60634 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
60635
60636
60637
60638
60639
60640
60641
60642 public function __construct($input, InputDefinition $definition = null)
60643 {
60644 if ($definition) {
60645 @trigger_error('The $definition argument of the '.__METHOD__.' method is deprecated and will be removed in 3.0. Set this parameter with the bind() method instead.', E_USER_DEPRECATED);
60646 }
60647
60648 parent::__construct(array(), null);
60649
60650 $this->setTokens($this->tokenize($input));
60651
60652 if (null !== $definition) {
60653 $this->bind($definition);
60654 }
60655 }
60656
60657
60658
60659
60660
60661
60662
60663
60664
60665
60666 private function tokenize($input)
60667 {
60668 $tokens = array();
60669 $length = \strlen($input);
60670 $cursor = 0;
60671 while ($cursor < $length) {
60672 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
60673 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
60674 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, \strlen($match[3]) - 2)));
60675 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
60676 $tokens[] = stripcslashes(substr($match[0], 1, \strlen($match[0]) - 2));
60677 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
60678 $tokens[] = stripcslashes($match[1]);
60679 } else {
60680
60681  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
60682 }
60683
60684 $cursor += \strlen($match[0]);
60685 }
60686
60687 return $tokens;
60688 }
60689 }
60690 Copyright (c) 2004-2018 Fabien Potencier
60691
60692 Permission is hereby granted, free of charge, to any person obtaining a copy
60693 of this software and associated documentation files (the "Software"), to deal
60694 in the Software without restriction, including without limitation the rights
60695 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
60696 copies of the Software, and to permit persons to whom the Software is furnished
60697 to do so, subject to the following conditions:
60698
60699 The above copyright notice and this permission notice shall be included in all
60700 copies or substantial portions of the Software.
60701
60702 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60703 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60704 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
60705 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
60706 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60707 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
60708 THE SOFTWARE.
60709 <?php
60710
60711
60712
60713
60714
60715
60716
60717
60718
60719
60720 namespace Symfony\Component\Console\Logger;
60721
60722 use Psr\Log\AbstractLogger;
60723 use Psr\Log\InvalidArgumentException;
60724 use Psr\Log\LogLevel;
60725 use Symfony\Component\Console\Output\ConsoleOutputInterface;
60726 use Symfony\Component\Console\Output\OutputInterface;
60727
60728
60729
60730
60731
60732
60733
60734
60735 class ConsoleLogger extends AbstractLogger
60736 {
60737 const INFO = 'info';
60738 const ERROR = 'error';
60739
60740 private $output;
60741 private $verbosityLevelMap = array(
60742 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
60743 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
60744 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
60745 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
60746 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
60747 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
60748 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
60749 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
60750 );
60751 private $formatLevelMap = array(
60752 LogLevel::EMERGENCY => self::ERROR,
60753 LogLevel::ALERT => self::ERROR,
60754 LogLevel::CRITICAL => self::ERROR,
60755 LogLevel::ERROR => self::ERROR,
60756 LogLevel::WARNING => self::INFO,
60757 LogLevel::NOTICE => self::INFO,
60758 LogLevel::INFO => self::INFO,
60759 LogLevel::DEBUG => self::INFO,
60760 );
60761
60762 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
60763 {
60764 $this->output = $output;
60765 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
60766 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
60767 }
60768
60769
60770
60771
60772 public function log($level, $message, array $context = array())
60773 {
60774 if (!isset($this->verbosityLevelMap[$level])) {
60775 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
60776 }
60777
60778
60779  if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) {
60780 $output = $this->output->getErrorOutput();
60781 } else {
60782 $output = $this->output;
60783 }
60784
60785 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
60786 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
60787 }
60788 }
60789
60790
60791
60792
60793
60794
60795
60796
60797
60798
60799
60800 private function interpolate($message, array $context)
60801 {
60802
60803  $replace = array();
60804 foreach ($context as $key => $val) {
60805 if (!\is_array($val) && (!\is_object($val) || method_exists($val, '__toString'))) {
60806 $replace[sprintf('{%s}', $key)] = $val;
60807 }
60808 }
60809
60810
60811  return strtr($message, $replace);
60812 }
60813 }
60814 <?php
60815
60816
60817
60818
60819
60820
60821
60822
60823
60824
60825 namespace Symfony\Component\Console\Output;
60826
60827
60828
60829
60830 class BufferedOutput extends Output
60831 {
60832 private $buffer = '';
60833
60834
60835
60836
60837
60838
60839 public function fetch()
60840 {
60841 $content = $this->buffer;
60842 $this->buffer = '';
60843
60844 return $content;
60845 }
60846
60847
60848
60849
60850 protected function doWrite($message, $newline)
60851 {
60852 $this->buffer .= $message;
60853
60854 if ($newline) {
60855 $this->buffer .= PHP_EOL;
60856 }
60857 }
60858 }
60859 <?php
60860
60861
60862
60863
60864
60865
60866
60867
60868
60869
60870 namespace Symfony\Component\Console\Output;
60871
60872 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
60873
60874
60875
60876
60877
60878
60879
60880
60881
60882
60883
60884
60885
60886
60887 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
60888 {
60889 private $stderr;
60890
60891
60892
60893
60894
60895
60896 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
60897 {
60898 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
60899
60900 $actualDecorated = $this->isDecorated();
60901 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
60902
60903 if (null === $decorated) {
60904 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
60905 }
60906 }
60907
60908
60909
60910
60911 public function setDecorated($decorated)
60912 {
60913 parent::setDecorated($decorated);
60914 $this->stderr->setDecorated($decorated);
60915 }
60916
60917
60918
60919
60920 public function setFormatter(OutputFormatterInterface $formatter)
60921 {
60922 parent::setFormatter($formatter);
60923 $this->stderr->setFormatter($formatter);
60924 }
60925
60926
60927
60928
60929 public function setVerbosity($level)
60930 {
60931 parent::setVerbosity($level);
60932 $this->stderr->setVerbosity($level);
60933 }
60934
60935
60936
60937
60938 public function getErrorOutput()
60939 {
60940 return $this->stderr;
60941 }
60942
60943
60944
60945
60946 public function setErrorOutput(OutputInterface $error)
60947 {
60948 $this->stderr = $error;
60949 }
60950
60951
60952
60953
60954
60955
60956
60957 protected function hasStdoutSupport()
60958 {
60959 return false === $this->isRunningOS400();
60960 }
60961
60962
60963
60964
60965
60966
60967
60968 protected function hasStderrSupport()
60969 {
60970 return false === $this->isRunningOS400();
60971 }
60972
60973
60974
60975
60976
60977
60978
60979 private function isRunningOS400()
60980 {
60981 $checks = array(
60982 \function_exists('php_uname') ? php_uname('s') : '',
60983 getenv('OSTYPE'),
60984 PHP_OS,
60985 );
60986
60987 return false !== stripos(implode(';', $checks), 'OS400');
60988 }
60989
60990
60991
60992
60993 private function openOutputStream()
60994 {
60995 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
60996
60997 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
60998 }
60999
61000
61001
61002
61003 private function openErrorStream()
61004 {
61005 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
61006
61007 return fopen($errorStream, 'w');
61008 }
61009 }
61010 <?php
61011
61012
61013
61014
61015
61016
61017
61018
61019
61020
61021 namespace Symfony\Component\Console\Output;
61022
61023
61024
61025
61026
61027
61028
61029 interface ConsoleOutputInterface extends OutputInterface
61030 {
61031
61032
61033
61034
61035
61036 public function getErrorOutput();
61037
61038 public function setErrorOutput(OutputInterface $error);
61039 }
61040 <?php
61041
61042
61043
61044
61045
61046
61047
61048
61049
61050
61051 namespace Symfony\Component\Console\Output;
61052
61053 use Symfony\Component\Console\Formatter\OutputFormatter;
61054 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
61055
61056
61057
61058
61059
61060
61061
61062
61063
61064 class NullOutput implements OutputInterface
61065 {
61066
61067
61068
61069 public function setFormatter(OutputFormatterInterface $formatter)
61070 {
61071
61072  }
61073
61074
61075
61076
61077 public function getFormatter()
61078 {
61079
61080  return new OutputFormatter();
61081 }
61082
61083
61084
61085
61086 public function setDecorated($decorated)
61087 {
61088
61089  }
61090
61091
61092
61093
61094 public function isDecorated()
61095 {
61096 return false;
61097 }
61098
61099
61100
61101
61102 public function setVerbosity($level)
61103 {
61104
61105  }
61106
61107
61108
61109
61110 public function getVerbosity()
61111 {
61112 return self::VERBOSITY_QUIET;
61113 }
61114
61115
61116
61117
61118 public function isQuiet()
61119 {
61120 return true;
61121 }
61122
61123
61124
61125
61126 public function isVerbose()
61127 {
61128 return false;
61129 }
61130
61131
61132
61133
61134 public function isVeryVerbose()
61135 {
61136 return false;
61137 }
61138
61139
61140
61141
61142 public function isDebug()
61143 {
61144 return false;
61145 }
61146
61147
61148
61149
61150 public function writeln($messages, $options = self::OUTPUT_NORMAL)
61151 {
61152
61153  }
61154
61155
61156
61157
61158 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
61159 {
61160
61161  }
61162 }
61163 <?php
61164
61165
61166
61167
61168
61169
61170
61171
61172
61173
61174 namespace Symfony\Component\Console\Output;
61175
61176 use Symfony\Component\Console\Formatter\OutputFormatter;
61177 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
61178
61179
61180
61181
61182
61183
61184
61185
61186
61187
61188
61189
61190
61191
61192 abstract class Output implements OutputInterface
61193 {
61194 private $verbosity;
61195 private $formatter;
61196
61197
61198
61199
61200
61201
61202 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
61203 {
61204 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
61205 $this->formatter = $formatter ?: new OutputFormatter();
61206 $this->formatter->setDecorated($decorated);
61207 }
61208
61209
61210
61211
61212 public function setFormatter(OutputFormatterInterface $formatter)
61213 {
61214 $this->formatter = $formatter;
61215 }
61216
61217
61218
61219
61220 public function getFormatter()
61221 {
61222 return $this->formatter;
61223 }
61224
61225
61226
61227
61228 public function setDecorated($decorated)
61229 {
61230 $this->formatter->setDecorated($decorated);
61231 }
61232
61233
61234
61235
61236 public function isDecorated()
61237 {
61238 return $this->formatter->isDecorated();
61239 }
61240
61241
61242
61243
61244 public function setVerbosity($level)
61245 {
61246 $this->verbosity = (int) $level;
61247 }
61248
61249
61250
61251
61252 public function getVerbosity()
61253 {
61254 return $this->verbosity;
61255 }
61256
61257
61258
61259
61260 public function isQuiet()
61261 {
61262 return self::VERBOSITY_QUIET === $this->verbosity;
61263 }
61264
61265
61266
61267
61268 public function isVerbose()
61269 {
61270 return self::VERBOSITY_VERBOSE <= $this->verbosity;
61271 }
61272
61273
61274
61275
61276 public function isVeryVerbose()
61277 {
61278 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
61279 }
61280
61281
61282
61283
61284 public function isDebug()
61285 {
61286 return self::VERBOSITY_DEBUG <= $this->verbosity;
61287 }
61288
61289
61290
61291
61292 public function writeln($messages, $options = self::OUTPUT_NORMAL)
61293 {
61294 $this->write($messages, true, $options);
61295 }
61296
61297
61298
61299
61300 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
61301 {
61302 $messages = (array) $messages;
61303
61304 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
61305 $type = $types & $options ?: self::OUTPUT_NORMAL;
61306
61307 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
61308 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
61309
61310 if ($verbosity > $this->getVerbosity()) {
61311 return;
61312 }
61313
61314 foreach ($messages as $message) {
61315 switch ($type) {
61316 case OutputInterface::OUTPUT_NORMAL:
61317 $message = $this->formatter->format($message);
61318 break;
61319 case OutputInterface::OUTPUT_RAW:
61320 break;
61321 case OutputInterface::OUTPUT_PLAIN:
61322 $message = strip_tags($this->formatter->format($message));
61323 break;
61324 }
61325
61326 $this->doWrite($message, $newline);
61327 }
61328 }
61329
61330
61331
61332
61333
61334
61335
61336 abstract protected function doWrite($message, $newline);
61337 }
61338 <?php
61339
61340
61341
61342
61343
61344
61345
61346
61347
61348
61349 namespace Symfony\Component\Console\Output;
61350
61351 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
61352
61353
61354
61355
61356
61357
61358 interface OutputInterface
61359 {
61360 const VERBOSITY_QUIET = 16;
61361 const VERBOSITY_NORMAL = 32;
61362 const VERBOSITY_VERBOSE = 64;
61363 const VERBOSITY_VERY_VERBOSE = 128;
61364 const VERBOSITY_DEBUG = 256;
61365
61366 const OUTPUT_NORMAL = 1;
61367 const OUTPUT_RAW = 2;
61368 const OUTPUT_PLAIN = 4;
61369
61370
61371
61372
61373
61374
61375
61376
61377 public function write($messages, $newline = false, $options = 0);
61378
61379
61380
61381
61382
61383
61384
61385 public function writeln($messages, $options = 0);
61386
61387
61388
61389
61390
61391
61392 public function setVerbosity($level);
61393
61394
61395
61396
61397
61398
61399 public function getVerbosity();
61400
61401
61402
61403
61404
61405
61406 public function setDecorated($decorated);
61407
61408
61409
61410
61411
61412
61413 public function isDecorated();
61414
61415 public function setFormatter(OutputFormatterInterface $formatter);
61416
61417
61418
61419
61420
61421
61422 public function getFormatter();
61423 }
61424 <?php
61425
61426
61427
61428
61429
61430
61431
61432
61433
61434
61435 namespace Symfony\Component\Console\Output;
61436
61437 use Symfony\Component\Console\Exception\InvalidArgumentException;
61438 use Symfony\Component\Console\Exception\RuntimeException;
61439 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
61440
61441
61442
61443
61444
61445
61446
61447
61448
61449
61450
61451
61452
61453
61454 class StreamOutput extends Output
61455 {
61456 private $stream;
61457
61458
61459
61460
61461
61462
61463
61464
61465
61466 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
61467 {
61468 if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
61469 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
61470 }
61471
61472 $this->stream = $stream;
61473
61474 if (null === $decorated) {
61475 $decorated = $this->hasColorSupport();
61476 }
61477
61478 parent::__construct($verbosity, $decorated, $formatter);
61479 }
61480
61481
61482
61483
61484
61485
61486 public function getStream()
61487 {
61488 return $this->stream;
61489 }
61490
61491
61492
61493
61494 protected function doWrite($message, $newline)
61495 {
61496 if ($newline) {
61497 $message .= PHP_EOL;
61498 }
61499
61500 if (false === @fwrite($this->stream, $message)) {
61501
61502  throw new RuntimeException('Unable to write output.');
61503 }
61504
61505 fflush($this->stream);
61506 }
61507
61508
61509
61510
61511
61512
61513
61514
61515
61516
61517
61518
61519
61520
61521 protected function hasColorSupport()
61522 {
61523 if ('Hyper' === getenv('TERM_PROGRAM')) {
61524 return true;
61525 }
61526
61527 if (\DIRECTORY_SEPARATOR === '\\') {
61528 return (\function_exists('sapi_windows_vt100_support')
61529 && @sapi_windows_vt100_support($this->stream))
61530 || false !== getenv('ANSICON')
61531 || 'ON' === getenv('ConEmuANSI')
61532 || 'xterm' === getenv('TERM');
61533 }
61534
61535 if (\function_exists('stream_isatty')) {
61536 return @stream_isatty($this->stream);
61537 }
61538
61539 if (\function_exists('posix_isatty')) {
61540 return @posix_isatty($this->stream);
61541 }
61542
61543 $stat = @fstat($this->stream);
61544
61545  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
61546 }
61547 }
61548 <?php
61549
61550
61551
61552
61553
61554
61555
61556
61557
61558
61559 namespace Symfony\Component\Console\Question;
61560
61561 use Symfony\Component\Console\Exception\InvalidArgumentException;
61562
61563
61564
61565
61566
61567
61568 class ChoiceQuestion extends Question
61569 {
61570 private $choices;
61571 private $multiselect = false;
61572 private $prompt = ' > ';
61573 private $errorMessage = 'Value "%s" is invalid';
61574
61575
61576
61577
61578
61579
61580 public function __construct($question, array $choices, $default = null)
61581 {
61582 if (!$choices) {
61583 throw new \LogicException('Choice question must have at least 1 choice available.');
61584 }
61585
61586 parent::__construct($question, $default);
61587
61588 $this->choices = $choices;
61589 $this->setValidator($this->getDefaultValidator());
61590 $this->setAutocompleterValues($choices);
61591 }
61592
61593
61594
61595
61596
61597
61598 public function getChoices()
61599 {
61600 return $this->choices;
61601 }
61602
61603
61604
61605
61606
61607
61608
61609
61610
61611
61612 public function setMultiselect($multiselect)
61613 {
61614 $this->multiselect = $multiselect;
61615 $this->setValidator($this->getDefaultValidator());
61616
61617 return $this;
61618 }
61619
61620
61621
61622
61623
61624
61625 public function isMultiselect()
61626 {
61627 return $this->multiselect;
61628 }
61629
61630
61631
61632
61633
61634
61635 public function getPrompt()
61636 {
61637 return $this->prompt;
61638 }
61639
61640
61641
61642
61643
61644
61645
61646
61647 public function setPrompt($prompt)
61648 {
61649 $this->prompt = $prompt;
61650
61651 return $this;
61652 }
61653
61654
61655
61656
61657
61658
61659
61660
61661
61662
61663 public function setErrorMessage($errorMessage)
61664 {
61665 $this->errorMessage = $errorMessage;
61666 $this->setValidator($this->getDefaultValidator());
61667
61668 return $this;
61669 }
61670
61671
61672
61673
61674
61675
61676 private function getDefaultValidator()
61677 {
61678 $choices = $this->choices;
61679 $errorMessage = $this->errorMessage;
61680 $multiselect = $this->multiselect;
61681 $isAssoc = $this->isAssoc($choices);
61682
61683 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
61684
61685  $selectedChoices = str_replace(' ', '', $selected);
61686
61687 if ($multiselect) {
61688
61689  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
61690 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
61691 }
61692 $selectedChoices = explode(',', $selectedChoices);
61693 } else {
61694 $selectedChoices = array($selected);
61695 }
61696
61697 $multiselectChoices = array();
61698 foreach ($selectedChoices as $value) {
61699 $results = array();
61700 foreach ($choices as $key => $choice) {
61701 if ($choice === $value) {
61702 $results[] = $key;
61703 }
61704 }
61705
61706 if (\count($results) > 1) {
61707 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
61708 }
61709
61710 $result = array_search($value, $choices);
61711
61712 if (!$isAssoc) {
61713 if (false !== $result) {
61714 $result = $choices[$result];
61715 } elseif (isset($choices[$value])) {
61716 $result = $choices[$value];
61717 }
61718 } elseif (false === $result && isset($choices[$value])) {
61719 $result = $value;
61720 }
61721
61722 if (false === $result) {
61723 throw new InvalidArgumentException(sprintf($errorMessage, $value));
61724 }
61725
61726 $multiselectChoices[] = (string) $result;
61727 }
61728
61729 if ($multiselect) {
61730 return $multiselectChoices;
61731 }
61732
61733 return current($multiselectChoices);
61734 };
61735 }
61736 }
61737 <?php
61738
61739
61740
61741
61742
61743
61744
61745
61746
61747
61748 namespace Symfony\Component\Console\Question;
61749
61750
61751
61752
61753
61754
61755 class ConfirmationQuestion extends Question
61756 {
61757 private $trueAnswerRegex;
61758
61759
61760
61761
61762
61763
61764 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
61765 {
61766 parent::__construct($question, (bool) $default);
61767
61768 $this->trueAnswerRegex = $trueAnswerRegex;
61769 $this->setNormalizer($this->getDefaultNormalizer());
61770 }
61771
61772
61773
61774
61775
61776
61777 private function getDefaultNormalizer()
61778 {
61779 $default = $this->getDefault();
61780 $regex = $this->trueAnswerRegex;
61781
61782 return function ($answer) use ($default, $regex) {
61783 if (\is_bool($answer)) {
61784 return $answer;
61785 }
61786
61787 $answerIsTrue = (bool) preg_match($regex, $answer);
61788 if (false === $default) {
61789 return $answer && $answerIsTrue;
61790 }
61791
61792 return !$answer || $answerIsTrue;
61793 };
61794 }
61795 }
61796 <?php
61797
61798
61799
61800
61801
61802
61803
61804
61805
61806
61807 namespace Symfony\Component\Console\Question;
61808
61809 use Symfony\Component\Console\Exception\InvalidArgumentException;
61810 use Symfony\Component\Console\Exception\LogicException;
61811
61812
61813
61814
61815
61816
61817 class Question
61818 {
61819 private $question;
61820 private $attempts;
61821 private $hidden = false;
61822 private $hiddenFallback = true;
61823 private $autocompleterValues;
61824 private $validator;
61825 private $default;
61826 private $normalizer;
61827
61828
61829
61830
61831
61832 public function __construct($question, $default = null)
61833 {
61834 $this->question = $question;
61835 $this->default = $default;
61836 }
61837
61838
61839
61840
61841
61842
61843 public function getQuestion()
61844 {
61845 return $this->question;
61846 }
61847
61848
61849
61850
61851
61852
61853 public function getDefault()
61854 {
61855 return $this->default;
61856 }
61857
61858
61859
61860
61861
61862
61863 public function isHidden()
61864 {
61865 return $this->hidden;
61866 }
61867
61868
61869
61870
61871
61872
61873
61874
61875
61876
61877 public function setHidden($hidden)
61878 {
61879 if ($this->autocompleterValues) {
61880 throw new LogicException('A hidden question cannot use the autocompleter.');
61881 }
61882
61883 $this->hidden = (bool) $hidden;
61884
61885 return $this;
61886 }
61887
61888
61889
61890
61891
61892
61893 public function isHiddenFallback()
61894 {
61895 return $this->hiddenFallback;
61896 }
61897
61898
61899
61900
61901
61902
61903
61904
61905 public function setHiddenFallback($fallback)
61906 {
61907 $this->hiddenFallback = (bool) $fallback;
61908
61909 return $this;
61910 }
61911
61912
61913
61914
61915
61916
61917 public function getAutocompleterValues()
61918 {
61919 return $this->autocompleterValues;
61920 }
61921
61922
61923
61924
61925
61926
61927
61928
61929
61930
61931
61932 public function setAutocompleterValues($values)
61933 {
61934 if (\is_array($values)) {
61935 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
61936 }
61937
61938 if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) {
61939 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
61940 }
61941
61942 if ($this->hidden) {
61943 throw new LogicException('A hidden question cannot use the autocompleter.');
61944 }
61945
61946 $this->autocompleterValues = $values;
61947
61948 return $this;
61949 }
61950
61951
61952
61953
61954
61955
61956
61957
61958 public function setValidator($validator)
61959 {
61960 $this->validator = $validator;
61961
61962 return $this;
61963 }
61964
61965
61966
61967
61968
61969
61970 public function getValidator()
61971 {
61972 return $this->validator;
61973 }
61974
61975
61976
61977
61978
61979
61980
61981
61982
61983
61984
61985
61986 public function setMaxAttempts($attempts)
61987 {
61988 if (null !== $attempts && $attempts < 1) {
61989 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
61990 }
61991
61992 $this->attempts = $attempts;
61993
61994 return $this;
61995 }
61996
61997
61998
61999
62000
62001
62002
62003
62004 public function getMaxAttempts()
62005 {
62006 return $this->attempts;
62007 }
62008
62009
62010
62011
62012
62013
62014
62015
62016
62017
62018 public function setNormalizer($normalizer)
62019 {
62020 $this->normalizer = $normalizer;
62021
62022 return $this;
62023 }
62024
62025
62026
62027
62028
62029
62030
62031
62032 public function getNormalizer()
62033 {
62034 return $this->normalizer;
62035 }
62036
62037 protected function isAssoc($array)
62038 {
62039 return (bool) \count(array_filter(array_keys($array), 'is_string'));
62040 }
62041 }
62042 <?php
62043
62044
62045
62046
62047
62048
62049
62050
62051
62052
62053 namespace Symfony\Component\Console;
62054
62055 use Symfony\Component\Console\Exception\RuntimeException;
62056 use Symfony\Component\Console\Input\StringInput;
62057 use Symfony\Component\Console\Output\ConsoleOutput;
62058 use Symfony\Component\Process\PhpExecutableFinder;
62059 use Symfony\Component\Process\ProcessBuilder;
62060
62061
62062
62063
62064
62065
62066
62067
62068
62069
62070
62071
62072 class Shell
62073 {
62074 private $application;
62075 private $history;
62076 private $output;
62077 private $hasReadline;
62078 private $processIsolation = false;
62079
62080
62081
62082
62083
62084 public function __construct(Application $application)
62085 {
62086 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
62087
62088 $this->hasReadline = \function_exists('readline');
62089 $this->application = $application;
62090 $this->history = getenv('HOME').'/.history_'.$application->getName();
62091 $this->output = new ConsoleOutput();
62092 }
62093
62094
62095
62096
62097 public function run()
62098 {
62099 $this->application->setAutoExit(false);
62100 $this->application->setCatchExceptions(true);
62101
62102 if ($this->hasReadline) {
62103 readline_read_history($this->history);
62104 readline_completion_function(array($this, 'autocompleter'));
62105 }
62106
62107 $this->output->writeln($this->getHeader());
62108 $php = null;
62109 if ($this->processIsolation) {
62110 $finder = new PhpExecutableFinder();
62111 $php = $finder->find();
62112 $this->output->writeln(<<<'EOF'
62113 <info>Running with process isolation, you should consider this:</info>
62114   * each command is executed as separate process,
62115   * commands don't support interactivity, all params must be passed explicitly,
62116   * commands output is not colorized.
62117
62118 EOF
62119 );
62120 }
62121
62122 while (true) {
62123 $command = $this->readline();
62124
62125 if (false === $command) {
62126 $this->output->writeln("\n");
62127
62128 break;
62129 }
62130
62131 if ($this->hasReadline) {
62132 readline_add_history($command);
62133 readline_write_history($this->history);
62134 }
62135
62136 if ($this->processIsolation) {
62137 $pb = new ProcessBuilder();
62138
62139 $process = $pb
62140 ->add($php)
62141 ->add($_SERVER['argv'][0])
62142 ->add($command)
62143 ->inheritEnvironmentVariables(true)
62144 ->getProcess()
62145 ;
62146
62147 $output = $this->output;
62148 $process->run(function ($type, $data) use ($output) {
62149 $output->writeln($data);
62150 });
62151
62152 $ret = $process->getExitCode();
62153 } else {
62154 $ret = $this->application->run(new StringInput($command), $this->output);
62155 }
62156
62157 if (0 !== $ret) {
62158 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
62159 }
62160 }
62161 }
62162
62163
62164
62165
62166
62167
62168 protected function getHeader()
62169 {
62170 return <<<EOF
62171
62172 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
62173
62174 At the prompt, type <comment>help</comment> for some help,
62175 or <comment>list</comment> to get a list of available commands.
62176
62177 To exit the shell, type <comment>^D</comment>.
62178
62179 EOF;
62180 }
62181
62182
62183
62184
62185
62186
62187 protected function getPrompt()
62188 {
62189
62190  return $this->output->getFormatter()->format($this->application->getName().' > ');
62191 }
62192
62193 protected function getOutput()
62194 {
62195 return $this->output;
62196 }
62197
62198 protected function getApplication()
62199 {
62200 return $this->application;
62201 }
62202
62203
62204
62205
62206
62207
62208
62209
62210 private function autocompleter($text)
62211 {
62212 $info = readline_info();
62213 $text = substr($info['line_buffer'], 0, $info['end']);
62214
62215 if ($info['point'] !== $info['end']) {
62216 return true;
62217 }
62218
62219
62220  if (false === strpos($text, ' ') || !$text) {
62221 return array_keys($this->application->all());
62222 }
62223
62224
62225  try {
62226 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
62227 } catch (\Exception $e) {
62228 return true;
62229 }
62230
62231 $list = array('--help');
62232 foreach ($command->getDefinition()->getOptions() as $option) {
62233 $list[] = '--'.$option->getName();
62234 }
62235
62236 return $list;
62237 }
62238
62239
62240
62241
62242
62243
62244 private function readline()
62245 {
62246 if ($this->hasReadline) {
62247 $line = readline($this->getPrompt());
62248 } else {
62249 $this->output->write($this->getPrompt());
62250 $line = fgets(STDIN, 1024);
62251 $line = (false === $line || '' === $line) ? false : rtrim($line);
62252 }
62253
62254 return $line;
62255 }
62256
62257 public function getProcessIsolation()
62258 {
62259 return $this->processIsolation;
62260 }
62261
62262 public function setProcessIsolation($processIsolation)
62263 {
62264 $this->processIsolation = (bool) $processIsolation;
62265
62266 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
62267 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
62268 }
62269 }
62270 }
62271 <?php
62272
62273
62274
62275
62276
62277
62278
62279
62280
62281
62282 namespace Symfony\Component\Console\Style;
62283
62284 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
62285 use Symfony\Component\Console\Helper\ProgressBar;
62286 use Symfony\Component\Console\Output\OutputInterface;
62287
62288
62289
62290
62291
62292
62293 abstract class OutputStyle implements OutputInterface, StyleInterface
62294 {
62295 private $output;
62296
62297 public function __construct(OutputInterface $output)
62298 {
62299 $this->output = $output;
62300 }
62301
62302
62303
62304
62305 public function newLine($count = 1)
62306 {
62307 $this->output->write(str_repeat(PHP_EOL, $count));
62308 }
62309
62310
62311
62312
62313
62314
62315 public function createProgressBar($max = 0)
62316 {
62317 return new ProgressBar($this->output, $max);
62318 }
62319
62320
62321
62322
62323 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
62324 {
62325 $this->output->write($messages, $newline, $type);
62326 }
62327
62328
62329
62330
62331 public function writeln($messages, $type = self::OUTPUT_NORMAL)
62332 {
62333 $this->output->writeln($messages, $type);
62334 }
62335
62336
62337
62338
62339 public function setVerbosity($level)
62340 {
62341 $this->output->setVerbosity($level);
62342 }
62343
62344
62345
62346
62347 public function getVerbosity()
62348 {
62349 return $this->output->getVerbosity();
62350 }
62351
62352
62353
62354
62355 public function setDecorated($decorated)
62356 {
62357 $this->output->setDecorated($decorated);
62358 }
62359
62360
62361
62362
62363 public function isDecorated()
62364 {
62365 return $this->output->isDecorated();
62366 }
62367
62368
62369
62370
62371 public function setFormatter(OutputFormatterInterface $formatter)
62372 {
62373 $this->output->setFormatter($formatter);
62374 }
62375
62376
62377
62378
62379 public function getFormatter()
62380 {
62381 return $this->output->getFormatter();
62382 }
62383 }
62384 <?php
62385
62386
62387
62388
62389
62390
62391
62392
62393
62394
62395 namespace Symfony\Component\Console\Style;
62396
62397
62398
62399
62400
62401
62402 interface StyleInterface
62403 {
62404
62405
62406
62407
62408
62409 public function title($message);
62410
62411
62412
62413
62414
62415
62416 public function section($message);
62417
62418
62419
62420
62421 public function listing(array $elements);
62422
62423
62424
62425
62426
62427
62428 public function text($message);
62429
62430
62431
62432
62433
62434
62435 public function success($message);
62436
62437
62438
62439
62440
62441
62442 public function error($message);
62443
62444
62445
62446
62447
62448
62449 public function warning($message);
62450
62451
62452
62453
62454
62455
62456 public function note($message);
62457
62458
62459
62460
62461
62462
62463 public function caution($message);
62464
62465
62466
62467
62468 public function table(array $headers, array $rows);
62469
62470
62471
62472
62473
62474
62475
62476
62477
62478
62479 public function ask($question, $default = null, $validator = null);
62480
62481
62482
62483
62484
62485
62486
62487
62488
62489 public function askHidden($question, $validator = null);
62490
62491
62492
62493
62494
62495
62496
62497
62498
62499 public function confirm($question, $default = true);
62500
62501
62502
62503
62504
62505
62506
62507
62508
62509
62510 public function choice($question, array $choices, $default = null);
62511
62512
62513
62514
62515
62516
62517 public function newLine($count = 1);
62518
62519
62520
62521
62522
62523
62524 public function progressStart($max = 0);
62525
62526
62527
62528
62529
62530
62531 public function progressAdvance($step = 1);
62532
62533
62534
62535
62536 public function progressFinish();
62537 }
62538 <?php
62539
62540
62541
62542
62543
62544
62545
62546
62547
62548
62549 namespace Symfony\Component\Console\Style;
62550
62551 use Symfony\Component\Console\Application;
62552 use Symfony\Component\Console\Exception\RuntimeException;
62553 use Symfony\Component\Console\Formatter\OutputFormatter;
62554 use Symfony\Component\Console\Helper\Helper;
62555 use Symfony\Component\Console\Helper\ProgressBar;
62556 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
62557 use Symfony\Component\Console\Helper\Table;
62558 use Symfony\Component\Console\Input\InputInterface;
62559 use Symfony\Component\Console\Output\BufferedOutput;
62560 use Symfony\Component\Console\Output\OutputInterface;
62561 use Symfony\Component\Console\Question\ChoiceQuestion;
62562 use Symfony\Component\Console\Question\ConfirmationQuestion;
62563 use Symfony\Component\Console\Question\Question;
62564
62565
62566
62567
62568
62569
62570 class SymfonyStyle extends OutputStyle
62571 {
62572 const MAX_LINE_LENGTH = 120;
62573
62574 private $input;
62575 private $questionHelper;
62576 private $progressBar;
62577 private $lineLength;
62578 private $bufferedOutput;
62579
62580 public function __construct(InputInterface $input, OutputInterface $output)
62581 {
62582 $this->input = $input;
62583 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
62584
62585  $this->lineLength = min($this->getTerminalWidth() - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
62586
62587 parent::__construct($output);
62588 }
62589
62590
62591
62592
62593
62594
62595
62596
62597
62598
62599 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
62600 {
62601 $messages = \is_array($messages) ? array_values($messages) : array($messages);
62602
62603 $this->autoPrependBlock();
62604 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
62605 $this->newLine();
62606 }
62607
62608
62609
62610
62611 public function title($message)
62612 {
62613 $this->autoPrependBlock();
62614 $this->writeln(array(
62615 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
62616 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
62617 ));
62618 $this->newLine();
62619 }
62620
62621
62622
62623
62624 public function section($message)
62625 {
62626 $this->autoPrependBlock();
62627 $this->writeln(array(
62628 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
62629 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
62630 ));
62631 $this->newLine();
62632 }
62633
62634
62635
62636
62637 public function listing(array $elements)
62638 {
62639 $this->autoPrependText();
62640 $elements = array_map(function ($element) {
62641 return sprintf(' * %s', $element);
62642 }, $elements);
62643
62644 $this->writeln($elements);
62645 $this->newLine();
62646 }
62647
62648
62649
62650
62651 public function text($message)
62652 {
62653 $this->autoPrependText();
62654
62655 $messages = \is_array($message) ? array_values($message) : array($message);
62656 foreach ($messages as $message) {
62657 $this->writeln(sprintf(' %s', $message));
62658 }
62659 }
62660
62661
62662
62663
62664
62665
62666 public function comment($message)
62667 {
62668 $messages = \is_array($message) ? array_values($message) : array($message);
62669
62670 $this->autoPrependBlock();
62671 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
62672 $this->newLine();
62673 }
62674
62675
62676
62677
62678 public function success($message)
62679 {
62680 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
62681 }
62682
62683
62684
62685
62686 public function error($message)
62687 {
62688 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
62689 }
62690
62691
62692
62693
62694 public function warning($message)
62695 {
62696 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
62697 }
62698
62699
62700
62701
62702 public function note($message)
62703 {
62704 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
62705 }
62706
62707
62708
62709
62710 public function caution($message)
62711 {
62712 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
62713 }
62714
62715
62716
62717
62718 public function table(array $headers, array $rows)
62719 {
62720 $style = clone Table::getStyleDefinition('symfony-style-guide');
62721 $style->setCellHeaderFormat('<info>%s</info>');
62722
62723 $table = new Table($this);
62724 $table->setHeaders($headers);
62725 $table->setRows($rows);
62726 $table->setStyle($style);
62727
62728 $table->render();
62729 $this->newLine();
62730 }
62731
62732
62733
62734
62735 public function ask($question, $default = null, $validator = null)
62736 {
62737 $question = new Question($question, $default);
62738 $question->setValidator($validator);
62739
62740 return $this->askQuestion($question);
62741 }
62742
62743
62744
62745
62746 public function askHidden($question, $validator = null)
62747 {
62748 $question = new Question($question);
62749
62750 $question->setHidden(true);
62751 $question->setValidator($validator);
62752
62753 return $this->askQuestion($question);
62754 }
62755
62756
62757
62758
62759 public function confirm($question, $default = true)
62760 {
62761 return $this->askQuestion(new ConfirmationQuestion($question, $default));
62762 }
62763
62764
62765
62766
62767 public function choice($question, array $choices, $default = null)
62768 {
62769 if (null !== $default) {
62770 $values = array_flip($choices);
62771 $default = $values[$default];
62772 }
62773
62774 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
62775 }
62776
62777
62778
62779
62780 public function progressStart($max = 0)
62781 {
62782 $this->progressBar = $this->createProgressBar($max);
62783 $this->progressBar->start();
62784 }
62785
62786
62787
62788
62789 public function progressAdvance($step = 1)
62790 {
62791 $this->getProgressBar()->advance($step);
62792 }
62793
62794
62795
62796
62797 public function progressFinish()
62798 {
62799 $this->getProgressBar()->finish();
62800 $this->newLine(2);
62801 $this->progressBar = null;
62802 }
62803
62804
62805
62806
62807 public function createProgressBar($max = 0)
62808 {
62809 $progressBar = parent::createProgressBar($max);
62810
62811 if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
62812 $progressBar->setEmptyBarCharacter('░'); 
62813  $progressBar->setProgressCharacter('');
62814 $progressBar->setBarCharacter('▓'); 
62815  }
62816
62817 return $progressBar;
62818 }
62819
62820
62821
62822
62823 public function askQuestion(Question $question)
62824 {
62825 if ($this->input->isInteractive()) {
62826 $this->autoPrependBlock();
62827 }
62828
62829 if (!$this->questionHelper) {
62830 $this->questionHelper = new SymfonyQuestionHelper();
62831 }
62832
62833 $answer = $this->questionHelper->ask($this->input, $this, $question);
62834
62835 if ($this->input->isInteractive()) {
62836 $this->newLine();
62837 $this->bufferedOutput->write("\n");
62838 }
62839
62840 return $answer;
62841 }
62842
62843
62844
62845
62846 public function writeln($messages, $type = self::OUTPUT_NORMAL)
62847 {
62848 parent::writeln($messages, $type);
62849 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
62850 }
62851
62852
62853
62854
62855 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
62856 {
62857 parent::write($messages, $newline, $type);
62858 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
62859 }
62860
62861
62862
62863
62864 public function newLine($count = 1)
62865 {
62866 parent::newLine($count);
62867 $this->bufferedOutput->write(str_repeat("\n", $count));
62868 }
62869
62870
62871
62872
62873 private function getProgressBar()
62874 {
62875 if (!$this->progressBar) {
62876 throw new RuntimeException('The ProgressBar is not started.');
62877 }
62878
62879 return $this->progressBar;
62880 }
62881
62882 private function getTerminalWidth()
62883 {
62884 $application = new Application();
62885 $dimensions = $application->getTerminalDimensions();
62886
62887 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
62888 }
62889
62890 private function autoPrependBlock()
62891 {
62892 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
62893
62894 if (!isset($chars[0])) {
62895 return $this->newLine(); 
62896  }
62897
62898  $this->newLine(2 - substr_count($chars, "\n"));
62899 }
62900
62901 private function autoPrependText()
62902 {
62903 $fetched = $this->bufferedOutput->fetch();
62904
62905  if ("\n" !== substr($fetched, -1)) {
62906 $this->newLine();
62907 }
62908 }
62909
62910 private function reduceBuffer($messages)
62911 {
62912
62913  
62914  return array_map(function ($value) {
62915 return substr($value, -4);
62916 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
62917 }
62918
62919 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
62920 {
62921 $indentLength = 0;
62922 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
62923 $lines = array();
62924
62925 if (null !== $type) {
62926 $type = sprintf('[%s] ', $type);
62927 $indentLength = \strlen($type);
62928 $lineIndentation = str_repeat(' ', $indentLength);
62929 }
62930
62931
62932  foreach ($messages as $key => $message) {
62933 if ($escape) {
62934 $message = OutputFormatter::escape($message);
62935 }
62936
62937 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
62938
62939 if (\count($messages) > 1 && $key < \count($messages) - 1) {
62940 $lines[] = '';
62941 }
62942 }
62943
62944 $firstLineIndex = 0;
62945 if ($padding && $this->isDecorated()) {
62946 $firstLineIndex = 1;
62947 array_unshift($lines, '');
62948 $lines[] = '';
62949 }
62950
62951 foreach ($lines as $i => &$line) {
62952 if (null !== $type) {
62953 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
62954 }
62955
62956 $line = $prefix.$line;
62957 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
62958
62959 if ($style) {
62960 $line = sprintf('<%s>%s</>', $style, $line);
62961 }
62962 }
62963
62964 return $lines;
62965 }
62966 }
62967 <?php
62968
62969
62970
62971
62972
62973
62974
62975
62976
62977
62978 namespace Symfony\Component\Console\Tester;
62979
62980 use Symfony\Component\Console\Application;
62981 use Symfony\Component\Console\Input\ArrayInput;
62982 use Symfony\Component\Console\Input\InputInterface;
62983 use Symfony\Component\Console\Output\OutputInterface;
62984 use Symfony\Component\Console\Output\StreamOutput;
62985
62986
62987
62988
62989
62990
62991
62992
62993
62994
62995
62996 class ApplicationTester
62997 {
62998 private $application;
62999 private $input;
63000 private $output;
63001 private $statusCode;
63002
63003 public function __construct(Application $application)
63004 {
63005 $this->application = $application;
63006 }
63007
63008
63009
63010
63011
63012
63013
63014
63015
63016
63017
63018
63019
63020
63021
63022 public function run(array $input, $options = array())
63023 {
63024 $this->input = new ArrayInput($input);
63025 if (isset($options['interactive'])) {
63026 $this->input->setInteractive($options['interactive']);
63027 }
63028
63029 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
63030 if (isset($options['decorated'])) {
63031 $this->output->setDecorated($options['decorated']);
63032 }
63033 if (isset($options['verbosity'])) {
63034 $this->output->setVerbosity($options['verbosity']);
63035 }
63036
63037 return $this->statusCode = $this->application->run($this->input, $this->output);
63038 }
63039
63040
63041
63042
63043
63044
63045
63046
63047 public function getDisplay($normalize = false)
63048 {
63049 rewind($this->output->getStream());
63050
63051 $display = stream_get_contents($this->output->getStream());
63052
63053 if ($normalize) {
63054 $display = str_replace(PHP_EOL, "\n", $display);
63055 }
63056
63057 return $display;
63058 }
63059
63060
63061
63062
63063
63064
63065 public function getInput()
63066 {
63067 return $this->input;
63068 }
63069
63070
63071
63072
63073
63074
63075 public function getOutput()
63076 {
63077 return $this->output;
63078 }
63079
63080
63081
63082
63083
63084
63085 public function getStatusCode()
63086 {
63087 return $this->statusCode;
63088 }
63089 }
63090 <?php
63091
63092
63093
63094
63095
63096
63097
63098
63099
63100
63101 namespace Symfony\Component\Console\Tester;
63102
63103 use Symfony\Component\Console\Command\Command;
63104 use Symfony\Component\Console\Input\ArrayInput;
63105 use Symfony\Component\Console\Input\InputInterface;
63106 use Symfony\Component\Console\Output\OutputInterface;
63107 use Symfony\Component\Console\Output\StreamOutput;
63108
63109
63110
63111
63112
63113
63114 class CommandTester
63115 {
63116 private $command;
63117 private $input;
63118 private $output;
63119 private $statusCode;
63120
63121 public function __construct(Command $command)
63122 {
63123 $this->command = $command;
63124 }
63125
63126
63127
63128
63129
63130
63131
63132
63133
63134
63135
63136
63137
63138
63139
63140 public function execute(array $input, array $options = array())
63141 {
63142
63143  
63144  if (!isset($input['command'])
63145 && (null !== $application = $this->command->getApplication())
63146 && $application->getDefinition()->hasArgument('command')
63147 ) {
63148 $input = array_merge(array('command' => $this->command->getName()), $input);
63149 }
63150
63151 $this->input = new ArrayInput($input);
63152 if (isset($options['interactive'])) {
63153 $this->input->setInteractive($options['interactive']);
63154 }
63155
63156 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
63157 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
63158 if (isset($options['verbosity'])) {
63159 $this->output->setVerbosity($options['verbosity']);
63160 }
63161
63162 return $this->statusCode = $this->command->run($this->input, $this->output);
63163 }
63164
63165
63166
63167
63168
63169
63170
63171
63172 public function getDisplay($normalize = false)
63173 {
63174 rewind($this->output->getStream());
63175
63176 $display = stream_get_contents($this->output->getStream());
63177
63178 if ($normalize) {
63179 $display = str_replace(PHP_EOL, "\n", $display);
63180 }
63181
63182 return $display;
63183 }
63184
63185
63186
63187
63188
63189
63190 public function getInput()
63191 {
63192 return $this->input;
63193 }
63194
63195
63196
63197
63198
63199
63200 public function getOutput()
63201 {
63202 return $this->output;
63203 }
63204
63205
63206
63207
63208
63209
63210 public function getStatusCode()
63211 {
63212 return $this->statusCode;
63213 }
63214 }
63215 <?php
63216
63217
63218
63219
63220
63221
63222
63223
63224
63225
63226 namespace Symfony\Component\Debug;
63227
63228 use Psr\Log\AbstractLogger;
63229
63230
63231
63232
63233
63234
63235 class BufferingLogger extends AbstractLogger
63236 {
63237 private $logs = array();
63238
63239 public function log($level, $message, array $context = array())
63240 {
63241 $this->logs[] = array($level, $message, $context);
63242 }
63243
63244 public function cleanLogs()
63245 {
63246 $logs = $this->logs;
63247 $this->logs = array();
63248
63249 return $logs;
63250 }
63251 }
63252 <?php
63253
63254
63255
63256
63257
63258
63259
63260
63261
63262
63263 namespace Symfony\Component\Debug;
63264
63265
63266
63267
63268
63269
63270 class Debug
63271 {
63272 private static $enabled = false;
63273
63274
63275
63276
63277
63278
63279
63280
63281
63282 public static function enable($errorReportingLevel = null, $displayErrors = true)
63283 {
63284 if (static::$enabled) {
63285 return;
63286 }
63287
63288 static::$enabled = true;
63289
63290 if (null !== $errorReportingLevel) {
63291 error_reporting($errorReportingLevel);
63292 } else {
63293 error_reporting(-1);
63294 }
63295
63296 if (!\in_array(\PHP_SAPI, array('cli', 'phpdbg'), true)) {
63297 ini_set('display_errors', 0);
63298 ExceptionHandler::register();
63299 } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) {
63300
63301  ini_set('display_errors', 1);
63302 }
63303 if ($displayErrors) {
63304 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
63305 } else {
63306 ErrorHandler::register()->throwAt(0, true);
63307 }
63308
63309 DebugClassLoader::enable();
63310 }
63311 }
63312 <?php
63313
63314
63315
63316
63317
63318
63319
63320
63321
63322
63323 namespace Symfony\Component\Debug;
63324
63325
63326
63327
63328
63329
63330
63331
63332
63333
63334
63335
63336 class DebugClassLoader
63337 {
63338 private $classLoader;
63339 private $isFinder;
63340 private $loaded = array();
63341 private $wasFinder;
63342 private static $caseCheck;
63343 private static $deprecated = array();
63344 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
63345 private static $darwinCache = array('/' => array('/', array()));
63346
63347
63348
63349
63350 public function __construct($classLoader)
63351 {
63352 $this->wasFinder = \is_object($classLoader) && method_exists($classLoader, 'findFile');
63353
63354 if ($this->wasFinder) {
63355 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
63356 $this->classLoader = array($classLoader, 'loadClass');
63357 $this->isFinder = true;
63358 } else {
63359 $this->classLoader = $classLoader;
63360 $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
63361 }
63362
63363 if (!isset(self::$caseCheck)) {
63364 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
63365 $i = strrpos($file, \DIRECTORY_SEPARATOR);
63366 $dir = substr($file, 0, 1 + $i);
63367 $file = substr($file, 1 + $i);
63368 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
63369 $test = realpath($dir.$test);
63370
63371 if (false === $test || false === $i) {
63372
63373  self::$caseCheck = 0;
63374 } elseif (substr($test, -\strlen($file)) === $file) {
63375
63376  self::$caseCheck = 1;
63377 } elseif (false !== stripos(PHP_OS, 'darwin')) {
63378
63379  self::$caseCheck = 2;
63380 } else {
63381
63382  self::$caseCheck = 0;
63383 }
63384 }
63385 }
63386
63387
63388
63389
63390
63391
63392 public function getClassLoader()
63393 {
63394 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
63395 }
63396
63397
63398
63399
63400 public static function enable()
63401 {
63402
63403  class_exists('Symfony\Component\Debug\ErrorHandler');
63404 class_exists('Psr\Log\LogLevel');
63405
63406 if (!\is_array($functions = spl_autoload_functions())) {
63407 return;
63408 }
63409
63410 foreach ($functions as $function) {
63411 spl_autoload_unregister($function);
63412 }
63413
63414 foreach ($functions as $function) {
63415 if (!\is_array($function) || !$function[0] instanceof self) {
63416 $function = array(new static($function), 'loadClass');
63417 }
63418
63419 spl_autoload_register($function);
63420 }
63421 }
63422
63423
63424
63425
63426 public static function disable()
63427 {
63428 if (!\is_array($functions = spl_autoload_functions())) {
63429 return;
63430 }
63431
63432 foreach ($functions as $function) {
63433 spl_autoload_unregister($function);
63434 }
63435
63436 foreach ($functions as $function) {
63437 if (\is_array($function) && $function[0] instanceof self) {
63438 $function = $function[0]->getClassLoader();
63439 }
63440
63441 spl_autoload_register($function);
63442 }
63443 }
63444
63445
63446
63447
63448
63449
63450
63451
63452
63453
63454 public function findFile($class)
63455 {
63456 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
63457
63458 if ($this->wasFinder) {
63459 return $this->classLoader[0]->findFile($class);
63460 }
63461 }
63462
63463
63464
63465
63466
63467
63468
63469
63470
63471
63472 public function loadClass($class)
63473 {
63474 ErrorHandler::stackErrors();
63475
63476 try {
63477 if ($this->isFinder && !isset($this->loaded[$class])) {
63478 $this->loaded[$class] = true;
63479 if ($file = $this->classLoader[0]->findFile($class)) {
63480 require $file;
63481 }
63482 } else {
63483 \call_user_func($this->classLoader, $class);
63484 $file = false;
63485 }
63486 } catch (\Exception $e) {
63487 ErrorHandler::unstackErrors();
63488
63489 throw $e;
63490 } catch (\Throwable $e) {
63491 ErrorHandler::unstackErrors();
63492
63493 throw $e;
63494 }
63495
63496 ErrorHandler::unstackErrors();
63497
63498 $exists = class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
63499
63500 if ($class && '\\' === $class[0]) {
63501 $class = substr($class, 1);
63502 }
63503
63504 if ($exists) {
63505 $refl = new \ReflectionClass($class);
63506 $name = $refl->getName();
63507
63508 if ($name !== $class && 0 === strcasecmp($name, $class)) {
63509 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
63510 }
63511
63512 if (\in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
63513 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
63514 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
63515 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
63516 } else {
63517 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
63518 $len = 0;
63519 $ns = '';
63520 } else {
63521 $ns = substr($name, 0, $len);
63522 }
63523 $parent = get_parent_class($class);
63524
63525 if (!$parent || strncmp($ns, $parent, $len)) {
63526 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
63527 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
63528 }
63529
63530 $parentInterfaces = array();
63531 $deprecatedInterfaces = array();
63532 if ($parent) {
63533 foreach (class_implements($parent) as $interface) {
63534 $parentInterfaces[$interface] = 1;
63535 }
63536 }
63537
63538 foreach ($refl->getInterfaceNames() as $interface) {
63539 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
63540 $deprecatedInterfaces[] = $interface;
63541 }
63542 foreach (class_implements($interface) as $interface) {
63543 $parentInterfaces[$interface] = 1;
63544 }
63545 }
63546
63547 foreach ($deprecatedInterfaces as $interface) {
63548 if (!isset($parentInterfaces[$interface])) {
63549 @trigger_error(sprintf('The %s %s %s that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
63550 }
63551 }
63552 }
63553 }
63554 }
63555
63556 if ($file) {
63557 if (!$exists) {
63558 if (false !== strpos($class, '/')) {
63559 throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
63560 }
63561
63562 throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
63563 }
63564 if (self::$caseCheck) {
63565 $real = explode('\\', $class.strrchr($file, '.'));
63566 $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
63567
63568 $i = \count($tail) - 1;
63569 $j = \count($real) - 1;
63570
63571 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
63572 --$i;
63573 --$j;
63574 }
63575
63576 array_splice($tail, 0, $i + 1);
63577 }
63578 if (self::$caseCheck && $tail) {
63579 $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
63580 $tailLen = \strlen($tail);
63581 $real = $refl->getFileName();
63582
63583 if (2 === self::$caseCheck) {
63584
63585
63586 $i = 1 + strrpos($real, '/');
63587 $file = substr($real, $i);
63588 $real = substr($real, 0, $i);
63589
63590 if (isset(self::$darwinCache[$real])) {
63591 $kDir = $real;
63592 } else {
63593 $kDir = strtolower($real);
63594
63595 if (isset(self::$darwinCache[$kDir])) {
63596 $real = self::$darwinCache[$kDir][0];
63597 } else {
63598 $dir = getcwd();
63599 chdir($real);
63600 $real = getcwd().'/';
63601 chdir($dir);
63602
63603 $dir = $real;
63604 $k = $kDir;
63605 $i = \strlen($dir) - 1;
63606 while (!isset(self::$darwinCache[$k])) {
63607 self::$darwinCache[$k] = array($dir, array());
63608 self::$darwinCache[$dir] = &self::$darwinCache[$k];
63609
63610 while ('/' !== $dir[--$i]) {
63611 }
63612 $k = substr($k, 0, ++$i);
63613 $dir = substr($dir, 0, $i--);
63614 }
63615 }
63616 }
63617
63618 $dirFiles = self::$darwinCache[$kDir][1];
63619
63620 if (isset($dirFiles[$file])) {
63621 $kFile = $file;
63622 } else {
63623 $kFile = strtolower($file);
63624
63625 if (!isset($dirFiles[$kFile])) {
63626 foreach (scandir($real, 2) as $f) {
63627 if ('.' !== $f[0]) {
63628 $dirFiles[$f] = $f;
63629 if ($f === $file) {
63630 $kFile = $k = $file;
63631 } elseif ($f !== $k = strtolower($f)) {
63632 $dirFiles[$k] = $f;
63633 }
63634 }
63635 }
63636 self::$darwinCache[$kDir][1] = $dirFiles;
63637 }
63638 }
63639
63640 $real .= $dirFiles[$kFile];
63641 }
63642
63643 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
63644 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
63645 ) {
63646 throw new \RuntimeException(sprintf('Case mismatch between class and real file names: %s vs %s in %s', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)));
63647 }
63648 }
63649
63650 return true;
63651 }
63652 }
63653 }
63654 <?php
63655
63656
63657
63658
63659
63660
63661
63662
63663
63664
63665 namespace Symfony\Component\Debug;
63666
63667 use Psr\Log\LoggerInterface;
63668 use Psr\Log\LogLevel;
63669 use Symfony\Component\Debug\Exception\ContextErrorException;
63670 use Symfony\Component\Debug\Exception\FatalErrorException;
63671 use Symfony\Component\Debug\Exception\FatalThrowableError;
63672 use Symfony\Component\Debug\Exception\OutOfMemoryException;
63673 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
63674 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
63675 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
63676 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
63677
63678
63679
63680
63681
63682
63683
63684
63685
63686
63687
63688
63689
63690
63691
63692
63693
63694
63695
63696
63697
63698
63699
63700 class ErrorHandler
63701 {
63702
63703
63704
63705 const TYPE_DEPRECATION = -100;
63706
63707 private $levels = array(
63708 E_DEPRECATED => 'Deprecated',
63709 E_USER_DEPRECATED => 'User Deprecated',
63710 E_NOTICE => 'Notice',
63711 E_USER_NOTICE => 'User Notice',
63712 E_STRICT => 'Runtime Notice',
63713 E_WARNING => 'Warning',
63714 E_USER_WARNING => 'User Warning',
63715 E_COMPILE_WARNING => 'Compile Warning',
63716 E_CORE_WARNING => 'Core Warning',
63717 E_USER_ERROR => 'User Error',
63718 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
63719 E_COMPILE_ERROR => 'Compile Error',
63720 E_PARSE => 'Parse Error',
63721 E_ERROR => 'Error',
63722 E_CORE_ERROR => 'Core Error',
63723 );
63724
63725 private $loggers = array(
63726 E_DEPRECATED => array(null, LogLevel::INFO),
63727 E_USER_DEPRECATED => array(null, LogLevel::INFO),
63728 E_NOTICE => array(null, LogLevel::WARNING),
63729 E_USER_NOTICE => array(null, LogLevel::WARNING),
63730 E_STRICT => array(null, LogLevel::WARNING),
63731 E_WARNING => array(null, LogLevel::WARNING),
63732 E_USER_WARNING => array(null, LogLevel::WARNING),
63733 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
63734 E_CORE_WARNING => array(null, LogLevel::WARNING),
63735 E_USER_ERROR => array(null, LogLevel::CRITICAL),
63736 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
63737 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
63738 E_PARSE => array(null, LogLevel::CRITICAL),
63739 E_ERROR => array(null, LogLevel::CRITICAL),
63740 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
63741 );
63742
63743 private $thrownErrors = 0x1FFF; 
63744  private $scopedErrors = 0x1FFF; 
63745  private $tracedErrors = 0x77FB; 
63746  private $screamedErrors = 0x55; 
63747  private $loggedErrors = 0;
63748
63749 private $loggedTraces = array();
63750 private $isRecursive = 0;
63751 private $isRoot = false;
63752 private $exceptionHandler;
63753 private $bootstrappingLogger;
63754
63755 private static $reservedMemory;
63756 private static $stackedErrors = array();
63757 private static $stackedErrorLevels = array();
63758 private static $toStringException = null;
63759 private static $exitCode = 0;
63760
63761
63762
63763
63764
63765
63766 private $displayErrors = 0x1FFF;
63767
63768
63769
63770
63771
63772
63773
63774
63775
63776 public static function register($handler = null, $replace = true)
63777 {
63778 if (null === self::$reservedMemory) {
63779 self::$reservedMemory = str_repeat('x', 10240);
63780 register_shutdown_function(__CLASS__.'::handleFatalError');
63781 }
63782
63783 $levels = -1;
63784
63785 if ($handlerIsNew = !$handler instanceof self) {
63786
63787  if (null !== $handler) {
63788 $levels = $replace ? $handler : 0;
63789 $replace = true;
63790 }
63791 $handler = new static();
63792 }
63793
63794 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
63795 restore_error_handler();
63796
63797  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
63798 $handler->isRoot = true;
63799 }
63800
63801 if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) {
63802 $handler = $prev[0];
63803 $replace = false;
63804 }
63805 if (!$replace && $prev) {
63806 restore_error_handler();
63807 $handlerIsRegistered = \is_array($prev) && $handler === $prev[0];
63808 } else {
63809 $handlerIsRegistered = true;
63810 }
63811 if (\is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
63812 restore_exception_handler();
63813 if (!$handlerIsRegistered) {
63814 $handler = $prev[0];
63815 } elseif ($handler !== $prev[0] && $replace) {
63816 set_exception_handler(array($handler, 'handleException'));
63817 $p = $prev[0]->setExceptionHandler(null);
63818 $handler->setExceptionHandler($p);
63819 $prev[0]->setExceptionHandler($p);
63820 }
63821 } else {
63822 $handler->setExceptionHandler($prev);
63823 }
63824
63825 $handler->throwAt($levels & $handler->thrownErrors, true);
63826
63827 return $handler;
63828 }
63829
63830 public function __construct(BufferingLogger $bootstrappingLogger = null)
63831 {
63832 if ($bootstrappingLogger) {
63833 $this->bootstrappingLogger = $bootstrappingLogger;
63834 $this->setDefaultLogger($bootstrappingLogger);
63835 }
63836 }
63837
63838
63839
63840
63841
63842
63843
63844
63845 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
63846 {
63847 $loggers = array();
63848
63849 if (\is_array($levels)) {
63850 foreach ($levels as $type => $logLevel) {
63851 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
63852 $loggers[$type] = array($logger, $logLevel);
63853 }
63854 }
63855 } else {
63856 if (null === $levels) {
63857 $levels = E_ALL | E_STRICT;
63858 }
63859 foreach ($this->loggers as $type => $log) {
63860 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
63861 $log[0] = $logger;
63862 $loggers[$type] = $log;
63863 }
63864 }
63865 }
63866
63867 $this->setLoggers($loggers);
63868 }
63869
63870
63871
63872
63873
63874
63875
63876
63877
63878
63879 public function setLoggers(array $loggers)
63880 {
63881 $prevLogged = $this->loggedErrors;
63882 $prev = $this->loggers;
63883 $flush = array();
63884
63885 foreach ($loggers as $type => $log) {
63886 if (!isset($prev[$type])) {
63887 throw new \InvalidArgumentException('Unknown error type: '.$type);
63888 }
63889 if (!\is_array($log)) {
63890 $log = array($log);
63891 } elseif (!array_key_exists(0, $log)) {
63892 throw new \InvalidArgumentException('No logger provided');
63893 }
63894 if (null === $log[0]) {
63895 $this->loggedErrors &= ~$type;
63896 } elseif ($log[0] instanceof LoggerInterface) {
63897 $this->loggedErrors |= $type;
63898 } else {
63899 throw new \InvalidArgumentException('Invalid logger provided');
63900 }
63901 $this->loggers[$type] = $log + $prev[$type];
63902
63903 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
63904 $flush[$type] = $type;
63905 }
63906 }
63907 $this->reRegister($prevLogged | $this->thrownErrors);
63908
63909 if ($flush) {
63910 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
63911 $type = $log[2]['type'];
63912 if (!isset($flush[$type])) {
63913 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
63914 } elseif ($this->loggers[$type][0]) {
63915 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
63916 }
63917 }
63918 }
63919
63920 return $prev;
63921 }
63922
63923
63924
63925
63926
63927
63928
63929
63930
63931
63932 public function setExceptionHandler($handler)
63933 {
63934 if (null !== $handler && !\is_callable($handler)) {
63935 throw new \LogicException('The exception handler must be a valid PHP callable.');
63936 }
63937 $prev = $this->exceptionHandler;
63938 $this->exceptionHandler = $handler;
63939
63940 return $prev;
63941 }
63942
63943
63944
63945
63946
63947
63948
63949
63950
63951 public function throwAt($levels, $replace = false)
63952 {
63953 $prev = $this->thrownErrors;
63954 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
63955 if (!$replace) {
63956 $this->thrownErrors |= $prev;
63957 }
63958 $this->reRegister($prev | $this->loggedErrors);
63959
63960
63961  $this->displayErrors = $this->thrownErrors;
63962
63963 return $prev;
63964 }
63965
63966
63967
63968
63969
63970
63971
63972
63973
63974 public function scopeAt($levels, $replace = false)
63975 {
63976 $prev = $this->scopedErrors;
63977 $this->scopedErrors = (int) $levels;
63978 if (!$replace) {
63979 $this->scopedErrors |= $prev;
63980 }
63981
63982 return $prev;
63983 }
63984
63985
63986
63987
63988
63989
63990
63991
63992
63993 public function traceAt($levels, $replace = false)
63994 {
63995 $prev = $this->tracedErrors;
63996 $this->tracedErrors = (int) $levels;
63997 if (!$replace) {
63998 $this->tracedErrors |= $prev;
63999 }
64000
64001 return $prev;
64002 }
64003
64004
64005
64006
64007
64008
64009
64010
64011
64012 public function screamAt($levels, $replace = false)
64013 {
64014 $prev = $this->screamedErrors;
64015 $this->screamedErrors = (int) $levels;
64016 if (!$replace) {
64017 $this->screamedErrors |= $prev;
64018 }
64019
64020 return $prev;
64021 }
64022
64023
64024
64025
64026 private function reRegister($prev)
64027 {
64028 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
64029 $handler = set_error_handler('var_dump');
64030 $handler = \is_array($handler) ? $handler[0] : null;
64031 restore_error_handler();
64032 if ($handler === $this) {
64033 restore_error_handler();
64034 if ($this->isRoot) {
64035 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
64036 } else {
64037 set_error_handler(array($this, 'handleError'));
64038 }
64039 }
64040 }
64041 }
64042
64043
64044
64045
64046
64047
64048
64049
64050
64051
64052
64053
64054
64055
64056
64057 public function handleError($type, $message, $file, $line)
64058 {
64059 $level = error_reporting();
64060 $silenced = 0 === ($level & $type);
64061 $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
64062 $log = $this->loggedErrors & $type;
64063 $throw = $this->thrownErrors & $type & $level;
64064 $type &= $level | $this->screamedErrors;
64065
64066 if (!$type || (!$log && !$throw)) {
64067 return !$silenced && $type && $log;
64068 }
64069 $scope = $this->scopedErrors & $type;
64070
64071 if (4 < $numArgs = \func_num_args()) {
64072 $context = $scope ? (func_get_arg(4) ?: array()) : array();
64073 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
64074  } else {
64075 $context = array();
64076 $backtrace = null;
64077 }
64078
64079 if (isset($context['GLOBALS']) && $scope) {
64080 $e = $context; 
64081  unset($e['GLOBALS'], $context); 
64082  $context = $e;
64083 }
64084
64085 if (null !== $backtrace && $type & E_ERROR) {
64086
64087  
64088  
64089  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
64090
64091 return true;
64092 }
64093
64094 if ($throw) {
64095 if (null !== self::$toStringException) {
64096 $throw = self::$toStringException;
64097 self::$toStringException = null;
64098 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
64099
64100  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
64101 } else {
64102 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
64103 }
64104
64105 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
64106
64107  
64108  
64109
64110 $throw->errorHandlerCanary = new ErrorHandlerCanary();
64111 }
64112
64113 if (E_USER_ERROR & $type) {
64114 $backtrace = $backtrace ?: $throw->getTrace();
64115
64116 for ($i = 1; isset($backtrace[$i]); ++$i) {
64117 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
64118 && '__toString' === $backtrace[$i]['function']
64119 && '->' === $backtrace[$i]['type']
64120 && !isset($backtrace[$i - 1]['class'])
64121 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
64122 ) {
64123
64124  
64125  
64126  
64127  
64128  
64129
64130 foreach ($context as $e) {
64131 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
64132 if (1 === $i) {
64133
64134  $throw = $e;
64135 break;
64136 }
64137 self::$toStringException = $e;
64138
64139 return true;
64140 }
64141 }
64142
64143 if (1 < $i) {
64144
64145  $this->handleException($throw);
64146
64147
64148  return false;
64149 }
64150 }
64151 }
64152 }
64153
64154 throw $throw;
64155 }
64156
64157
64158  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
64159 $trace = true;
64160
64161 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
64162 $trace = false;
64163 } else {
64164 $this->loggedTraces[$e] = 1;
64165 }
64166
64167 $e = compact('type', 'file', 'line', 'level');
64168
64169 if ($type & $level) {
64170 if ($scope) {
64171 $e['scope_vars'] = $context;
64172 if ($trace) {
64173 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
64174 }
64175 } elseif ($trace) {
64176 if (null === $backtrace) {
64177 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
64178 } else {
64179 foreach ($backtrace as &$frame) {
64180 unset($frame['args'], $frame);
64181 }
64182 $e['stack'] = $backtrace;
64183 }
64184 }
64185 }
64186
64187 if ($this->isRecursive) {
64188 $log = 0;
64189 } elseif (self::$stackedErrorLevels) {
64190 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
64191 } else {
64192 try {
64193 $this->isRecursive = true;
64194 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
64195 $this->isRecursive = false;
64196 } catch (\Exception $e) {
64197 $this->isRecursive = false;
64198
64199 throw $e;
64200 } catch (\Throwable $e) {
64201 $this->isRecursive = false;
64202
64203 throw $e;
64204 }
64205 }
64206
64207 return !$silenced && $type && $log;
64208 }
64209
64210
64211
64212
64213
64214
64215
64216
64217
64218 public function handleException($exception, array $error = null)
64219 {
64220 if (null === $error) {
64221 self::$exitCode = 255;
64222 }
64223 if (!$exception instanceof \Exception) {
64224 $exception = new FatalThrowableError($exception);
64225 }
64226 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
64227 $handlerException = null;
64228
64229 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
64230 $e = array(
64231 'type' => $type,
64232 'file' => $exception->getFile(),
64233 'line' => $exception->getLine(),
64234 'level' => error_reporting(),
64235 'stack' => $exception->getTrace(),
64236 );
64237 if ($exception instanceof FatalErrorException) {
64238 if ($exception instanceof FatalThrowableError) {
64239 $error = array(
64240 'type' => $type,
64241 'message' => $message = $exception->getMessage(),
64242 'file' => $e['file'],
64243 'line' => $e['line'],
64244 );
64245 } else {
64246 $message = 'Fatal '.$exception->getMessage();
64247 }
64248 } elseif ($exception instanceof \ErrorException) {
64249 $message = 'Uncaught '.$exception->getMessage();
64250 if ($exception instanceof ContextErrorException) {
64251 $e['context'] = $exception->getContext();
64252 }
64253 } else {
64254 $message = 'Uncaught Exception: '.$exception->getMessage();
64255 }
64256 }
64257 if ($this->loggedErrors & $type) {
64258 try {
64259 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
64260 } catch (\Exception $handlerException) {
64261 } catch (\Throwable $handlerException) {
64262 }
64263 }
64264 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
64265 foreach ($this->getFatalErrorHandlers() as $handler) {
64266 if ($e = $handler->handleError($error, $exception)) {
64267 $exception = $e;
64268 break;
64269 }
64270 }
64271 }
64272 $exceptionHandler = $this->exceptionHandler;
64273 $this->exceptionHandler = null;
64274 try {
64275 if (null !== $exceptionHandler) {
64276 return \call_user_func($exceptionHandler, $exception);
64277 }
64278 $handlerException = $handlerException ?: $exception;
64279 } catch (\Exception $handlerException) {
64280 } catch (\Throwable $handlerException) {
64281 }
64282 if ($exception === $handlerException) {
64283 self::$reservedMemory = null; 
64284  throw $exception; 
64285  }
64286 $this->handleException($handlerException);
64287 }
64288
64289
64290
64291
64292
64293
64294
64295
64296 public static function handleFatalError(array $error = null)
64297 {
64298 if (null === self::$reservedMemory) {
64299 return;
64300 }
64301
64302 $handler = self::$reservedMemory = null;
64303 $handlers = array();
64304 $previousHandler = null;
64305 $sameHandlerLimit = 10;
64306
64307 while (!\is_array($handler) || !$handler[0] instanceof self) {
64308 $handler = set_exception_handler('var_dump');
64309 restore_exception_handler();
64310
64311 if (!$handler) {
64312 break;
64313 }
64314 restore_exception_handler();
64315
64316 if ($handler !== $previousHandler) {
64317 array_unshift($handlers, $handler);
64318 $previousHandler = $handler;
64319 } elseif (0 === --$sameHandlerLimit) {
64320 $handler = null;
64321 break;
64322 }
64323 }
64324 foreach ($handlers as $h) {
64325 set_exception_handler($h);
64326 }
64327 if (!$handler) {
64328 return;
64329 }
64330 if ($handler !== $h) {
64331 $handler[0]->setExceptionHandler($h);
64332 }
64333 $handler = $handler[0];
64334 $handlers = array();
64335
64336 if ($exit = null === $error) {
64337 $error = error_get_last();
64338 }
64339
64340 try {
64341 while (self::$stackedErrorLevels) {
64342 static::unstackErrors();
64343 }
64344 } catch (\Exception $exception) {
64345
64346  } catch (\Throwable $exception) {
64347
64348  }
64349
64350 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
64351
64352  $handler->throwAt(0, true);
64353 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
64354
64355 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
64356 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
64357 } else {
64358 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
64359 }
64360 }
64361
64362 try {
64363 if (isset($exception)) {
64364 self::$exitCode = 255;
64365 $handler->handleException($exception, $error);
64366 }
64367 } catch (FatalErrorException $e) {
64368
64369  }
64370
64371 if ($exit && self::$exitCode) {
64372 $exitCode = self::$exitCode;
64373 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
64374 }
64375 }
64376
64377
64378
64379
64380
64381
64382
64383
64384
64385
64386
64387
64388 public static function stackErrors()
64389 {
64390 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
64391 }
64392
64393
64394
64395
64396 public static function unstackErrors()
64397 {
64398 $level = array_pop(self::$stackedErrorLevels);
64399
64400 if (null !== $level) {
64401 $e = error_reporting($level);
64402 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
64403
64404  error_reporting($e);
64405 }
64406 }
64407
64408 if (empty(self::$stackedErrorLevels)) {
64409 $errors = self::$stackedErrors;
64410 self::$stackedErrors = array();
64411
64412 foreach ($errors as $e) {
64413 $e[0]->log($e[1], $e[2], $e[3]);
64414 }
64415 }
64416 }
64417
64418
64419
64420
64421
64422
64423
64424
64425 protected function getFatalErrorHandlers()
64426 {
64427 return array(
64428 new UndefinedFunctionFatalErrorHandler(),
64429 new UndefinedMethodFatalErrorHandler(),
64430 new ClassNotFoundFatalErrorHandler(),
64431 );
64432 }
64433
64434
64435
64436
64437
64438
64439
64440
64441 public function setLevel($level)
64442 {
64443 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
64444
64445 $level = null === $level ? error_reporting() : $level;
64446 $this->throwAt($level, true);
64447 }
64448
64449
64450
64451
64452
64453
64454
64455
64456 public function setDisplayErrors($displayErrors)
64457 {
64458 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
64459
64460 if ($displayErrors) {
64461 $this->throwAt($this->displayErrors, true);
64462 } else {
64463 $displayErrors = $this->displayErrors;
64464 $this->throwAt(0, true);
64465 $this->displayErrors = $displayErrors;
64466 }
64467 }
64468
64469
64470
64471
64472
64473
64474
64475
64476
64477 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
64478 {
64479 @trigger_error('The '.__METHOD__.' static method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the setLoggers() or setDefaultLogger() methods instead.', E_USER_DEPRECATED);
64480
64481 $handler = set_error_handler('var_dump');
64482 $handler = \is_array($handler) ? $handler[0] : null;
64483 restore_error_handler();
64484 if (!$handler instanceof self) {
64485 return;
64486 }
64487 if ('deprecation' === $channel) {
64488 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
64489 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
64490 } elseif ('scream' === $channel) {
64491 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
64492 $handler->screamAt(E_ALL | E_STRICT);
64493 } elseif ('emergency' === $channel) {
64494 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
64495 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
64496 }
64497 }
64498
64499
64500
64501
64502 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
64503 {
64504 $this->handleError(E_USER_DEPRECATED, 'The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the handleError() method instead.', __FILE__, __LINE__, array());
64505
64506 return $this->handleError($level, $message, $file, $line, (array) $context);
64507 }
64508
64509
64510
64511
64512
64513
64514 public function handleFatal()
64515 {
64516 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the handleFatalError() method instead.', E_USER_DEPRECATED);
64517
64518 static::handleFatalError();
64519 }
64520 }
64521
64522
64523
64524
64525
64526
64527
64528
64529 class ErrorHandlerCanary
64530 {
64531 private static $displayErrors = null;
64532
64533 public function __construct()
64534 {
64535 if (null === self::$displayErrors) {
64536 self::$displayErrors = ini_set('display_errors', 1);
64537 }
64538 }
64539
64540 public function __destruct()
64541 {
64542 if (null !== self::$displayErrors) {
64543 ini_set('display_errors', self::$displayErrors);
64544 self::$displayErrors = null;
64545 }
64546 }
64547 }
64548 <?php
64549
64550
64551
64552
64553
64554
64555
64556
64557
64558
64559 namespace Symfony\Component\Debug\Exception;
64560
64561
64562
64563
64564
64565
64566 class ClassNotFoundException extends FatalErrorException
64567 {
64568 public function __construct($message, \ErrorException $previous)
64569 {
64570 parent::__construct(
64571 $message,
64572 $previous->getCode(),
64573 $previous->getSeverity(),
64574 $previous->getFile(),
64575 $previous->getLine(),
64576 null,
64577 true,
64578 null,
64579 $previous->getPrevious()
64580 );
64581 $this->setTrace($previous->getTrace());
64582 }
64583 }
64584 <?php
64585
64586
64587
64588
64589
64590
64591
64592
64593
64594
64595 namespace Symfony\Component\Debug\Exception;
64596
64597
64598
64599
64600
64601
64602 class ContextErrorException extends \ErrorException
64603 {
64604 private $context = array();
64605
64606 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
64607 {
64608 parent::__construct($message, $code, $severity, $filename, $lineno);
64609 $this->context = $context;
64610 }
64611
64612
64613
64614
64615 public function getContext()
64616 {
64617 return $this->context;
64618 }
64619 }
64620 <?php
64621
64622
64623
64624
64625
64626
64627
64628
64629
64630
64631 namespace Symfony\Component\Debug\Exception;
64632
64633 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
64634
64635
64636
64637
64638
64639
64640 class DummyException extends \ErrorException
64641 {
64642 }
64643 <?php
64644
64645
64646
64647
64648
64649
64650
64651
64652
64653
64654 namespace Symfony\Component\HttpKernel\Exception;
64655
64656
64657
64658
64659
64660
64661
64662
64663
64664
64665 class FatalErrorException extends \ErrorException
64666 {
64667 }
64668
64669 namespace Symfony\Component\Debug\Exception;
64670
64671 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
64672
64673
64674
64675
64676
64677
64678 class FatalErrorException extends LegacyFatalErrorException
64679 {
64680 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null, $previous = null)
64681 {
64682 parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
64683
64684 if (null !== $trace) {
64685 if (!$traceArgs) {
64686 foreach ($trace as &$frame) {
64687 unset($frame['args'], $frame['this'], $frame);
64688 }
64689 }
64690
64691 $this->setTrace($trace);
64692 } elseif (null !== $traceOffset) {
64693 if (\function_exists('xdebug_get_function_stack')) {
64694 $trace = xdebug_get_function_stack();
64695 if (0 < $traceOffset) {
64696 array_splice($trace, -$traceOffset);
64697 }
64698
64699 foreach ($trace as &$frame) {
64700 if (!isset($frame['type'])) {
64701
64702  if (isset($frame['class'])) {
64703 $frame['type'] = '::';
64704 }
64705 } elseif ('dynamic' === $frame['type']) {
64706 $frame['type'] = '->';
64707 } elseif ('static' === $frame['type']) {
64708 $frame['type'] = '::';
64709 }
64710
64711
64712  if (!$traceArgs) {
64713 unset($frame['params'], $frame['args']);
64714 } elseif (isset($frame['params']) && !isset($frame['args'])) {
64715 $frame['args'] = $frame['params'];
64716 unset($frame['params']);
64717 }
64718 }
64719
64720 unset($frame);
64721 $trace = array_reverse($trace);
64722 } elseif (\function_exists('symfony_debug_backtrace')) {
64723 $trace = symfony_debug_backtrace();
64724 if (0 < $traceOffset) {
64725 array_splice($trace, 0, $traceOffset);
64726 }
64727 } else {
64728 $trace = array();
64729 }
64730
64731 $this->setTrace($trace);
64732 }
64733 }
64734
64735 protected function setTrace($trace)
64736 {
64737 $traceReflector = new \ReflectionProperty('Exception', 'trace');
64738 $traceReflector->setAccessible(true);
64739 $traceReflector->setValue($this, $trace);
64740 }
64741 }
64742 <?php
64743
64744
64745
64746
64747
64748
64749
64750
64751
64752
64753 namespace Symfony\Component\Debug\Exception;
64754
64755
64756
64757
64758
64759
64760 class FatalThrowableError extends FatalErrorException
64761 {
64762 public function __construct(\Throwable $e)
64763 {
64764 if ($e instanceof \ParseError) {
64765 $message = 'Parse error: '.$e->getMessage();
64766 $severity = E_PARSE;
64767 } elseif ($e instanceof \TypeError) {
64768 $message = 'Type error: '.$e->getMessage();
64769 $severity = E_RECOVERABLE_ERROR;
64770 } else {
64771 $message = $e->getMessage();
64772 $severity = E_ERROR;
64773 }
64774
64775 \ErrorException::__construct(
64776 $message,
64777 $e->getCode(),
64778 $severity,
64779 $e->getFile(),
64780 $e->getLine(),
64781 $e->getPrevious()
64782 );
64783
64784 $this->setTrace($e->getTrace());
64785 }
64786 }
64787 <?php
64788
64789
64790
64791
64792
64793
64794
64795
64796
64797
64798 namespace Symfony\Component\HttpKernel\Exception;
64799
64800 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
64801
64802
64803
64804
64805
64806
64807
64808
64809
64810
64811 class FlattenException
64812 {
64813 private $handler;
64814
64815 public static function __callStatic($method, $args)
64816 {
64817 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
64818 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_called_class(), $method));
64819 }
64820
64821 return \call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
64822 }
64823
64824 public function __call($method, $args)
64825 {
64826 if (!isset($this->handler)) {
64827 $this->handler = new DebugFlattenException();
64828 }
64829
64830 if (!method_exists($this->handler, $method)) {
64831 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_class($this), $method));
64832 }
64833
64834 return \call_user_func_array(array($this->handler, $method), $args);
64835 }
64836 }
64837
64838 namespace Symfony\Component\Debug\Exception;
64839
64840 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
64841 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
64842
64843
64844
64845
64846
64847
64848
64849
64850 class FlattenException extends LegacyFlattenException
64851 {
64852 private $message;
64853 private $code;
64854 private $previous;
64855 private $trace;
64856 private $class;
64857 private $statusCode;
64858 private $headers;
64859 private $file;
64860 private $line;
64861
64862 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
64863 {
64864 $e = new static();
64865 $e->setMessage($exception->getMessage());
64866 $e->setCode($exception->getCode());
64867
64868 if ($exception instanceof HttpExceptionInterface) {
64869 $statusCode = $exception->getStatusCode();
64870 $headers = array_merge($headers, $exception->getHeaders());
64871 }
64872
64873 if (null === $statusCode) {
64874 $statusCode = 500;
64875 }
64876
64877 $e->setStatusCode($statusCode);
64878 $e->setHeaders($headers);
64879 $e->setTraceFromException($exception);
64880 $e->setClass(\get_class($exception));
64881 $e->setFile($exception->getFile());
64882 $e->setLine($exception->getLine());
64883
64884 $previous = $exception->getPrevious();
64885
64886 if ($previous instanceof \Exception) {
64887 $e->setPrevious(static::create($previous));
64888 } elseif ($previous instanceof \Throwable) {
64889 $e->setPrevious(static::create(new FatalThrowableError($previous)));
64890 }
64891
64892 return $e;
64893 }
64894
64895 public function toArray()
64896 {
64897 $exceptions = array();
64898 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
64899 $exceptions[] = array(
64900 'message' => $exception->getMessage(),
64901 'class' => $exception->getClass(),
64902 'trace' => $exception->getTrace(),
64903 );
64904 }
64905
64906 return $exceptions;
64907 }
64908
64909 public function getStatusCode()
64910 {
64911 return $this->statusCode;
64912 }
64913
64914 public function setStatusCode($code)
64915 {
64916 $this->statusCode = $code;
64917 }
64918
64919 public function getHeaders()
64920 {
64921 return $this->headers;
64922 }
64923
64924 public function setHeaders(array $headers)
64925 {
64926 $this->headers = $headers;
64927 }
64928
64929 public function getClass()
64930 {
64931 return $this->class;
64932 }
64933
64934 public function setClass($class)
64935 {
64936 $this->class = $class;
64937 }
64938
64939 public function getFile()
64940 {
64941 return $this->file;
64942 }
64943
64944 public function setFile($file)
64945 {
64946 $this->file = $file;
64947 }
64948
64949 public function getLine()
64950 {
64951 return $this->line;
64952 }
64953
64954 public function setLine($line)
64955 {
64956 $this->line = $line;
64957 }
64958
64959 public function getMessage()
64960 {
64961 return $this->message;
64962 }
64963
64964 public function setMessage($message)
64965 {
64966 $this->message = $message;
64967 }
64968
64969 public function getCode()
64970 {
64971 return $this->code;
64972 }
64973
64974 public function setCode($code)
64975 {
64976 $this->code = $code;
64977 }
64978
64979 public function getPrevious()
64980 {
64981 return $this->previous;
64982 }
64983
64984 public function setPrevious(FlattenException $previous)
64985 {
64986 $this->previous = $previous;
64987 }
64988
64989 public function getAllPrevious()
64990 {
64991 $exceptions = array();
64992 $e = $this;
64993 while ($e = $e->getPrevious()) {
64994 $exceptions[] = $e;
64995 }
64996
64997 return $exceptions;
64998 }
64999
65000 public function getTrace()
65001 {
65002 return $this->trace;
65003 }
65004
65005 public function setTraceFromException(\Exception $exception)
65006 {
65007 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
65008 }
65009
65010 public function setTrace($trace, $file, $line)
65011 {
65012 $this->trace = array();
65013 $this->trace[] = array(
65014 'namespace' => '',
65015 'short_class' => '',
65016 'class' => '',
65017 'type' => '',
65018 'function' => '',
65019 'file' => $file,
65020 'line' => $line,
65021 'args' => array(),
65022 );
65023 foreach ($trace as $entry) {
65024 $class = '';
65025 $namespace = '';
65026 if (isset($entry['class'])) {
65027 $parts = explode('\\', $entry['class']);
65028 $class = array_pop($parts);
65029 $namespace = implode('\\', $parts);
65030 }
65031
65032 $this->trace[] = array(
65033 'namespace' => $namespace,
65034 'short_class' => $class,
65035 'class' => isset($entry['class']) ? $entry['class'] : '',
65036 'type' => isset($entry['type']) ? $entry['type'] : '',
65037 'function' => isset($entry['function']) ? $entry['function'] : null,
65038 'file' => isset($entry['file']) ? $entry['file'] : null,
65039 'line' => isset($entry['line']) ? $entry['line'] : null,
65040 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
65041 );
65042 }
65043 }
65044
65045 private function flattenArgs($args, $level = 0, &$count = 0)
65046 {
65047 $result = array();
65048 foreach ($args as $key => $value) {
65049 if (++$count > 1e4) {
65050 return array('array', '*SKIPPED over 10000 entries*');
65051 }
65052 if ($value instanceof \__PHP_Incomplete_Class) {
65053
65054  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
65055 } elseif (\is_object($value)) {
65056 $result[$key] = array('object', \get_class($value));
65057 } elseif (\is_array($value)) {
65058 if ($level > 10) {
65059 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
65060 } else {
65061 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
65062 }
65063 } elseif (null === $value) {
65064 $result[$key] = array('null', null);
65065 } elseif (\is_bool($value)) {
65066 $result[$key] = array('boolean', $value);
65067 } elseif (\is_resource($value)) {
65068 $result[$key] = array('resource', get_resource_type($value));
65069 } else {
65070 $result[$key] = array('string', (string) $value);
65071 }
65072 }
65073
65074 return $result;
65075 }
65076
65077 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
65078 {
65079 $array = new \ArrayObject($value);
65080
65081 return $array['__PHP_Incomplete_Class_Name'];
65082 }
65083 }
65084 <?php
65085
65086
65087
65088
65089
65090
65091
65092
65093
65094
65095 namespace Symfony\Component\Debug\Exception;
65096
65097
65098
65099
65100
65101
65102 class OutOfMemoryException extends FatalErrorException
65103 {
65104 }
65105 <?php
65106
65107
65108
65109
65110
65111
65112
65113
65114
65115
65116 namespace Symfony\Component\Debug\Exception;
65117
65118
65119
65120
65121
65122
65123 class UndefinedFunctionException extends FatalErrorException
65124 {
65125 public function __construct($message, \ErrorException $previous)
65126 {
65127 parent::__construct(
65128 $message,
65129 $previous->getCode(),
65130 $previous->getSeverity(),
65131 $previous->getFile(),
65132 $previous->getLine(),
65133 null,
65134 true,
65135 null,
65136 $previous->getPrevious()
65137 );
65138 $this->setTrace($previous->getTrace());
65139 }
65140 }
65141 <?php
65142
65143
65144
65145
65146
65147
65148
65149
65150
65151
65152 namespace Symfony\Component\Debug\Exception;
65153
65154
65155
65156
65157
65158
65159 class UndefinedMethodException extends FatalErrorException
65160 {
65161 public function __construct($message, \ErrorException $previous)
65162 {
65163 parent::__construct(
65164 $message,
65165 $previous->getCode(),
65166 $previous->getSeverity(),
65167 $previous->getFile(),
65168 $previous->getLine(),
65169 null,
65170 true,
65171 null,
65172 $previous->getPrevious()
65173 );
65174 $this->setTrace($previous->getTrace());
65175 }
65176 }
65177 <?php
65178
65179
65180
65181
65182
65183
65184
65185
65186
65187
65188 namespace Symfony\Component\Debug;
65189
65190 use Symfony\Component\Debug\Exception\FlattenException;
65191 use Symfony\Component\Debug\Exception\OutOfMemoryException;
65192 use Symfony\Component\HttpFoundation\Response;
65193
65194
65195
65196
65197
65198
65199
65200
65201
65202
65203
65204
65205
65206 class ExceptionHandler
65207 {
65208 private $debug;
65209 private $charset;
65210 private $handler;
65211 private $caughtBuffer;
65212 private $caughtLength;
65213 private $fileLinkFormat;
65214
65215 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
65216 {
65217 if (false !== strpos($charset, '%')) {
65218 @trigger_error('Providing $fileLinkFormat as second argument to '.__METHOD__.' is deprecated since Symfony 2.8 and will be unsupported in 3.0. Please provide it as third argument, after $charset.', E_USER_DEPRECATED);
65219
65220
65221  $pivot = $fileLinkFormat;
65222 $fileLinkFormat = $charset;
65223 $charset = $pivot;
65224 }
65225 $this->debug = $debug;
65226 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
65227 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
65228 }
65229
65230
65231
65232
65233
65234
65235
65236
65237
65238
65239 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
65240 {
65241 $handler = new static($debug, $charset, $fileLinkFormat);
65242
65243 $prev = set_exception_handler(array($handler, 'handle'));
65244 if (\is_array($prev) && $prev[0] instanceof ErrorHandler) {
65245 restore_exception_handler();
65246 $prev[0]->setExceptionHandler(array($handler, 'handle'));
65247 }
65248
65249 return $handler;
65250 }
65251
65252
65253
65254
65255
65256
65257
65258
65259 public function setHandler($handler)
65260 {
65261 if (null !== $handler && !\is_callable($handler)) {
65262 throw new \LogicException('The exception handler must be a valid PHP callable.');
65263 }
65264 $old = $this->handler;
65265 $this->handler = $handler;
65266
65267 return $old;
65268 }
65269
65270
65271
65272
65273
65274
65275
65276
65277 public function setFileLinkFormat($format)
65278 {
65279 $old = $this->fileLinkFormat;
65280 $this->fileLinkFormat = $format;
65281
65282 return $old;
65283 }
65284
65285
65286
65287
65288
65289
65290
65291
65292
65293 public function handle(\Exception $exception)
65294 {
65295 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
65296 $this->failSafeHandle($exception);
65297
65298 return;
65299 }
65300
65301 $caughtLength = $this->caughtLength = 0;
65302
65303 ob_start(array($this, 'catchOutput'));
65304 $this->failSafeHandle($exception);
65305 while (null === $this->caughtBuffer && ob_end_flush()) {
65306
65307  }
65308 if (isset($this->caughtBuffer[0])) {
65309 ob_start(array($this, 'cleanOutput'));
65310 echo $this->caughtBuffer;
65311 $caughtLength = ob_get_length();
65312 }
65313 $this->caughtBuffer = null;
65314
65315 try {
65316 \call_user_func($this->handler, $exception);
65317 $this->caughtLength = $caughtLength;
65318 } catch (\Exception $e) {
65319 if (!$caughtLength) {
65320
65321  throw $exception;
65322 }
65323 }
65324 }
65325
65326
65327
65328
65329
65330
65331
65332
65333 private function failSafeHandle(\Exception $exception)
65334 {
65335 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
65336 && __CLASS__ !== \get_class($this)
65337 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
65338 && __CLASS__ !== $reflector->class
65339 ) {
65340 $response = $this->createResponse($exception);
65341 $response->sendHeaders();
65342 $response->sendContent();
65343 @trigger_error(sprintf("The %s::createResponse method is deprecated since Symfony 2.8 and won't be called anymore when handling an exception in 3.0.", $reflector->class), E_USER_DEPRECATED);
65344
65345 return;
65346 }
65347
65348 $this->sendPhpResponse($exception);
65349 }
65350
65351
65352
65353
65354
65355
65356
65357
65358
65359 public function sendPhpResponse($exception)
65360 {
65361 if (!$exception instanceof FlattenException) {
65362 $exception = FlattenException::create($exception);
65363 }
65364
65365 if (!headers_sent()) {
65366 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
65367 foreach ($exception->getHeaders() as $name => $value) {
65368 header($name.': '.$value, false);
65369 }
65370 header('Content-Type: text/html; charset='.$this->charset);
65371 }
65372
65373 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
65374 }
65375
65376
65377
65378
65379
65380
65381
65382
65383
65384
65385 public function createResponse($exception)
65386 {
65387 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65388
65389 if (!$exception instanceof FlattenException) {
65390 $exception = FlattenException::create($exception);
65391 }
65392
65393 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
65394 }
65395
65396
65397
65398
65399
65400
65401
65402
65403 public function getHtml($exception)
65404 {
65405 if (!$exception instanceof FlattenException) {
65406 $exception = FlattenException::create($exception);
65407 }
65408
65409 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
65410 }
65411
65412
65413
65414
65415
65416
65417 public function getContent(FlattenException $exception)
65418 {
65419 switch ($exception->getStatusCode()) {
65420 case 404:
65421 $title = 'Sorry, the page you are looking for could not be found.';
65422 break;
65423 default:
65424 $title = 'Whoops, looks like something went wrong.';
65425 }
65426
65427 $content = '';
65428 if ($this->debug) {
65429 try {
65430 $count = \count($exception->getAllPrevious());
65431 $total = $count + 1;
65432 foreach ($exception->toArray() as $position => $e) {
65433 $ind = $count - $position + 1;
65434 $class = $this->formatClass($e['class']);
65435 $message = nl2br($this->escapeHtml($e['message']));
65436 $content .= sprintf(<<<'EOF'
65437                         <h2 class="block_exception clear_fix">
65438                             <span class="exception_counter">%d/%d</span>
65439                             <span class="exception_title">%s%s:</span>
65440                             <span class="exception_message">%s</span>
65441                         </h2>
65442                         <div class="block">
65443                             <ol class="traces list_exception">
65444
65445 EOF
65446 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
65447 foreach ($e['trace'] as $trace) {
65448 $content .= '       <li>';
65449 if ($trace['function']) {
65450 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
65451 }
65452 if (isset($trace['file']) && isset($trace['line'])) {
65453 $content .= $this->formatPath($trace['file'], $trace['line']);
65454 }
65455 $content .= "</li>\n";
65456 }
65457
65458 $content .= "    </ol>\n</div>\n";
65459 }
65460 } catch (\Exception $e) {
65461
65462  if ($this->debug) {
65463 $title = sprintf('Exception thrown when handling an exception (%s: %s)', \get_class($e), $this->escapeHtml($e->getMessage()));
65464 } else {
65465 $title = 'Whoops, looks like something went wrong.';
65466 }
65467 }
65468 }
65469
65470 return <<<EOF
65471             <div id="sf-resetcontent" class="sf-reset">
65472                 <h1>$title</h1>
65473                 $content
65474             </div>
65475 EOF;
65476 }
65477
65478
65479
65480
65481
65482
65483 public function getStylesheet(FlattenException $exception)
65484 {
65485 return <<<'EOF'
65486             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
65487             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
65488             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
65489             .sf-reset .clear_fix { display:inline-block; }
65490             .sf-reset * html .clear_fix { height:1%; }
65491             .sf-reset .clear_fix { display:block; }
65492             .sf-reset, .sf-reset .block { margin: auto }
65493             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
65494             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
65495             .sf-reset strong { font-weight:bold; }
65496             .sf-reset a { color:#6c6159; cursor: default; }
65497             .sf-reset a img { border:none; }
65498             .sf-reset a:hover { text-decoration:underline; }
65499             .sf-reset em { font-style:italic; }
65500             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
65501             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
65502             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
65503             .sf-reset .exception_message { margin-left: 3em; display: block; }
65504             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
65505             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
65506                 -webkit-border-bottom-right-radius: 16px;
65507                 -webkit-border-bottom-left-radius: 16px;
65508                 -moz-border-radius-bottomright: 16px;
65509                 -moz-border-radius-bottomleft: 16px;
65510                 border-bottom-right-radius: 16px;
65511                 border-bottom-left-radius: 16px;
65512                 border-bottom:1px solid #ccc;
65513                 border-right:1px solid #ccc;
65514                 border-left:1px solid #ccc;
65515                 word-wrap: break-word;
65516             }
65517             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
65518                 -webkit-border-top-left-radius: 16px;
65519                 -webkit-border-top-right-radius: 16px;
65520                 -moz-border-radius-topleft: 16px;
65521                 -moz-border-radius-topright: 16px;
65522                 border-top-left-radius: 16px;
65523                 border-top-right-radius: 16px;
65524                 border-top:1px solid #ccc;
65525                 border-right:1px solid #ccc;
65526                 border-left:1px solid #ccc;
65527                 overflow: hidden;
65528                 word-wrap: break-word;
65529             }
65530             .sf-reset a { background:none; color:#868686; text-decoration:none; }
65531             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
65532             .sf-reset ol { padding: 10px 0; }
65533             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
65534                 -webkit-border-radius: 10px;
65535                 -moz-border-radius: 10px;
65536                 border-radius: 10px;
65537                 border: 1px solid #ccc;
65538             }
65539 EOF;
65540 }
65541
65542 private function decorate($content, $css)
65543 {
65544 return <<<EOF
65545 <!DOCTYPE html>
65546 <html>
65547     <head>
65548         <meta charset="{$this->charset}" />
65549         <meta name="robots" content="noindex,nofollow" />
65550         <style>
65551             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
65552             html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
65553
65554             html { background: #eee; padding: 10px }
65555             img { border: 0; }
65556             #sf-resetcontent { width:970px; margin:0 auto; }
65557             $css
65558         </style>
65559     </head>
65560     <body>
65561         $content
65562     </body>
65563 </html>
65564 EOF;
65565 }
65566
65567 private function formatClass($class)
65568 {
65569 $parts = explode('\\', $class);
65570
65571 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
65572 }
65573
65574 private function formatPath($path, $line)
65575 {
65576 $path = $this->escapeHtml($path);
65577 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
65578
65579 if ($linkFormat = $this->fileLinkFormat) {
65580 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
65581
65582 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
65583 }
65584
65585 return sprintf(' in <a title="%s line %3$d" ondblclick="var f=this.innerHTML;this.innerHTML=this.title;this.title=f;">%s line %d</a>', $path, $file, $line);
65586 }
65587
65588
65589
65590
65591
65592
65593
65594
65595 private function formatArgs(array $args)
65596 {
65597 $result = array();
65598 foreach ($args as $key => $item) {
65599 if ('object' === $item[0]) {
65600 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
65601 } elseif ('array' === $item[0]) {
65602 $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
65603 } elseif ('string' === $item[0]) {
65604 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
65605 } elseif ('null' === $item[0]) {
65606 $formattedValue = '<em>null</em>';
65607 } elseif ('boolean' === $item[0]) {
65608 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
65609 } elseif ('resource' === $item[0]) {
65610 $formattedValue = '<em>resource</em>';
65611 } else {
65612 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
65613 }
65614
65615 $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
65616 }
65617
65618 return implode(', ', $result);
65619 }
65620
65621
65622
65623
65624
65625
65626 protected static function utf8Htmlize($str)
65627 {
65628 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
65629
65630 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
65631 }
65632
65633
65634
65635
65636 private function escapeHtml($str)
65637 {
65638 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
65639 }
65640
65641
65642
65643
65644 public function catchOutput($buffer)
65645 {
65646 $this->caughtBuffer = $buffer;
65647
65648 return '';
65649 }
65650
65651
65652
65653
65654 public function cleanOutput($buffer)
65655 {
65656 if ($this->caughtLength) {
65657
65658  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
65659 if (isset($cleanBuffer[0])) {
65660 $buffer = $cleanBuffer;
65661 }
65662 }
65663
65664 return $buffer;
65665 }
65666 }
65667 <?php
65668
65669
65670
65671
65672
65673
65674
65675
65676
65677
65678 namespace Symfony\Component\Debug\FatalErrorHandler;
65679
65680 use Composer\Autoload\ClassLoader as ComposerClassLoader;
65681 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
65682 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
65683 use Symfony\Component\Debug\DebugClassLoader;
65684 use Symfony\Component\Debug\Exception\ClassNotFoundException;
65685 use Symfony\Component\Debug\Exception\FatalErrorException;
65686
65687
65688
65689
65690
65691
65692 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
65693 {
65694
65695
65696
65697 public function handleError(array $error, FatalErrorException $exception)
65698 {
65699 $messageLen = \strlen($error['message']);
65700 $notFoundSuffix = '\' not found';
65701 $notFoundSuffixLen = \strlen($notFoundSuffix);
65702 if ($notFoundSuffixLen > $messageLen) {
65703 return;
65704 }
65705
65706 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
65707 return;
65708 }
65709
65710 foreach (array('class', 'interface', 'trait') as $typeName) {
65711 $prefix = ucfirst($typeName).' \'';
65712 $prefixLen = \strlen($prefix);
65713 if (0 !== strpos($error['message'], $prefix)) {
65714 continue;
65715 }
65716
65717 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
65718 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
65719 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
65720 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
65721 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
65722 $tail = ' for another namespace?';
65723 } else {
65724 $className = $fullyQualifiedClassName;
65725 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
65726 $tail = '?';
65727 }
65728
65729 if ($candidates = $this->getClassCandidates($className)) {
65730 $tail = array_pop($candidates).'"?';
65731 if ($candidates) {
65732 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
65733 } else {
65734 $tail = ' for "'.$tail;
65735 }
65736 }
65737 $message .= "\nDid you forget a \"use\" statement".$tail;
65738
65739 return new ClassNotFoundException($message, $exception);
65740 }
65741 }
65742
65743
65744
65745
65746
65747
65748
65749
65750
65751
65752
65753 private function getClassCandidates($class)
65754 {
65755 if (!\is_array($functions = spl_autoload_functions())) {
65756 return array();
65757 }
65758
65759
65760  $classes = array();
65761
65762 foreach ($functions as $function) {
65763 if (!\is_array($function)) {
65764 continue;
65765 }
65766
65767  if ($function[0] instanceof DebugClassLoader) {
65768 $function = $function[0]->getClassLoader();
65769
65770
65771  if (\is_object($function)) {
65772 $function = array($function);
65773 }
65774
65775 if (!\is_array($function)) {
65776 continue;
65777 }
65778 }
65779
65780 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
65781 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
65782 foreach ($paths as $path) {
65783 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
65784 }
65785 }
65786 }
65787 if ($function[0] instanceof ComposerClassLoader) {
65788 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
65789 foreach ($paths as $path) {
65790 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
65791 }
65792 }
65793 }
65794 }
65795
65796 return array_unique($classes);
65797 }
65798
65799
65800
65801
65802
65803
65804
65805
65806 private function findClassInPath($path, $class, $prefix)
65807 {
65808 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
65809 return array();
65810 }
65811
65812 $classes = array();
65813 $filename = $class.'.php';
65814 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
65815 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
65816 $classes[] = $class;
65817 }
65818 }
65819
65820 return $classes;
65821 }
65822
65823
65824
65825
65826
65827
65828
65829
65830 private function convertFileToClass($path, $file, $prefix)
65831 {
65832 $candidates = array(
65833
65834  $namespacedClass = str_replace(array($path.\DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
65835
65836  $prefix.$namespacedClass,
65837
65838  $prefix.'\\'.$namespacedClass,
65839
65840  str_replace('\\', '_', $namespacedClass),
65841
65842  str_replace('\\', '_', $prefix.$namespacedClass),
65843
65844  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
65845 );
65846
65847 if ($prefix) {
65848 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
65849 }
65850
65851
65852  
65853  
65854  foreach ($candidates as $candidate) {
65855 if ($this->classExists($candidate)) {
65856 return $candidate;
65857 }
65858 }
65859
65860 require_once $file;
65861
65862 foreach ($candidates as $candidate) {
65863 if ($this->classExists($candidate)) {
65864 return $candidate;
65865 }
65866 }
65867 }
65868
65869
65870
65871
65872
65873
65874 private function classExists($class)
65875 {
65876 return class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
65877 }
65878 }
65879 <?php
65880
65881
65882
65883
65884
65885
65886
65887
65888
65889
65890 namespace Symfony\Component\Debug\FatalErrorHandler;
65891
65892 use Symfony\Component\Debug\Exception\FatalErrorException;
65893
65894
65895
65896
65897
65898
65899 interface FatalErrorHandlerInterface
65900 {
65901
65902
65903
65904
65905
65906
65907
65908
65909 public function handleError(array $error, FatalErrorException $exception);
65910 }
65911 <?php
65912
65913
65914
65915
65916
65917
65918
65919
65920
65921
65922 namespace Symfony\Component\Debug\FatalErrorHandler;
65923
65924 use Symfony\Component\Debug\Exception\FatalErrorException;
65925 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
65926
65927
65928
65929
65930
65931
65932 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
65933 {
65934
65935
65936
65937 public function handleError(array $error, FatalErrorException $exception)
65938 {
65939 $messageLen = \strlen($error['message']);
65940 $notFoundSuffix = '()';
65941 $notFoundSuffixLen = \strlen($notFoundSuffix);
65942 if ($notFoundSuffixLen > $messageLen) {
65943 return;
65944 }
65945
65946 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
65947 return;
65948 }
65949
65950 $prefix = 'Call to undefined function ';
65951 $prefixLen = \strlen($prefix);
65952 if (0 !== strpos($error['message'], $prefix)) {
65953 return;
65954 }
65955
65956 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
65957 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
65958 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
65959 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
65960 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
65961 } else {
65962 $functionName = $fullyQualifiedFunctionName;
65963 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
65964 }
65965
65966 $candidates = array();
65967 foreach (get_defined_functions() as $type => $definedFunctionNames) {
65968 foreach ($definedFunctionNames as $definedFunctionName) {
65969 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
65970 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
65971 } else {
65972 $definedFunctionNameBasename = $definedFunctionName;
65973 }
65974
65975 if ($definedFunctionNameBasename === $functionName) {
65976 $candidates[] = '\\'.$definedFunctionName;
65977 }
65978 }
65979 }
65980
65981 if ($candidates) {
65982 sort($candidates);
65983 $last = array_pop($candidates).'"?';
65984 if ($candidates) {
65985 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
65986 } else {
65987 $candidates = '"'.$last;
65988 }
65989 $message .= "\nDid you mean to call ".$candidates;
65990 }
65991
65992 return new UndefinedFunctionException($message, $exception);
65993 }
65994 }
65995 <?php
65996
65997
65998
65999
66000
66001
66002
66003
66004
66005
66006 namespace Symfony\Component\Debug\FatalErrorHandler;
66007
66008 use Symfony\Component\Debug\Exception\FatalErrorException;
66009 use Symfony\Component\Debug\Exception\UndefinedMethodException;
66010
66011
66012
66013
66014
66015
66016 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
66017 {
66018
66019
66020
66021 public function handleError(array $error, FatalErrorException $exception)
66022 {
66023 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
66024 if (!$matches) {
66025 return;
66026 }
66027
66028 $className = $matches[1];
66029 $methodName = $matches[2];
66030
66031 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
66032
66033 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
66034
66035  return new UndefinedMethodException($message, $exception);
66036 }
66037
66038 $candidates = array();
66039 foreach ($methods as $definedMethodName) {
66040 $lev = levenshtein($methodName, $definedMethodName);
66041 if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
66042 $candidates[] = $definedMethodName;
66043 }
66044 }
66045
66046 if ($candidates) {
66047 sort($candidates);
66048 $last = array_pop($candidates).'"?';
66049 if ($candidates) {
66050 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
66051 } else {
66052 $candidates = '"'.$last;
66053 }
66054
66055 $message .= "\nDid you mean to call ".$candidates;
66056 }
66057
66058 return new UndefinedMethodException($message, $exception);
66059 }
66060 }
66061 Copyright (c) 2004-2018 Fabien Potencier
66062
66063 Permission is hereby granted, free of charge, to any person obtaining a copy
66064 of this software and associated documentation files (the "Software"), to deal
66065 in the Software without restriction, including without limitation the rights
66066 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66067 copies of the Software, and to permit persons to whom the Software is furnished
66068 to do so, subject to the following conditions:
66069
66070 The above copyright notice and this permission notice shall be included in all
66071 copies or substantial portions of the Software.
66072
66073 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
66074 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
66075 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66076 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66077 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
66078 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
66079 THE SOFTWARE.
66080 <?php
66081
66082
66083
66084
66085
66086
66087
66088
66089
66090
66091 namespace Symfony\Component\Filesystem\Exception;
66092
66093
66094
66095
66096
66097
66098 interface ExceptionInterface
66099 {
66100 }
66101 <?php
66102
66103
66104
66105
66106
66107
66108
66109
66110
66111
66112 namespace Symfony\Component\Filesystem\Exception;
66113
66114
66115
66116
66117
66118
66119
66120 class FileNotFoundException extends IOException
66121 {
66122 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
66123 {
66124 if (null === $message) {
66125 if (null === $path) {
66126 $message = 'File could not be found.';
66127 } else {
66128 $message = sprintf('File "%s" could not be found.', $path);
66129 }
66130 }
66131
66132 parent::__construct($message, $code, $previous, $path);
66133 }
66134 }
66135 <?php
66136
66137
66138
66139
66140
66141
66142
66143
66144
66145
66146 namespace Symfony\Component\Filesystem\Exception;
66147
66148
66149
66150
66151
66152
66153
66154
66155 class IOException extends \RuntimeException implements IOExceptionInterface
66156 {
66157 private $path;
66158
66159 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
66160 {
66161 $this->path = $path;
66162
66163 parent::__construct($message, $code, $previous);
66164 }
66165
66166
66167
66168
66169 public function getPath()
66170 {
66171 return $this->path;
66172 }
66173 }
66174 <?php
66175
66176
66177
66178
66179
66180
66181
66182
66183
66184
66185 namespace Symfony\Component\Filesystem\Exception;
66186
66187
66188
66189
66190
66191
66192 interface IOExceptionInterface extends ExceptionInterface
66193 {
66194
66195
66196
66197
66198
66199 public function getPath();
66200 }
66201 <?php
66202
66203
66204
66205
66206
66207
66208
66209
66210
66211
66212 namespace Symfony\Component\Filesystem;
66213
66214 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
66215 use Symfony\Component\Filesystem\Exception\IOException;
66216
66217
66218
66219
66220
66221
66222 class Filesystem
66223 {
66224 private static $lastError;
66225
66226
66227
66228
66229
66230
66231
66232
66233
66234
66235
66236
66237
66238
66239
66240 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
66241 {
66242 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
66243 if ($originIsLocal && !is_file($originFile)) {
66244 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
66245 }
66246
66247 $this->mkdir(\dirname($targetFile));
66248
66249 $doCopy = true;
66250 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
66251 $doCopy = filemtime($originFile) > filemtime($targetFile);
66252 }
66253
66254 if ($doCopy) {
66255
66256  if (false === $source = @fopen($originFile, 'r')) {
66257 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
66258 }
66259
66260
66261  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
66262 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
66263 }
66264
66265 $bytesCopied = stream_copy_to_stream($source, $target);
66266 fclose($source);
66267 fclose($target);
66268 unset($source, $target);
66269
66270 if (!is_file($targetFile)) {
66271 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
66272 }
66273
66274 if ($originIsLocal) {
66275
66276  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
66277
66278 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
66279 throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile);
66280 }
66281 }
66282 }
66283 }
66284
66285
66286
66287
66288
66289
66290
66291
66292
66293 public function mkdir($dirs, $mode = 0777)
66294 {
66295 foreach ($this->toIterator($dirs) as $dir) {
66296 if (is_dir($dir)) {
66297 continue;
66298 }
66299
66300 if (!self::box('mkdir', $dir, $mode, true)) {
66301 if (!is_dir($dir)) {
66302
66303  if (self::$lastError) {
66304 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
66305 }
66306 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
66307 }
66308 }
66309 }
66310 }
66311
66312
66313
66314
66315
66316
66317
66318
66319 public function exists($files)
66320 {
66321 $maxPathLength = PHP_MAXPATHLEN - 2;
66322
66323 foreach ($this->toIterator($files) as $file) {
66324 if (\strlen($file) > $maxPathLength) {
66325 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
66326 }
66327
66328 if (!file_exists($file)) {
66329 return false;
66330 }
66331 }
66332
66333 return true;
66334 }
66335
66336
66337
66338
66339
66340
66341
66342
66343
66344
66345 public function touch($files, $time = null, $atime = null)
66346 {
66347 foreach ($this->toIterator($files) as $file) {
66348 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
66349 if (true !== $touch) {
66350 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
66351 }
66352 }
66353 }
66354
66355
66356
66357
66358
66359
66360
66361
66362 public function remove($files)
66363 {
66364 if ($files instanceof \Traversable) {
66365 $files = iterator_to_array($files, false);
66366 } elseif (!\is_array($files)) {
66367 $files = array($files);
66368 }
66369 $files = array_reverse($files);
66370 foreach ($files as $file) {
66371 if (is_link($file)) {
66372
66373  if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
66374 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
66375 }
66376 } elseif (is_dir($file)) {
66377 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
66378
66379 if (!self::box('rmdir', $file) && file_exists($file)) {
66380 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
66381 }
66382 } elseif (!self::box('unlink', $file) && file_exists($file)) {
66383 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
66384 }
66385 }
66386 }
66387
66388
66389
66390
66391
66392
66393
66394
66395
66396
66397
66398 public function chmod($files, $mode, $umask = 0000, $recursive = false)
66399 {
66400 foreach ($this->toIterator($files) as $file) {
66401 if (true !== @chmod($file, $mode & ~$umask)) {
66402 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
66403 }
66404 if ($recursive && is_dir($file) && !is_link($file)) {
66405 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
66406 }
66407 }
66408 }
66409
66410
66411
66412
66413
66414
66415
66416
66417
66418
66419 public function chown($files, $user, $recursive = false)
66420 {
66421 foreach ($this->toIterator($files) as $file) {
66422 if ($recursive && is_dir($file) && !is_link($file)) {
66423 $this->chown(new \FilesystemIterator($file), $user, true);
66424 }
66425 if (is_link($file) && \function_exists('lchown')) {
66426 if (true !== @lchown($file, $user)) {
66427 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
66428 }
66429 } else {
66430 if (true !== @chown($file, $user)) {
66431 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
66432 }
66433 }
66434 }
66435 }
66436
66437
66438
66439
66440
66441
66442
66443
66444
66445
66446 public function chgrp($files, $group, $recursive = false)
66447 {
66448 foreach ($this->toIterator($files) as $file) {
66449 if ($recursive && is_dir($file) && !is_link($file)) {
66450 $this->chgrp(new \FilesystemIterator($file), $group, true);
66451 }
66452 if (is_link($file) && \function_exists('lchgrp')) {
66453 if (true !== @lchgrp($file, $group) || (\defined('HHVM_VERSION') && !posix_getgrnam($group))) {
66454 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
66455 }
66456 } else {
66457 if (true !== @chgrp($file, $group)) {
66458 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
66459 }
66460 }
66461 }
66462 }
66463
66464
66465
66466
66467
66468
66469
66470
66471
66472
66473
66474 public function rename($origin, $target, $overwrite = false)
66475 {
66476
66477  if (!$overwrite && $this->isReadable($target)) {
66478 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
66479 }
66480
66481 if (true !== @rename($origin, $target)) {
66482 if (is_dir($origin)) {
66483
66484  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
66485 $this->remove($origin);
66486
66487 return;
66488 }
66489 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
66490 }
66491 }
66492
66493
66494
66495
66496
66497
66498
66499
66500
66501
66502 private function isReadable($filename)
66503 {
66504 $maxPathLength = PHP_MAXPATHLEN - 2;
66505
66506 if (\strlen($filename) > $maxPathLength) {
66507 throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
66508 }
66509
66510 return is_readable($filename);
66511 }
66512
66513
66514
66515
66516
66517
66518
66519
66520
66521
66522 public function symlink($originDir, $targetDir, $copyOnWindows = false)
66523 {
66524 if ('\\' === \DIRECTORY_SEPARATOR) {
66525 $originDir = strtr($originDir, '/', '\\');
66526 $targetDir = strtr($targetDir, '/', '\\');
66527
66528 if ($copyOnWindows) {
66529 $this->mirror($originDir, $targetDir);
66530
66531 return;
66532 }
66533 }
66534
66535 $this->mkdir(\dirname($targetDir));
66536
66537 if (is_link($targetDir)) {
66538 if (readlink($targetDir) === $originDir) {
66539 return;
66540 }
66541 $this->remove($targetDir);
66542 }
66543
66544 if (!self::box('symlink', $originDir, $targetDir)) {
66545 if (null !== self::$lastError) {
66546 if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
66547 throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', 0, null, $targetDir);
66548 }
66549 }
66550 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
66551 }
66552 }
66553
66554
66555
66556
66557
66558
66559
66560
66561
66562 public function makePathRelative($endPath, $startPath)
66563 {
66564
66565  if ('\\' === \DIRECTORY_SEPARATOR) {
66566 $endPath = str_replace('\\', '/', $endPath);
66567 $startPath = str_replace('\\', '/', $startPath);
66568 }
66569
66570 $stripDriveLetter = function ($path) {
66571 if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
66572 return substr($path, 2);
66573 }
66574
66575 return $path;
66576 };
66577
66578 $endPath = $stripDriveLetter($endPath);
66579 $startPath = $stripDriveLetter($startPath);
66580
66581
66582  $startPathArr = explode('/', trim($startPath, '/'));
66583 $endPathArr = explode('/', trim($endPath, '/'));
66584
66585 $normalizePathArray = function ($pathSegments, $absolute) {
66586 $result = array();
66587
66588 foreach ($pathSegments as $segment) {
66589 if ('..' === $segment && ($absolute || \count($result))) {
66590 array_pop($result);
66591 } elseif ('.' !== $segment) {
66592 $result[] = $segment;
66593 }
66594 }
66595
66596 return $result;
66597 };
66598
66599 $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
66600 $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
66601
66602
66603  $index = 0;
66604 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
66605 ++$index;
66606 }
66607
66608
66609  if (1 === \count($startPathArr) && '' === $startPathArr[0]) {
66610 $depth = 0;
66611 } else {
66612 $depth = \count($startPathArr) - $index;
66613 }
66614
66615
66616  $traverser = str_repeat('../', $depth);
66617
66618 $endPathRemainder = implode('/', \array_slice($endPathArr, $index));
66619
66620
66621  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
66622
66623 return '' === $relativePath ? './' : $relativePath;
66624 }
66625
66626
66627
66628
66629
66630
66631
66632
66633
66634
66635
66636
66637
66638
66639
66640
66641
66642
66643
66644
66645 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
66646 {
66647 $targetDir = rtrim($targetDir, '/\\');
66648 $originDir = rtrim($originDir, '/\\');
66649 $originDirLen = \strlen($originDir);
66650
66651
66652  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
66653 $deleteIterator = $iterator;
66654 if (null === $deleteIterator) {
66655 $flags = \FilesystemIterator::SKIP_DOTS;
66656 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
66657 }
66658 $targetDirLen = \strlen($targetDir);
66659 foreach ($deleteIterator as $file) {
66660 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
66661 if (!$this->exists($origin)) {
66662 $this->remove($file);
66663 }
66664 }
66665 }
66666
66667 $copyOnWindows = false;
66668 if (isset($options['copy_on_windows'])) {
66669 $copyOnWindows = $options['copy_on_windows'];
66670 }
66671
66672 if (null === $iterator) {
66673 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
66674 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
66675 }
66676
66677 if ($this->exists($originDir)) {
66678 $this->mkdir($targetDir);
66679 }
66680
66681 foreach ($iterator as $file) {
66682 $target = $targetDir.substr($file->getPathname(), $originDirLen);
66683
66684 if ($copyOnWindows) {
66685 if (is_file($file)) {
66686 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
66687 } elseif (is_dir($file)) {
66688 $this->mkdir($target);
66689 } else {
66690 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
66691 }
66692 } else {
66693 if (is_link($file)) {
66694 $this->symlink($file->getLinkTarget(), $target);
66695 } elseif (is_dir($file)) {
66696 $this->mkdir($target);
66697 } elseif (is_file($file)) {
66698 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
66699 } else {
66700 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
66701 }
66702 }
66703 }
66704 }
66705
66706
66707
66708
66709
66710
66711
66712
66713 public function isAbsolutePath($file)
66714 {
66715 return strspn($file, '/\\', 0, 1)
66716 || (\strlen($file) > 3 && ctype_alpha($file[0])
66717 && ':' === substr($file, 1, 1)
66718 && strspn($file, '/\\', 2, 1)
66719 )
66720 || null !== parse_url($file, PHP_URL_SCHEME)
66721 ;
66722 }
66723
66724
66725
66726
66727
66728
66729
66730
66731
66732
66733 public function tempnam($dir, $prefix)
66734 {
66735 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
66736
66737
66738  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
66739 $tmpFile = @tempnam($hierarchy, $prefix);
66740
66741
66742  if (false !== $tmpFile) {
66743 if (null !== $scheme && 'gs' !== $scheme) {
66744 return $scheme.'://'.$tmpFile;
66745 }
66746
66747 return $tmpFile;
66748 }
66749
66750 throw new IOException('A temporary file could not be created.');
66751 }
66752
66753
66754  for ($i = 0; $i < 10; ++$i) {
66755
66756  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
66757
66758
66759  
66760  $handle = @fopen($tmpFile, 'x+');
66761
66762
66763  if (false === $handle) {
66764 continue;
66765 }
66766
66767
66768  @fclose($handle);
66769
66770 return $tmpFile;
66771 }
66772
66773 throw new IOException('A temporary file could not be created.');
66774 }
66775
66776
66777
66778
66779
66780
66781
66782
66783
66784
66785
66786 public function dumpFile($filename, $content, $mode = 0666)
66787 {
66788 $dir = \dirname($filename);
66789
66790 if (!is_dir($dir)) {
66791 $this->mkdir($dir);
66792 }
66793
66794 if (!is_writable($dir)) {
66795 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
66796 }
66797
66798 $tmpFile = $this->tempnam($dir, basename($filename));
66799
66800 if (false === @file_put_contents($tmpFile, $content)) {
66801 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
66802 }
66803
66804 if (null !== $mode) {
66805 if (\func_num_args() > 2) {
66806 @trigger_error('Support for modifying file permissions is deprecated since Symfony 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
66807 }
66808
66809 $this->chmod($tmpFile, $mode);
66810 } elseif (file_exists($filename)) {
66811 @chmod($tmpFile, fileperms($filename));
66812 }
66813
66814 $this->rename($tmpFile, $filename, true);
66815 }
66816
66817
66818
66819
66820
66821
66822 private function toIterator($files)
66823 {
66824 if (!$files instanceof \Traversable) {
66825 $files = new \ArrayObject(\is_array($files) ? $files : array($files));
66826 }
66827
66828 return $files;
66829 }
66830
66831
66832
66833
66834
66835
66836
66837
66838 private function getSchemeAndHierarchy($filename)
66839 {
66840 $components = explode('://', $filename, 2);
66841
66842 return 2 === \count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
66843 }
66844
66845 private static function box($func)
66846 {
66847 self::$lastError = null;
66848 \set_error_handler(__CLASS__.'::handleError');
66849 try {
66850 $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
66851 \restore_error_handler();
66852
66853 return $result;
66854 } catch (\Throwable $e) {
66855 } catch (\Exception $e) {
66856 }
66857 \restore_error_handler();
66858
66859 throw $e;
66860 }
66861
66862
66863
66864
66865 public static function handleError($type, $msg)
66866 {
66867 self::$lastError = $msg;
66868 }
66869 }
66870 Copyright (c) 2004-2018 Fabien Potencier
66871
66872 Permission is hereby granted, free of charge, to any person obtaining a copy
66873 of this software and associated documentation files (the "Software"), to deal
66874 in the Software without restriction, including without limitation the rights
66875 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66876 copies of the Software, and to permit persons to whom the Software is furnished
66877 to do so, subject to the following conditions:
66878
66879 The above copyright notice and this permission notice shall be included in all
66880 copies or substantial portions of the Software.
66881
66882 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
66883 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
66884 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66885 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66886 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
66887 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
66888 THE SOFTWARE.
66889 <?php
66890
66891
66892
66893
66894
66895
66896
66897
66898
66899
66900 namespace Symfony\Component\Filesystem;
66901
66902 use Symfony\Component\Filesystem\Exception\IOException;
66903
66904
66905
66906
66907
66908
66909
66910
66911
66912
66913
66914
66915
66916
66917 class LockHandler
66918 {
66919 private $file;
66920 private $handle;
66921
66922
66923
66924
66925
66926
66927
66928 public function __construct($name, $lockPath = null)
66929 {
66930 $lockPath = $lockPath ?: sys_get_temp_dir();
66931
66932 if (!is_dir($lockPath)) {
66933 $fs = new Filesystem();
66934 $fs->mkdir($lockPath);
66935 }
66936
66937 if (!is_writable($lockPath)) {
66938 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
66939 }
66940
66941 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
66942 }
66943
66944
66945
66946
66947
66948
66949
66950
66951
66952
66953 public function lock($blocking = false)
66954 {
66955 if ($this->handle) {
66956 return true;
66957 }
66958
66959 $error = null;
66960
66961
66962  set_error_handler(function ($errno, $msg) use (&$error) {
66963 $error = $msg;
66964 });
66965
66966 if (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
66967 if ($this->handle = fopen($this->file, 'x')) {
66968 chmod($this->file, 0666);
66969 } elseif (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
66970 usleep(100); 
66971  $this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r');
66972 }
66973 }
66974 restore_error_handler();
66975
66976 if (!$this->handle) {
66977 throw new IOException($error, 0, null, $this->file);
66978 }
66979
66980
66981  
66982  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
66983 fclose($this->handle);
66984 $this->handle = null;
66985
66986 return false;
66987 }
66988
66989 return true;
66990 }
66991
66992
66993
66994
66995 public function release()
66996 {
66997 if ($this->handle) {
66998 flock($this->handle, LOCK_UN | LOCK_NB);
66999 fclose($this->handle);
67000 $this->handle = null;
67001 }
67002 }
67003 }
67004 <?php
67005
67006
67007
67008
67009
67010
67011
67012
67013
67014
67015 namespace Symfony\Component\Finder\Adapter;
67016
67017 @trigger_error('The '.__NAMESPACE__.'\AbstractAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
67018
67019
67020
67021
67022
67023
67024
67025
67026 abstract class AbstractAdapter implements AdapterInterface
67027 {
67028 protected $followLinks = false;
67029 protected $mode = 0;
67030 protected $minDepth = 0;
67031 protected $maxDepth = PHP_INT_MAX;
67032 protected $exclude = array();
67033 protected $names = array();
67034 protected $notNames = array();
67035 protected $contains = array();
67036 protected $notContains = array();
67037 protected $sizes = array();
67038 protected $dates = array();
67039 protected $filters = array();
67040 protected $sort = false;
67041 protected $paths = array();
67042 protected $notPaths = array();
67043 protected $ignoreUnreadableDirs = false;
67044
67045 private static $areSupported = array();
67046
67047
67048
67049
67050 public function isSupported()
67051 {
67052 $name = $this->getName();
67053
67054 if (!array_key_exists($name, self::$areSupported)) {
67055 self::$areSupported[$name] = $this->canBeUsed();
67056 }
67057
67058 return self::$areSupported[$name];
67059 }
67060
67061
67062
67063
67064 public function setFollowLinks($followLinks)
67065 {
67066 $this->followLinks = $followLinks;
67067
67068 return $this;
67069 }
67070
67071
67072
67073
67074 public function setMode($mode)
67075 {
67076 $this->mode = $mode;
67077
67078 return $this;
67079 }
67080
67081
67082
67083
67084 public function setDepths(array $depths)
67085 {
67086 $this->minDepth = 0;
67087 $this->maxDepth = PHP_INT_MAX;
67088
67089 foreach ($depths as $comparator) {
67090 switch ($comparator->getOperator()) {
67091 case '>':
67092 $this->minDepth = $comparator->getTarget() + 1;
67093 break;
67094 case '>=':
67095 $this->minDepth = $comparator->getTarget();
67096 break;
67097 case '<':
67098 $this->maxDepth = $comparator->getTarget() - 1;
67099 break;
67100 case '<=':
67101 $this->maxDepth = $comparator->getTarget();
67102 break;
67103 default:
67104 $this->minDepth = $this->maxDepth = $comparator->getTarget();
67105 }
67106 }
67107
67108 return $this;
67109 }
67110
67111
67112
67113
67114 public function setExclude(array $exclude)
67115 {
67116 $this->exclude = $exclude;
67117
67118 return $this;
67119 }
67120
67121
67122
67123
67124 public function setNames(array $names)
67125 {
67126 $this->names = $names;
67127
67128 return $this;
67129 }
67130
67131
67132
67133
67134 public function setNotNames(array $notNames)
67135 {
67136 $this->notNames = $notNames;
67137
67138 return $this;
67139 }
67140
67141
67142
67143
67144 public function setContains(array $contains)
67145 {
67146 $this->contains = $contains;
67147
67148 return $this;
67149 }
67150
67151
67152
67153
67154 public function setNotContains(array $notContains)
67155 {
67156 $this->notContains = $notContains;
67157
67158 return $this;
67159 }
67160
67161
67162
67163
67164 public function setSizes(array $sizes)
67165 {
67166 $this->sizes = $sizes;
67167
67168 return $this;
67169 }
67170
67171
67172
67173
67174 public function setDates(array $dates)
67175 {
67176 $this->dates = $dates;
67177
67178 return $this;
67179 }
67180
67181
67182
67183
67184 public function setFilters(array $filters)
67185 {
67186 $this->filters = $filters;
67187
67188 return $this;
67189 }
67190
67191
67192
67193
67194 public function setSort($sort)
67195 {
67196 $this->sort = $sort;
67197
67198 return $this;
67199 }
67200
67201
67202
67203
67204 public function setPath(array $paths)
67205 {
67206 $this->paths = $paths;
67207
67208 return $this;
67209 }
67210
67211
67212
67213
67214 public function setNotPath(array $notPaths)
67215 {
67216 $this->notPaths = $notPaths;
67217
67218 return $this;
67219 }
67220
67221
67222
67223
67224 public function ignoreUnreadableDirs($ignore = true)
67225 {
67226 $this->ignoreUnreadableDirs = (bool) $ignore;
67227
67228 return $this;
67229 }
67230
67231
67232
67233
67234
67235
67236
67237
67238
67239
67240
67241
67242 abstract protected function canBeUsed();
67243 }
67244 <?php
67245
67246
67247
67248
67249
67250
67251
67252
67253
67254
67255 namespace Symfony\Component\Finder\Adapter;
67256
67257 @trigger_error('The '.__NAMESPACE__.'\AbstractFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
67258
67259 use Symfony\Component\Finder\Comparator\DateComparator;
67260 use Symfony\Component\Finder\Comparator\NumberComparator;
67261 use Symfony\Component\Finder\Exception\AccessDeniedException;
67262 use Symfony\Component\Finder\Expression\Expression;
67263 use Symfony\Component\Finder\Iterator;
67264 use Symfony\Component\Finder\Shell\Command;
67265 use Symfony\Component\Finder\Shell\Shell;
67266
67267
67268
67269
67270
67271
67272
67273
67274 abstract class AbstractFindAdapter extends AbstractAdapter
67275 {
67276 protected $shell;
67277
67278 public function __construct()
67279 {
67280 $this->shell = new Shell();
67281 }
67282
67283
67284
67285
67286 public function searchInDirectory($dir)
67287 {
67288
67289  $dir = realpath($dir);
67290
67291
67292  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
67293 return new Iterator\FilePathsIterator(array(), $dir);
67294 }
67295
67296 $command = Command::create();
67297 $find = $this->buildFindCommand($command, $dir);
67298
67299 if ($this->followLinks) {
67300 $find->add('-follow');
67301 }
67302
67303 $find->add('-mindepth')->add($this->minDepth + 1);
67304
67305 if (PHP_INT_MAX !== $this->maxDepth) {
67306 $find->add('-maxdepth')->add($this->maxDepth + 1);
67307 }
67308
67309 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
67310 $find->add('-type d');
67311 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
67312 $find->add('-type f');
67313 }
67314
67315 $this->buildNamesFiltering($find, $this->names);
67316 $this->buildNamesFiltering($find, $this->notNames, true);
67317 $this->buildPathsFiltering($find, $dir, $this->paths);
67318 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
67319 $this->buildSizesFiltering($find, $this->sizes);
67320 $this->buildDatesFiltering($find, $this->dates);
67321
67322 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
67323 $useSort = \is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
67324
67325 if ($useGrep && ($this->contains || $this->notContains)) {
67326 $grep = $command->ins('grep');
67327 $this->buildContentFiltering($grep, $this->contains);
67328 $this->buildContentFiltering($grep, $this->notContains, true);
67329 }
67330
67331 if ($useSort) {
67332 $this->buildSorting($command, $this->sort);
67333 }
67334
67335 $command->setErrorHandler(
67336 $this->ignoreUnreadableDirs
67337
67338  ? function ($stderr) { }
67339 : function ($stderr) { throw new AccessDeniedException($stderr); }
67340 );
67341
67342 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
67343 $iterator = new Iterator\FilePathsIterator($paths, $dir);
67344
67345 if ($this->exclude) {
67346 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
67347 }
67348
67349 if (!$useGrep && ($this->contains || $this->notContains)) {
67350 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
67351 }
67352
67353 if ($this->filters) {
67354 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
67355 }
67356
67357 if (!$useSort && $this->sort) {
67358 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
67359 $iterator = $iteratorAggregate->getIterator();
67360 }
67361
67362 return $iterator;
67363 }
67364
67365
67366
67367
67368 protected function canBeUsed()
67369 {
67370 return $this->shell->testCommand('find');
67371 }
67372
67373
67374
67375
67376
67377
67378
67379 protected function buildFindCommand(Command $command, $dir)
67380 {
67381 return $command
67382 ->ins('find')
67383 ->add('find ')
67384 ->arg($dir)
67385 ->add('-noleaf'); 
67386  }
67387
67388
67389
67390
67391
67392
67393 private function buildNamesFiltering(Command $command, array $names, $not = false)
67394 {
67395 if (0 === \count($names)) {
67396 return;
67397 }
67398
67399 $command->add($not ? '-not' : null)->cmd('(');
67400
67401 foreach ($names as $i => $name) {
67402 $expr = Expression::create($name);
67403
67404
67405  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
67406 $expr = Expression::create($expr->getGlob()->toRegex(false));
67407 }
67408
67409
67410  
67411  
67412  if ($expr->isRegex()) {
67413 $regex = $expr->getRegex();
67414 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
67415 ->setStartFlag(false)
67416 ->setStartJoker(true)
67417 ->replaceJokers('[^/]');
67418 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
67419 $regex->setEndJoker(false)->append('[^/]*');
67420 }
67421 }
67422
67423 $command
67424 ->add($i > 0 ? '-or' : null)
67425 ->add($expr->isRegex()
67426 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
67427 : ($expr->isCaseSensitive() ? '-name' : '-iname')
67428 )
67429 ->arg($expr->renderPattern());
67430 }
67431
67432 $command->cmd(')');
67433 }
67434
67435
67436
67437
67438
67439
67440
67441 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
67442 {
67443 if (0 === \count($paths)) {
67444 return;
67445 }
67446
67447 $command->add($not ? '-not' : null)->cmd('(');
67448
67449 foreach ($paths as $i => $path) {
67450 $expr = Expression::create($path);
67451
67452
67453  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
67454 $expr = Expression::create($expr->getGlob()->toRegex(false));
67455 }
67456
67457
67458  if ($expr->isRegex()) {
67459 $regex = $expr->getRegex();
67460 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).\DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
67461 } else {
67462 $expr->prepend('*')->append('*');
67463 }
67464
67465 $command
67466 ->add($i > 0 ? '-or' : null)
67467 ->add($expr->isRegex()
67468 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
67469 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
67470 )
67471 ->arg($expr->renderPattern());
67472 }
67473
67474 $command->cmd(')');
67475 }
67476
67477
67478
67479
67480
67481 private function buildSizesFiltering(Command $command, array $sizes)
67482 {
67483 foreach ($sizes as $i => $size) {
67484 $command->add($i > 0 ? '-and' : null);
67485
67486 switch ($size->getOperator()) {
67487 case '<=':
67488 $command->add('-size -'.($size->getTarget() + 1).'c');
67489 break;
67490 case '>=':
67491 $command->add('-size +'.($size->getTarget() - 1).'c');
67492 break;
67493 case '>':
67494 $command->add('-size +'.$size->getTarget().'c');
67495 break;
67496 case '!=':
67497 $command->add('-size -'.$size->getTarget().'c');
67498 $command->add('-size +'.$size->getTarget().'c');
67499 break;
67500 case '<':
67501 default:
67502 $command->add('-size -'.$size->getTarget().'c');
67503 }
67504 }
67505 }
67506
67507
67508
67509
67510
67511 private function buildDatesFiltering(Command $command, array $dates)
67512 {
67513 foreach ($dates as $i => $date) {
67514 $command->add($i > 0 ? '-and' : null);
67515
67516 $mins = (int) round((time() - $date->getTarget()) / 60);
67517
67518 if (0 > $mins) {
67519
67520  $command->add(' -mmin -0');
67521
67522  return;
67523 }
67524
67525 switch ($date->getOperator()) {
67526 case '<=':
67527 $command->add('-mmin +'.($mins - 1));
67528 break;
67529 case '>=':
67530 $command->add('-mmin -'.($mins + 1));
67531 break;
67532 case '>':
67533 $command->add('-mmin -'.$mins);
67534 break;
67535 case '!=':
67536 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
67537 break;
67538 case '<':
67539 default:
67540 $command->add('-mmin +'.$mins);
67541 }
67542 }
67543 }
67544
67545
67546
67547
67548
67549
67550
67551 private function buildSorting(Command $command, $sort)
67552 {
67553 $this->buildFormatSorting($command, $sort);
67554 }
67555
67556
67557
67558
67559
67560 abstract protected function buildFormatSorting(Command $command, $sort);
67561
67562
67563
67564
67565
67566
67567 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
67568 }
67569 <?php
67570
67571
67572
67573
67574
67575
67576
67577
67578
67579
67580 namespace Symfony\Component\Finder\Adapter;
67581
67582
67583
67584
67585
67586
67587 interface AdapterInterface
67588 {
67589
67590
67591
67592
67593
67594 public function setFollowLinks($followLinks);
67595
67596
67597
67598
67599
67600
67601 public function setMode($mode);
67602
67603
67604
67605
67606 public function setExclude(array $exclude);
67607
67608
67609
67610
67611 public function setDepths(array $depths);
67612
67613
67614
67615
67616 public function setNames(array $names);
67617
67618
67619
67620
67621 public function setNotNames(array $notNames);
67622
67623
67624
67625
67626 public function setContains(array $contains);
67627
67628
67629
67630
67631 public function setNotContains(array $notContains);
67632
67633
67634
67635
67636 public function setSizes(array $sizes);
67637
67638
67639
67640
67641 public function setDates(array $dates);
67642
67643
67644
67645
67646 public function setFilters(array $filters);
67647
67648
67649
67650
67651
67652
67653 public function setSort($sort);
67654
67655
67656
67657
67658 public function setPath(array $paths);
67659
67660
67661
67662
67663 public function setNotPath(array $notPaths);
67664
67665
67666
67667
67668
67669
67670 public function ignoreUnreadableDirs($ignore = true);
67671
67672
67673
67674
67675
67676
67677 public function searchInDirectory($dir);
67678
67679
67680
67681
67682
67683
67684 public function isSupported();
67685
67686
67687
67688
67689
67690
67691 public function getName();
67692 }
67693 <?php
67694
67695
67696
67697
67698
67699
67700
67701
67702
67703
67704 namespace Symfony\Component\Finder\Adapter;
67705
67706 @trigger_error('The '.__NAMESPACE__.'\BsdFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
67707
67708 use Symfony\Component\Finder\Expression\Expression;
67709 use Symfony\Component\Finder\Iterator\SortableIterator;
67710 use Symfony\Component\Finder\Shell\Command;
67711 use Symfony\Component\Finder\Shell\Shell;
67712
67713
67714
67715
67716
67717
67718
67719
67720 class BsdFindAdapter extends AbstractFindAdapter
67721 {
67722
67723
67724
67725 public function getName()
67726 {
67727 return 'bsd_find';
67728 }
67729
67730
67731
67732
67733 protected function canBeUsed()
67734 {
67735 return \in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
67736 }
67737
67738
67739
67740
67741 protected function buildFormatSorting(Command $command, $sort)
67742 {
67743 switch ($sort) {
67744 case SortableIterator::SORT_BY_NAME:
67745 $command->ins('sort')->add('| sort');
67746
67747 return;
67748 case SortableIterator::SORT_BY_TYPE:
67749 $format = '%HT';
67750 break;
67751 case SortableIterator::SORT_BY_ACCESSED_TIME:
67752 $format = '%a';
67753 break;
67754 case SortableIterator::SORT_BY_CHANGED_TIME:
67755 $format = '%c';
67756 break;
67757 case SortableIterator::SORT_BY_MODIFIED_TIME:
67758 $format = '%m';
67759 break;
67760 default:
67761 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
67762 }
67763
67764 $command
67765 ->add('-print0 | xargs -0 stat -f')
67766 ->arg($format.'%t%N')
67767 ->add('| sort | cut -f 2');
67768 }
67769
67770
67771
67772
67773 protected function buildFindCommand(Command $command, $dir)
67774 {
67775 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
67776
67777 return $command;
67778 }
67779
67780
67781
67782
67783 protected function buildContentFiltering(Command $command, array $contains, $not = false)
67784 {
67785 foreach ($contains as $contain) {
67786 $expr = Expression::create($contain);
67787
67788
67789  $command
67790 ->add('| grep -v \'^$\'')
67791 ->add('| xargs -I{} grep -I')
67792 ->add($expr->isCaseSensitive() ? null : '-i')
67793 ->add($not ? '-L' : '-l')
67794 ->add('-Ee')->arg($expr->renderPattern())
67795 ->add('{}')
67796 ;
67797 }
67798 }
67799 }
67800 <?php
67801
67802
67803
67804
67805
67806
67807
67808
67809
67810
67811 namespace Symfony\Component\Finder\Adapter;
67812
67813 @trigger_error('The '.__NAMESPACE__.'\GnuFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
67814
67815 use Symfony\Component\Finder\Expression\Expression;
67816 use Symfony\Component\Finder\Iterator\SortableIterator;
67817 use Symfony\Component\Finder\Shell\Command;
67818 use Symfony\Component\Finder\Shell\Shell;
67819
67820
67821
67822
67823
67824
67825
67826
67827 class GnuFindAdapter extends AbstractFindAdapter
67828 {
67829
67830
67831
67832 public function getName()
67833 {
67834 return 'gnu_find';
67835 }
67836
67837
67838
67839
67840 protected function buildFormatSorting(Command $command, $sort)
67841 {
67842 switch ($sort) {
67843 case SortableIterator::SORT_BY_NAME:
67844 $command->ins('sort')->add('| sort');
67845
67846 return;
67847 case SortableIterator::SORT_BY_TYPE:
67848 $format = '%y';
67849 break;
67850 case SortableIterator::SORT_BY_ACCESSED_TIME:
67851 $format = '%A@';
67852 break;
67853 case SortableIterator::SORT_BY_CHANGED_TIME:
67854 $format = '%C@';
67855 break;
67856 case SortableIterator::SORT_BY_MODIFIED_TIME:
67857 $format = '%T@';
67858 break;
67859 default:
67860 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
67861 }
67862
67863 $command
67864 ->get('find')
67865 ->add('-printf')
67866 ->arg($format.' %h/%f\\n')
67867 ->add('| sort | cut')
67868 ->arg('-d ')
67869 ->arg('-f2-')
67870 ;
67871 }
67872
67873
67874
67875
67876 protected function canBeUsed()
67877 {
67878 return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
67879 }
67880
67881
67882
67883
67884 protected function buildFindCommand(Command $command, $dir)
67885 {
67886 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
67887 }
67888
67889
67890
67891
67892 protected function buildContentFiltering(Command $command, array $contains, $not = false)
67893 {
67894 foreach ($contains as $contain) {
67895 $expr = Expression::create($contain);
67896
67897
67898  $command
67899 ->add('| xargs -I{} -r grep -I')
67900 ->add($expr->isCaseSensitive() ? null : '-i')
67901 ->add($not ? '-L' : '-l')
67902 ->add('-Ee')->arg($expr->renderPattern())
67903 ->add('{}')
67904 ;
67905 }
67906 }
67907 }
67908 <?php
67909
67910
67911
67912
67913
67914
67915
67916
67917
67918
67919 namespace Symfony\Component\Finder\Adapter;
67920
67921 @trigger_error('The '.__NAMESPACE__.'\PhpAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
67922
67923 use Symfony\Component\Finder\Iterator;
67924
67925
67926
67927
67928
67929
67930
67931
67932 class PhpAdapter extends AbstractAdapter
67933 {
67934
67935
67936
67937 public function searchInDirectory($dir)
67938 {
67939 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
67940
67941 if ($this->followLinks) {
67942 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
67943 }
67944
67945 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
67946
67947 if ($this->exclude) {
67948 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
67949 }
67950
67951 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
67952
67953 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
67954 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
67955 }
67956
67957 if ($this->mode) {
67958 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
67959 }
67960
67961 if ($this->names || $this->notNames) {
67962 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
67963 }
67964
67965 if ($this->contains || $this->notContains) {
67966 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
67967 }
67968
67969 if ($this->sizes) {
67970 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
67971 }
67972
67973 if ($this->dates) {
67974 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
67975 }
67976
67977 if ($this->filters) {
67978 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
67979 }
67980
67981 if ($this->paths || $this->notPaths) {
67982 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
67983 }
67984
67985 if ($this->sort) {
67986 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
67987 $iterator = $iteratorAggregate->getIterator();
67988 }
67989
67990 return $iterator;
67991 }
67992
67993
67994
67995
67996 public function getName()
67997 {
67998 return 'php';
67999 }
68000
68001
68002
68003
68004 protected function canBeUsed()
68005 {
68006 return true;
68007 }
68008 }
68009 <?php
68010
68011
68012
68013
68014
68015
68016
68017
68018
68019
68020 namespace Symfony\Component\Finder\Comparator;
68021
68022
68023
68024
68025
68026
68027 class Comparator
68028 {
68029 private $target;
68030 private $operator = '==';
68031
68032
68033
68034
68035
68036
68037 public function getTarget()
68038 {
68039 return $this->target;
68040 }
68041
68042
68043
68044
68045
68046
68047 public function setTarget($target)
68048 {
68049 $this->target = $target;
68050 }
68051
68052
68053
68054
68055
68056
68057 public function getOperator()
68058 {
68059 return $this->operator;
68060 }
68061
68062
68063
68064
68065
68066
68067
68068
68069 public function setOperator($operator)
68070 {
68071 if (!$operator) {
68072 $operator = '==';
68073 }
68074
68075 if (!\in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
68076 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
68077 }
68078
68079 $this->operator = $operator;
68080 }
68081
68082
68083
68084
68085
68086
68087
68088
68089 public function test($test)
68090 {
68091 switch ($this->operator) {
68092 case '>':
68093 return $test > $this->target;
68094 case '>=':
68095 return $test >= $this->target;
68096 case '<':
68097 return $test < $this->target;
68098 case '<=':
68099 return $test <= $this->target;
68100 case '!=':
68101 return $test != $this->target;
68102 }
68103
68104 return $test == $this->target;
68105 }
68106 }
68107 <?php
68108
68109
68110
68111
68112
68113
68114
68115
68116
68117
68118 namespace Symfony\Component\Finder\Comparator;
68119
68120
68121
68122
68123
68124
68125 class DateComparator extends Comparator
68126 {
68127
68128
68129
68130
68131
68132 public function __construct($test)
68133 {
68134 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
68135 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
68136 }
68137
68138 try {
68139 $date = new \DateTime($matches[2]);
68140 $target = $date->format('U');
68141 } catch (\Exception $e) {
68142 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
68143 }
68144
68145 $operator = isset($matches[1]) ? $matches[1] : '==';
68146 if ('since' === $operator || 'after' === $operator) {
68147 $operator = '>';
68148 }
68149
68150 if ('until' === $operator || 'before' === $operator) {
68151 $operator = '<';
68152 }
68153
68154 $this->setOperator($operator);
68155 $this->setTarget($target);
68156 }
68157 }
68158 <?php
68159
68160
68161
68162
68163
68164
68165
68166
68167
68168
68169 namespace Symfony\Component\Finder\Comparator;
68170
68171
68172
68173
68174
68175
68176
68177
68178
68179
68180
68181
68182
68183
68184
68185
68186
68187
68188
68189
68190
68191
68192 class NumberComparator extends Comparator
68193 {
68194
68195
68196
68197
68198
68199 public function __construct($test)
68200 {
68201 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
68202 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
68203 }
68204
68205 $target = $matches[2];
68206 if (!is_numeric($target)) {
68207 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
68208 }
68209 if (isset($matches[3])) {
68210
68211  switch (strtolower($matches[3])) {
68212 case 'k':
68213 $target *= 1000;
68214 break;
68215 case 'ki':
68216 $target *= 1024;
68217 break;
68218 case 'm':
68219 $target *= 1000000;
68220 break;
68221 case 'mi':
68222 $target *= 1024 * 1024;
68223 break;
68224 case 'g':
68225 $target *= 1000000000;
68226 break;
68227 case 'gi':
68228 $target *= 1024 * 1024 * 1024;
68229 break;
68230 }
68231 }
68232
68233 $this->setTarget($target);
68234 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
68235 }
68236 }
68237 <?php
68238
68239
68240
68241
68242
68243
68244
68245
68246
68247
68248 namespace Symfony\Component\Finder\Exception;
68249
68250
68251
68252
68253 class AccessDeniedException extends \UnexpectedValueException
68254 {
68255 }
68256 <?php
68257
68258
68259
68260
68261
68262
68263
68264
68265
68266
68267 namespace Symfony\Component\Finder\Exception;
68268
68269 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68270
68271 use Symfony\Component\Finder\Adapter\AdapterInterface;
68272
68273
68274
68275
68276
68277
68278
68279
68280 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
68281 {
68282 private $adapter;
68283
68284
68285
68286
68287
68288
68289 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
68290 {
68291 $this->adapter = $adapter;
68292 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
68293 }
68294
68295
68296
68297
68298 public function getAdapter()
68299 {
68300 return $this->adapter;
68301 }
68302 }
68303 <?php
68304
68305
68306
68307
68308
68309
68310
68311
68312
68313
68314 namespace Symfony\Component\Finder\Exception;
68315
68316
68317
68318
68319 interface ExceptionInterface
68320 {
68321
68322
68323
68324 public function getAdapter();
68325 }
68326 <?php
68327
68328
68329
68330
68331
68332
68333
68334
68335
68336
68337 namespace Symfony\Component\Finder\Exception;
68338
68339 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68340
68341
68342
68343
68344
68345
68346 class OperationNotPermitedException extends AdapterFailureException
68347 {
68348 }
68349 <?php
68350
68351
68352
68353
68354
68355
68356
68357
68358
68359
68360 namespace Symfony\Component\Finder\Exception;
68361
68362 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68363
68364 use Symfony\Component\Finder\Adapter\AdapterInterface;
68365 use Symfony\Component\Finder\Shell\Command;
68366
68367
68368
68369
68370
68371
68372 class ShellCommandFailureException extends AdapterFailureException
68373 {
68374 private $command;
68375
68376 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
68377 {
68378 $this->command = $command;
68379 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
68380 }
68381
68382
68383
68384
68385 public function getCommand()
68386 {
68387 return $this->command;
68388 }
68389 }
68390 <?php
68391
68392
68393
68394
68395
68396
68397
68398
68399
68400
68401 namespace Symfony\Component\Finder\Expression;
68402
68403 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68404
68405
68406
68407
68408 class Expression implements ValueInterface
68409 {
68410 const TYPE_REGEX = 1;
68411 const TYPE_GLOB = 2;
68412
68413
68414
68415
68416 private $value;
68417
68418
68419
68420
68421
68422
68423 public static function create($expr)
68424 {
68425 return new self($expr);
68426 }
68427
68428
68429
68430
68431 public function __construct($expr)
68432 {
68433 try {
68434 $this->value = Regex::create($expr);
68435 } catch (\InvalidArgumentException $e) {
68436 $this->value = new Glob($expr);
68437 }
68438 }
68439
68440
68441
68442
68443 public function __toString()
68444 {
68445 return $this->render();
68446 }
68447
68448
68449
68450
68451 public function render()
68452 {
68453 return $this->value->render();
68454 }
68455
68456
68457
68458
68459 public function renderPattern()
68460 {
68461 return $this->value->renderPattern();
68462 }
68463
68464
68465
68466
68467 public function isCaseSensitive()
68468 {
68469 return $this->value->isCaseSensitive();
68470 }
68471
68472
68473
68474
68475 public function getType()
68476 {
68477 return $this->value->getType();
68478 }
68479
68480
68481
68482
68483 public function prepend($expr)
68484 {
68485 $this->value->prepend($expr);
68486
68487 return $this;
68488 }
68489
68490
68491
68492
68493 public function append($expr)
68494 {
68495 $this->value->append($expr);
68496
68497 return $this;
68498 }
68499
68500
68501
68502
68503 public function isRegex()
68504 {
68505 return self::TYPE_REGEX === $this->value->getType();
68506 }
68507
68508
68509
68510
68511 public function isGlob()
68512 {
68513 return self::TYPE_GLOB === $this->value->getType();
68514 }
68515
68516
68517
68518
68519
68520
68521 public function getGlob()
68522 {
68523 if (self::TYPE_GLOB !== $this->value->getType()) {
68524 throw new \LogicException('Regex can\'t be transformed to glob.');
68525 }
68526
68527 return $this->value;
68528 }
68529
68530
68531
68532
68533 public function getRegex()
68534 {
68535 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
68536 }
68537 }
68538 <?php
68539
68540
68541
68542
68543
68544
68545
68546
68547
68548
68549 namespace Symfony\Component\Finder\Expression;
68550
68551 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68552
68553 use Symfony\Component\Finder\Glob as FinderGlob;
68554
68555
68556
68557
68558 class Glob implements ValueInterface
68559 {
68560 private $pattern;
68561
68562
68563
68564
68565 public function __construct($pattern)
68566 {
68567 $this->pattern = $pattern;
68568 }
68569
68570
68571
68572
68573 public function render()
68574 {
68575 return $this->pattern;
68576 }
68577
68578
68579
68580
68581 public function renderPattern()
68582 {
68583 return $this->pattern;
68584 }
68585
68586
68587
68588
68589 public function getType()
68590 {
68591 return Expression::TYPE_GLOB;
68592 }
68593
68594
68595
68596
68597 public function isCaseSensitive()
68598 {
68599 return true;
68600 }
68601
68602
68603
68604
68605 public function prepend($expr)
68606 {
68607 $this->pattern = $expr.$this->pattern;
68608
68609 return $this;
68610 }
68611
68612
68613
68614
68615 public function append($expr)
68616 {
68617 $this->pattern .= $expr;
68618
68619 return $this;
68620 }
68621
68622
68623
68624
68625
68626
68627 public function isExpandable()
68628 {
68629 return false !== strpos($this->pattern, '{')
68630 && false !== strpos($this->pattern, '}');
68631 }
68632
68633
68634
68635
68636
68637
68638
68639 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
68640 {
68641 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
68642
68643 return new Regex($regex);
68644 }
68645 }
68646 <?php
68647
68648
68649
68650
68651
68652
68653
68654
68655
68656
68657 namespace Symfony\Component\Finder\Expression;
68658
68659 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68660
68661
68662
68663
68664 class Regex implements ValueInterface
68665 {
68666 const START_FLAG = '^';
68667 const END_FLAG = '$';
68668 const BOUNDARY = '~';
68669 const JOKER = '.*';
68670 const ESCAPING = '\\';
68671
68672
68673
68674
68675 private $pattern;
68676
68677
68678
68679
68680 private $options;
68681
68682
68683
68684
68685 private $startFlag;
68686
68687
68688
68689
68690 private $endFlag;
68691
68692
68693
68694
68695 private $startJoker;
68696
68697
68698
68699
68700 private $endJoker;
68701
68702
68703
68704
68705
68706
68707
68708
68709 public static function create($expr)
68710 {
68711 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
68712 $start = substr($m[1], 0, 1);
68713 $end = substr($m[1], -1);
68714
68715 if (
68716 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
68717 || ('{' === $start && '}' === $end)
68718 || ('(' === $start && ')' === $end)
68719 ) {
68720 return new self(substr($m[1], 1, -1), $m[2], $end);
68721 }
68722 }
68723
68724 throw new \InvalidArgumentException('Given expression is not a regex.');
68725 }
68726
68727
68728
68729
68730
68731
68732 public function __construct($pattern, $options = '', $delimiter = null)
68733 {
68734 if (null !== $delimiter) {
68735
68736  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
68737 }
68738
68739 $this->parsePattern($pattern);
68740 $this->options = $options;
68741 }
68742
68743
68744
68745
68746 public function __toString()
68747 {
68748 return $this->render();
68749 }
68750
68751
68752
68753
68754 public function render()
68755 {
68756 return self::BOUNDARY
68757 .$this->renderPattern()
68758 .self::BOUNDARY
68759 .$this->options;
68760 }
68761
68762
68763
68764
68765 public function renderPattern()
68766 {
68767 return ($this->startFlag ? self::START_FLAG : '')
68768 .($this->startJoker ? self::JOKER : '')
68769 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
68770 .($this->endJoker ? self::JOKER : '')
68771 .($this->endFlag ? self::END_FLAG : '');
68772 }
68773
68774
68775
68776
68777 public function isCaseSensitive()
68778 {
68779 return !$this->hasOption('i');
68780 }
68781
68782
68783
68784
68785 public function getType()
68786 {
68787 return Expression::TYPE_REGEX;
68788 }
68789
68790
68791
68792
68793 public function prepend($expr)
68794 {
68795 $this->pattern = $expr.$this->pattern;
68796
68797 return $this;
68798 }
68799
68800
68801
68802
68803 public function append($expr)
68804 {
68805 $this->pattern .= $expr;
68806
68807 return $this;
68808 }
68809
68810
68811
68812
68813
68814
68815 public function hasOption($option)
68816 {
68817 return false !== strpos($this->options, $option);
68818 }
68819
68820
68821
68822
68823
68824
68825 public function addOption($option)
68826 {
68827 if (!$this->hasOption($option)) {
68828 $this->options .= $option;
68829 }
68830
68831 return $this;
68832 }
68833
68834
68835
68836
68837
68838
68839 public function removeOption($option)
68840 {
68841 $this->options = str_replace($option, '', $this->options);
68842
68843 return $this;
68844 }
68845
68846
68847
68848
68849
68850
68851 public function setStartFlag($startFlag)
68852 {
68853 $this->startFlag = $startFlag;
68854
68855 return $this;
68856 }
68857
68858
68859
68860
68861 public function hasStartFlag()
68862 {
68863 return $this->startFlag;
68864 }
68865
68866
68867
68868
68869
68870
68871 public function setEndFlag($endFlag)
68872 {
68873 $this->endFlag = (bool) $endFlag;
68874
68875 return $this;
68876 }
68877
68878
68879
68880
68881 public function hasEndFlag()
68882 {
68883 return $this->endFlag;
68884 }
68885
68886
68887
68888
68889
68890
68891 public function setStartJoker($startJoker)
68892 {
68893 $this->startJoker = $startJoker;
68894
68895 return $this;
68896 }
68897
68898
68899
68900
68901 public function hasStartJoker()
68902 {
68903 return $this->startJoker;
68904 }
68905
68906
68907
68908
68909
68910
68911 public function setEndJoker($endJoker)
68912 {
68913 $this->endJoker = (bool) $endJoker;
68914
68915 return $this;
68916 }
68917
68918
68919
68920
68921 public function hasEndJoker()
68922 {
68923 return $this->endJoker;
68924 }
68925
68926
68927
68928
68929 public function replaceJokers($replacement)
68930 {
68931 $replace = function ($subject) use ($replacement) {
68932 $subject = $subject[0];
68933 $replace = 0 === substr_count($subject, '\\') % 2;
68934
68935 return $replace ? str_replace('.', $replacement, $subject) : $subject;
68936 };
68937
68938 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
68939
68940 return $this;
68941 }
68942
68943
68944
68945
68946 private function parsePattern($pattern)
68947 {
68948 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
68949 $pattern = substr($pattern, 1);
68950 }
68951
68952 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
68953 $pattern = substr($pattern, 2);
68954 }
68955
68956 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
68957 $pattern = substr($pattern, 0, -1);
68958 }
68959
68960 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
68961 $pattern = substr($pattern, 0, -2);
68962 }
68963
68964 $this->pattern = $pattern;
68965 }
68966 }
68967 <?php
68968
68969
68970
68971
68972
68973
68974
68975
68976
68977
68978 namespace Symfony\Component\Finder\Expression;
68979
68980 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68981
68982
68983
68984
68985 interface ValueInterface
68986 {
68987
68988
68989
68990
68991
68992 public function render();
68993
68994
68995
68996
68997
68998
68999 public function renderPattern();
69000
69001
69002
69003
69004
69005
69006 public function isCaseSensitive();
69007
69008
69009
69010
69011
69012
69013 public function getType();
69014
69015
69016
69017
69018
69019
69020 public function prepend($expr);
69021
69022
69023
69024
69025
69026
69027 public function append($expr);
69028 }
69029 <?php
69030
69031
69032
69033
69034
69035
69036
69037
69038
69039
69040 namespace Symfony\Component\Finder;
69041
69042 use Symfony\Component\Finder\Adapter\AdapterInterface;
69043 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
69044 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
69045 use Symfony\Component\Finder\Adapter\PhpAdapter;
69046 use Symfony\Component\Finder\Comparator\DateComparator;
69047 use Symfony\Component\Finder\Comparator\NumberComparator;
69048 use Symfony\Component\Finder\Exception\ExceptionInterface;
69049 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
69050 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
69051 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
69052 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
69053 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
69054 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
69055 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
69056 use Symfony\Component\Finder\Iterator\SortableIterator;
69057
69058
69059
69060
69061
69062
69063
69064
69065
69066
69067
69068
69069
69070
69071 class Finder implements \IteratorAggregate, \Countable
69072 {
69073 const IGNORE_VCS_FILES = 1;
69074 const IGNORE_DOT_FILES = 2;
69075
69076 private $mode = 0;
69077 private $names = array();
69078 private $notNames = array();
69079 private $exclude = array();
69080 private $filters = array();
69081 private $depths = array();
69082 private $sizes = array();
69083 private $followLinks = false;
69084 private $sort = false;
69085 private $ignore = 0;
69086 private $dirs = array();
69087 private $dates = array();
69088 private $iterators = array();
69089 private $contains = array();
69090 private $notContains = array();
69091 private $adapters = null;
69092 private $paths = array();
69093 private $notPaths = array();
69094 private $ignoreUnreadableDirs = false;
69095
69096 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
69097
69098 public function __construct()
69099 {
69100 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
69101 }
69102
69103
69104
69105
69106
69107
69108 public static function create()
69109 {
69110 return new static();
69111 }
69112
69113
69114
69115
69116
69117
69118
69119
69120
69121
69122
69123 public function addAdapter(AdapterInterface $adapter, $priority = 0)
69124 {
69125 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69126
69127 $this->initDefaultAdapters();
69128
69129 $this->adapters[$adapter->getName()] = array(
69130 'adapter' => $adapter,
69131 'priority' => $priority,
69132 'selected' => false,
69133 );
69134
69135 return $this->sortAdapters();
69136 }
69137
69138
69139
69140
69141
69142
69143
69144
69145 public function useBestAdapter()
69146 {
69147 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69148
69149 $this->initDefaultAdapters();
69150
69151 $this->resetAdapterSelection();
69152
69153 return $this->sortAdapters();
69154 }
69155
69156
69157
69158
69159
69160
69161
69162
69163
69164
69165
69166
69167 public function setAdapter($name)
69168 {
69169 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69170
69171 $this->initDefaultAdapters();
69172
69173 if (!isset($this->adapters[$name])) {
69174 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
69175 }
69176
69177 $this->resetAdapterSelection();
69178 $this->adapters[$name]['selected'] = true;
69179
69180 return $this->sortAdapters();
69181 }
69182
69183
69184
69185
69186
69187
69188
69189
69190 public function removeAdapters()
69191 {
69192 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69193
69194 $this->adapters = array();
69195
69196 return $this;
69197 }
69198
69199
69200
69201
69202
69203
69204
69205
69206 public function getAdapters()
69207 {
69208 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69209
69210 $this->initDefaultAdapters();
69211
69212 return array_values(array_map(function (array $adapter) {
69213 return $adapter['adapter'];
69214 }, $this->adapters));
69215 }
69216
69217
69218
69219
69220
69221
69222 public function directories()
69223 {
69224 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
69225
69226 return $this;
69227 }
69228
69229
69230
69231
69232
69233
69234 public function files()
69235 {
69236 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
69237
69238 return $this;
69239 }
69240
69241
69242
69243
69244
69245
69246
69247
69248
69249
69250
69251
69252
69253
69254
69255
69256 public function depth($level)
69257 {
69258 $this->depths[] = new Comparator\NumberComparator($level);
69259
69260 return $this;
69261 }
69262
69263
69264
69265
69266
69267
69268
69269
69270
69271
69272
69273
69274
69275
69276
69277
69278
69279
69280
69281 public function date($date)
69282 {
69283 $this->dates[] = new Comparator\DateComparator($date);
69284
69285 return $this;
69286 }
69287
69288
69289
69290
69291
69292
69293
69294
69295
69296
69297
69298
69299
69300
69301
69302
69303 public function name($pattern)
69304 {
69305 $this->names[] = $pattern;
69306
69307 return $this;
69308 }
69309
69310
69311
69312
69313
69314
69315
69316
69317
69318
69319 public function notName($pattern)
69320 {
69321 $this->notNames[] = $pattern;
69322
69323 return $this;
69324 }
69325
69326
69327
69328
69329
69330
69331
69332
69333
69334
69335
69336
69337
69338
69339
69340 public function contains($pattern)
69341 {
69342 $this->contains[] = $pattern;
69343
69344 return $this;
69345 }
69346
69347
69348
69349
69350
69351
69352
69353
69354
69355
69356
69357
69358
69359
69360
69361 public function notContains($pattern)
69362 {
69363 $this->notContains[] = $pattern;
69364
69365 return $this;
69366 }
69367
69368
69369
69370
69371
69372
69373
69374
69375
69376
69377
69378
69379
69380
69381
69382
69383
69384 public function path($pattern)
69385 {
69386 $this->paths[] = $pattern;
69387
69388 return $this;
69389 }
69390
69391
69392
69393
69394
69395
69396
69397
69398
69399
69400
69401
69402
69403
69404
69405
69406
69407 public function notPath($pattern)
69408 {
69409 $this->notPaths[] = $pattern;
69410
69411 return $this;
69412 }
69413
69414
69415
69416
69417
69418
69419
69420
69421
69422
69423
69424
69425
69426
69427
69428 public function size($size)
69429 {
69430 $this->sizes[] = new Comparator\NumberComparator($size);
69431
69432 return $this;
69433 }
69434
69435
69436
69437
69438
69439
69440
69441
69442
69443
69444
69445
69446
69447
69448 public function exclude($dirs)
69449 {
69450 $this->exclude = array_merge($this->exclude, (array) $dirs);
69451
69452 return $this;
69453 }
69454
69455
69456
69457
69458
69459
69460
69461
69462
69463
69464
69465
69466 public function ignoreDotFiles($ignoreDotFiles)
69467 {
69468 if ($ignoreDotFiles) {
69469 $this->ignore |= static::IGNORE_DOT_FILES;
69470 } else {
69471 $this->ignore &= ~static::IGNORE_DOT_FILES;
69472 }
69473
69474 return $this;
69475 }
69476
69477
69478
69479
69480
69481
69482
69483
69484
69485
69486
69487
69488 public function ignoreVCS($ignoreVCS)
69489 {
69490 if ($ignoreVCS) {
69491 $this->ignore |= static::IGNORE_VCS_FILES;
69492 } else {
69493 $this->ignore &= ~static::IGNORE_VCS_FILES;
69494 }
69495
69496 return $this;
69497 }
69498
69499
69500
69501
69502
69503
69504
69505
69506 public static function addVCSPattern($pattern)
69507 {
69508 foreach ((array) $pattern as $p) {
69509 self::$vcsPatterns[] = $p;
69510 }
69511
69512 self::$vcsPatterns = array_unique(self::$vcsPatterns);
69513 }
69514
69515
69516
69517
69518
69519
69520
69521
69522
69523
69524
69525
69526 public function sort(\Closure $closure)
69527 {
69528 $this->sort = $closure;
69529
69530 return $this;
69531 }
69532
69533
69534
69535
69536
69537
69538
69539
69540
69541
69542 public function sortByName()
69543 {
69544 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
69545
69546 return $this;
69547 }
69548
69549
69550
69551
69552
69553
69554
69555
69556
69557
69558 public function sortByType()
69559 {
69560 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
69561
69562 return $this;
69563 }
69564
69565
69566
69567
69568
69569
69570
69571
69572
69573
69574
69575
69576 public function sortByAccessedTime()
69577 {
69578 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
69579
69580 return $this;
69581 }
69582
69583
69584
69585
69586
69587
69588
69589
69590
69591
69592
69593
69594
69595
69596 public function sortByChangedTime()
69597 {
69598 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
69599
69600 return $this;
69601 }
69602
69603
69604
69605
69606
69607
69608
69609
69610
69611
69612
69613
69614 public function sortByModifiedTime()
69615 {
69616 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
69617
69618 return $this;
69619 }
69620
69621
69622
69623
69624
69625
69626
69627
69628
69629
69630
69631 public function filter(\Closure $closure)
69632 {
69633 $this->filters[] = $closure;
69634
69635 return $this;
69636 }
69637
69638
69639
69640
69641
69642
69643 public function followLinks()
69644 {
69645 $this->followLinks = true;
69646
69647 return $this;
69648 }
69649
69650
69651
69652
69653
69654
69655
69656
69657
69658
69659 public function ignoreUnreadableDirs($ignore = true)
69660 {
69661 $this->ignoreUnreadableDirs = (bool) $ignore;
69662
69663 return $this;
69664 }
69665
69666
69667
69668
69669
69670
69671
69672
69673
69674
69675 public function in($dirs)
69676 {
69677 $resolvedDirs = array();
69678
69679 foreach ((array) $dirs as $dir) {
69680 if (is_dir($dir)) {
69681 $resolvedDirs[] = $this->normalizeDir($dir);
69682 } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
69683 $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob));
69684 } else {
69685 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
69686 }
69687 }
69688
69689 $this->dirs = array_merge($this->dirs, $resolvedDirs);
69690
69691 return $this;
69692 }
69693
69694
69695
69696
69697
69698
69699
69700
69701
69702
69703 public function getIterator()
69704 {
69705 if (0 === \count($this->dirs) && 0 === \count($this->iterators)) {
69706 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
69707 }
69708
69709 if (1 === \count($this->dirs) && 0 === \count($this->iterators)) {
69710 return $this->searchInDirectory($this->dirs[0]);
69711 }
69712
69713 $iterator = new \AppendIterator();
69714 foreach ($this->dirs as $dir) {
69715 $iterator->append($this->searchInDirectory($dir));
69716 }
69717
69718 foreach ($this->iterators as $it) {
69719 $iterator->append($it);
69720 }
69721
69722 return $iterator;
69723 }
69724
69725
69726
69727
69728
69729
69730
69731
69732
69733
69734
69735
69736 public function append($iterator)
69737 {
69738 if ($iterator instanceof \IteratorAggregate) {
69739 $this->iterators[] = $iterator->getIterator();
69740 } elseif ($iterator instanceof \Iterator) {
69741 $this->iterators[] = $iterator;
69742 } elseif ($iterator instanceof \Traversable || \is_array($iterator)) {
69743 $it = new \ArrayIterator();
69744 foreach ($iterator as $file) {
69745 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
69746 }
69747 $this->iterators[] = $it;
69748 } else {
69749 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
69750 }
69751
69752 return $this;
69753 }
69754
69755
69756
69757
69758
69759
69760 public function count()
69761 {
69762 return iterator_count($this->getIterator());
69763 }
69764
69765
69766
69767
69768 private function sortAdapters()
69769 {
69770 uasort($this->adapters, function (array $a, array $b) {
69771 if ($a['selected'] || $b['selected']) {
69772 return $a['selected'] ? -1 : 1;
69773 }
69774
69775 return $a['priority'] > $b['priority'] ? -1 : 1;
69776 });
69777
69778 return $this;
69779 }
69780
69781
69782
69783
69784
69785
69786 private function searchInDirectory($dir)
69787 {
69788 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
69789 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
69790 }
69791
69792 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
69793 $this->notPaths[] = '#(^|/)\..+(/|$)#';
69794 }
69795
69796 if ($this->adapters) {
69797 foreach ($this->adapters as $adapter) {
69798 if ($adapter['adapter']->isSupported()) {
69799 try {
69800 return $this
69801 ->buildAdapter($adapter['adapter'])
69802 ->searchInDirectory($dir);
69803 } catch (ExceptionInterface $e) {
69804 }
69805 }
69806 }
69807 }
69808
69809 $minDepth = 0;
69810 $maxDepth = PHP_INT_MAX;
69811
69812 foreach ($this->depths as $comparator) {
69813 switch ($comparator->getOperator()) {
69814 case '>':
69815 $minDepth = $comparator->getTarget() + 1;
69816 break;
69817 case '>=':
69818 $minDepth = $comparator->getTarget();
69819 break;
69820 case '<':
69821 $maxDepth = $comparator->getTarget() - 1;
69822 break;
69823 case '<=':
69824 $maxDepth = $comparator->getTarget();
69825 break;
69826 default:
69827 $minDepth = $maxDepth = $comparator->getTarget();
69828 }
69829 }
69830
69831 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
69832
69833 if ($this->followLinks) {
69834 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
69835 }
69836
69837 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
69838
69839 if ($this->exclude) {
69840 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
69841 }
69842
69843 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
69844
69845 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
69846 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
69847 }
69848
69849 if ($this->mode) {
69850 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
69851 }
69852
69853 if ($this->names || $this->notNames) {
69854 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
69855 }
69856
69857 if ($this->contains || $this->notContains) {
69858 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
69859 }
69860
69861 if ($this->sizes) {
69862 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
69863 }
69864
69865 if ($this->dates) {
69866 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
69867 }
69868
69869 if ($this->filters) {
69870 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
69871 }
69872
69873 if ($this->paths || $this->notPaths) {
69874 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
69875 }
69876
69877 if ($this->sort) {
69878 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
69879 $iterator = $iteratorAggregate->getIterator();
69880 }
69881
69882 return $iterator;
69883 }
69884
69885
69886
69887
69888 private function buildAdapter(AdapterInterface $adapter)
69889 {
69890 return $adapter
69891 ->setFollowLinks($this->followLinks)
69892 ->setDepths($this->depths)
69893 ->setMode($this->mode)
69894 ->setExclude($this->exclude)
69895 ->setNames($this->names)
69896 ->setNotNames($this->notNames)
69897 ->setContains($this->contains)
69898 ->setNotContains($this->notContains)
69899 ->setSizes($this->sizes)
69900 ->setDates($this->dates)
69901 ->setFilters($this->filters)
69902 ->setSort($this->sort)
69903 ->setPath($this->paths)
69904 ->setNotPath($this->notPaths)
69905 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
69906 }
69907
69908
69909
69910
69911 private function resetAdapterSelection()
69912 {
69913 $this->adapters = array_map(function (array $properties) {
69914 $properties['selected'] = false;
69915
69916 return $properties;
69917 }, $this->adapters);
69918 }
69919
69920 private function initDefaultAdapters()
69921 {
69922 if (null === $this->adapters) {
69923 $this->adapters = array();
69924 $this
69925 ->addAdapter(new GnuFindAdapter())
69926 ->addAdapter(new BsdFindAdapter())
69927 ->addAdapter(new PhpAdapter(), -50)
69928 ->setAdapter('php')
69929 ;
69930 }
69931 }
69932
69933
69934
69935
69936
69937
69938
69939
69940 private function normalizeDir($dir)
69941 {
69942 return rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
69943 }
69944 }
69945 <?php
69946
69947
69948
69949
69950
69951
69952
69953
69954
69955
69956 namespace Symfony\Component\Finder;
69957
69958
69959
69960
69961
69962
69963
69964
69965
69966
69967
69968
69969
69970
69971
69972
69973
69974
69975
69976
69977
69978
69979
69980 class Glob
69981 {
69982
69983
69984
69985
69986
69987
69988
69989
69990
69991
69992 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
69993 {
69994 $firstByte = true;
69995 $escaping = false;
69996 $inCurlies = 0;
69997 $regex = '';
69998 $sizeGlob = \strlen($glob);
69999 for ($i = 0; $i < $sizeGlob; ++$i) {
70000 $car = $glob[$i];
70001 if ($firstByte) {
70002 if ($strictLeadingDot && '.' !== $car) {
70003 $regex .= '(?=[^\.])';
70004 }
70005
70006 $firstByte = false;
70007 }
70008
70009 if ('/' === $car) {
70010 $firstByte = true;
70011 }
70012
70013 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
70014 $regex .= "\\$car";
70015 } elseif ('*' === $car) {
70016 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
70017 } elseif ('?' === $car) {
70018 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
70019 } elseif ('{' === $car) {
70020 $regex .= $escaping ? '\\{' : '(';
70021 if (!$escaping) {
70022 ++$inCurlies;
70023 }
70024 } elseif ('}' === $car && $inCurlies) {
70025 $regex .= $escaping ? '}' : ')';
70026 if (!$escaping) {
70027 --$inCurlies;
70028 }
70029 } elseif (',' === $car && $inCurlies) {
70030 $regex .= $escaping ? ',' : '|';
70031 } elseif ('\\' === $car) {
70032 if ($escaping) {
70033 $regex .= '\\\\';
70034 $escaping = false;
70035 } else {
70036 $escaping = true;
70037 }
70038
70039 continue;
70040 } else {
70041 $regex .= $car;
70042 }
70043 $escaping = false;
70044 }
70045
70046 return $delimiter.'^'.$regex.'$'.$delimiter;
70047 }
70048 }
70049 <?php
70050
70051
70052
70053
70054
70055
70056
70057
70058
70059
70060 namespace Symfony\Component\Finder\Iterator;
70061
70062
70063
70064
70065
70066
70067
70068
70069
70070 class CustomFilterIterator extends FilterIterator
70071 {
70072 private $filters = array();
70073
70074
70075
70076
70077
70078
70079
70080 public function __construct(\Iterator $iterator, array $filters)
70081 {
70082 foreach ($filters as $filter) {
70083 if (!\is_callable($filter)) {
70084 throw new \InvalidArgumentException('Invalid PHP callback.');
70085 }
70086 }
70087 $this->filters = $filters;
70088
70089 parent::__construct($iterator);
70090 }
70091
70092
70093
70094
70095
70096
70097 public function accept()
70098 {
70099 $fileinfo = $this->current();
70100
70101 foreach ($this->filters as $filter) {
70102 if (false === \call_user_func($filter, $fileinfo)) {
70103 return false;
70104 }
70105 }
70106
70107 return true;
70108 }
70109 }
70110 <?php
70111
70112
70113
70114
70115
70116
70117
70118
70119
70120
70121 namespace Symfony\Component\Finder\Iterator;
70122
70123 use Symfony\Component\Finder\Comparator\DateComparator;
70124
70125
70126
70127
70128
70129
70130 class DateRangeFilterIterator extends FilterIterator
70131 {
70132 private $comparators = array();
70133
70134
70135
70136
70137
70138 public function __construct(\Iterator $iterator, array $comparators)
70139 {
70140 $this->comparators = $comparators;
70141
70142 parent::__construct($iterator);
70143 }
70144
70145
70146
70147
70148
70149
70150 public function accept()
70151 {
70152 $fileinfo = $this->current();
70153
70154 if (!file_exists($fileinfo->getPathname())) {
70155 return false;
70156 }
70157
70158 $filedate = $fileinfo->getMTime();
70159 foreach ($this->comparators as $compare) {
70160 if (!$compare->test($filedate)) {
70161 return false;
70162 }
70163 }
70164
70165 return true;
70166 }
70167 }
70168 <?php
70169
70170
70171
70172
70173
70174
70175
70176
70177
70178
70179 namespace Symfony\Component\Finder\Iterator;
70180
70181
70182
70183
70184
70185
70186 class DepthRangeFilterIterator extends FilterIterator
70187 {
70188 private $minDepth = 0;
70189
70190
70191
70192
70193
70194
70195 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
70196 {
70197 $this->minDepth = $minDepth;
70198 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
70199
70200 parent::__construct($iterator);
70201 }
70202
70203
70204
70205
70206
70207
70208 public function accept()
70209 {
70210 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
70211 }
70212 }
70213 <?php
70214
70215
70216
70217
70218
70219
70220
70221
70222
70223
70224 namespace Symfony\Component\Finder\Iterator;
70225
70226
70227
70228
70229
70230
70231 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
70232 {
70233 private $iterator;
70234 private $isRecursive;
70235 private $excludedDirs = array();
70236 private $excludedPattern;
70237
70238
70239
70240
70241
70242 public function __construct(\Iterator $iterator, array $directories)
70243 {
70244 $this->iterator = $iterator;
70245 $this->isRecursive = $iterator instanceof \RecursiveIterator;
70246 $patterns = array();
70247 foreach ($directories as $directory) {
70248 $directory = rtrim($directory, '/');
70249 if (!$this->isRecursive || false !== strpos($directory, '/')) {
70250 $patterns[] = preg_quote($directory, '#');
70251 } else {
70252 $this->excludedDirs[$directory] = true;
70253 }
70254 }
70255 if ($patterns) {
70256 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
70257 }
70258
70259 parent::__construct($iterator);
70260 }
70261
70262
70263
70264
70265
70266
70267 public function accept()
70268 {
70269 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
70270 return false;
70271 }
70272
70273 if ($this->excludedPattern) {
70274 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
70275 $path = str_replace('\\', '/', $path);
70276
70277 return !preg_match($this->excludedPattern, $path);
70278 }
70279
70280 return true;
70281 }
70282
70283 public function hasChildren()
70284 {
70285 return $this->isRecursive && $this->iterator->hasChildren();
70286 }
70287
70288 public function getChildren()
70289 {
70290 $children = new self($this->iterator->getChildren(), array());
70291 $children->excludedDirs = $this->excludedDirs;
70292 $children->excludedPattern = $this->excludedPattern;
70293
70294 return $children;
70295 }
70296 }
70297 <?php
70298
70299
70300
70301
70302
70303
70304
70305
70306
70307
70308 namespace Symfony\Component\Finder\Iterator;
70309
70310 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70311
70312 use Symfony\Component\Finder\SplFileInfo;
70313
70314
70315
70316
70317
70318
70319
70320
70321 class FilePathsIterator extends \ArrayIterator
70322 {
70323
70324
70325
70326 private $baseDir;
70327
70328
70329
70330
70331 private $baseDirLength;
70332
70333
70334
70335
70336 private $subPath;
70337
70338
70339
70340
70341 private $subPathname;
70342
70343
70344
70345
70346 private $current;
70347
70348
70349
70350
70351
70352 public function __construct(array $paths, $baseDir)
70353 {
70354 $this->baseDir = $baseDir;
70355 $this->baseDirLength = \strlen($baseDir);
70356
70357 parent::__construct($paths);
70358 }
70359
70360
70361
70362
70363
70364
70365
70366 public function __call($name, array $arguments)
70367 {
70368 return \call_user_func_array(array($this->current(), $name), $arguments);
70369 }
70370
70371
70372
70373
70374
70375
70376 public function current()
70377 {
70378 return $this->current;
70379 }
70380
70381
70382
70383
70384 public function key()
70385 {
70386 return $this->current->getPathname();
70387 }
70388
70389 public function next()
70390 {
70391 parent::next();
70392 $this->buildProperties();
70393 }
70394
70395 public function rewind()
70396 {
70397 parent::rewind();
70398 $this->buildProperties();
70399 }
70400
70401
70402
70403
70404 public function getSubPath()
70405 {
70406 return $this->subPath;
70407 }
70408
70409
70410
70411
70412 public function getSubPathname()
70413 {
70414 return $this->subPathname;
70415 }
70416
70417 private function buildProperties()
70418 {
70419 $absolutePath = parent::current();
70420
70421 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
70422 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
70423 $dir = \dirname($this->subPathname);
70424 $this->subPath = '.' === $dir ? '' : $dir;
70425 } else {
70426 $this->subPath = $this->subPathname = '';
70427 }
70428
70429 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
70430 }
70431 }
70432 <?php
70433
70434
70435
70436
70437
70438
70439
70440
70441
70442
70443 namespace Symfony\Component\Finder\Iterator;
70444
70445
70446
70447
70448
70449
70450 class FileTypeFilterIterator extends FilterIterator
70451 {
70452 const ONLY_FILES = 1;
70453 const ONLY_DIRECTORIES = 2;
70454
70455 private $mode;
70456
70457
70458
70459
70460
70461 public function __construct(\Iterator $iterator, $mode)
70462 {
70463 $this->mode = $mode;
70464
70465 parent::__construct($iterator);
70466 }
70467
70468
70469
70470
70471
70472
70473 public function accept()
70474 {
70475 $fileinfo = $this->current();
70476 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
70477 return false;
70478 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
70479 return false;
70480 }
70481
70482 return true;
70483 }
70484 }
70485 <?php
70486
70487
70488
70489
70490
70491
70492
70493
70494
70495
70496 namespace Symfony\Component\Finder\Iterator;
70497
70498
70499
70500
70501
70502
70503
70504 class FilecontentFilterIterator extends MultiplePcreFilterIterator
70505 {
70506
70507
70508
70509
70510
70511 public function accept()
70512 {
70513 if (!$this->matchRegexps && !$this->noMatchRegexps) {
70514 return true;
70515 }
70516
70517 $fileinfo = $this->current();
70518
70519 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
70520 return false;
70521 }
70522
70523 $content = $fileinfo->getContents();
70524 if (!$content) {
70525 return false;
70526 }
70527
70528 return $this->isAccepted($content);
70529 }
70530
70531
70532
70533
70534
70535
70536
70537
70538 protected function toRegex($str)
70539 {
70540 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
70541 }
70542 }
70543 <?php
70544
70545
70546
70547
70548
70549
70550
70551
70552
70553
70554 namespace Symfony\Component\Finder\Iterator;
70555
70556 use Symfony\Component\Finder\Glob;
70557
70558
70559
70560
70561
70562
70563 class FilenameFilterIterator extends MultiplePcreFilterIterator
70564 {
70565
70566
70567
70568
70569
70570 public function accept()
70571 {
70572 return $this->isAccepted($this->current()->getFilename());
70573 }
70574
70575
70576
70577
70578
70579
70580
70581
70582
70583
70584
70585 protected function toRegex($str)
70586 {
70587 return $this->isRegex($str) ? $str : Glob::toRegex($str);
70588 }
70589 }
70590 <?php
70591
70592
70593
70594
70595
70596
70597
70598
70599
70600
70601 namespace Symfony\Component\Finder\Iterator;
70602
70603
70604
70605
70606
70607
70608
70609
70610
70611 abstract class FilterIterator extends \FilterIterator
70612 {
70613
70614
70615
70616
70617
70618
70619 public function rewind()
70620 {
70621 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
70622 parent::rewind();
70623
70624 return;
70625 }
70626
70627 $iterator = $this;
70628 while ($iterator instanceof \OuterIterator) {
70629 $innerIterator = $iterator->getInnerIterator();
70630
70631 if ($innerIterator instanceof RecursiveDirectoryIterator) {
70632
70633  if ($innerIterator->isRewindable()) {
70634 $innerIterator->next();
70635 $innerIterator->rewind();
70636 }
70637 } elseif ($innerIterator instanceof \FilesystemIterator) {
70638 $innerIterator->next();
70639 $innerIterator->rewind();
70640 }
70641
70642 $iterator = $innerIterator;
70643 }
70644
70645 parent::rewind();
70646 }
70647 }
70648 <?php
70649
70650
70651
70652
70653
70654
70655
70656
70657
70658
70659 namespace Symfony\Component\Finder\Iterator;
70660
70661
70662
70663
70664
70665
70666 abstract class MultiplePcreFilterIterator extends FilterIterator
70667 {
70668 protected $matchRegexps = array();
70669 protected $noMatchRegexps = array();
70670
70671
70672
70673
70674
70675
70676 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
70677 {
70678 foreach ($matchPatterns as $pattern) {
70679 $this->matchRegexps[] = $this->toRegex($pattern);
70680 }
70681
70682 foreach ($noMatchPatterns as $pattern) {
70683 $this->noMatchRegexps[] = $this->toRegex($pattern);
70684 }
70685
70686 parent::__construct($iterator);
70687 }
70688
70689
70690
70691
70692
70693
70694
70695
70696
70697
70698
70699
70700 protected function isAccepted($string)
70701 {
70702
70703  foreach ($this->noMatchRegexps as $regex) {
70704 if (preg_match($regex, $string)) {
70705 return false;
70706 }
70707 }
70708
70709
70710  if ($this->matchRegexps) {
70711 foreach ($this->matchRegexps as $regex) {
70712 if (preg_match($regex, $string)) {
70713 return true;
70714 }
70715 }
70716
70717 return false;
70718 }
70719
70720
70721  return true;
70722 }
70723
70724
70725
70726
70727
70728
70729
70730
70731 protected function isRegex($str)
70732 {
70733 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
70734 $start = substr($m[1], 0, 1);
70735 $end = substr($m[1], -1);
70736
70737 if ($start === $end) {
70738 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
70739 }
70740
70741 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
70742 if ($start === $delimiters[0] && $end === $delimiters[1]) {
70743 return true;
70744 }
70745 }
70746 }
70747
70748 return false;
70749 }
70750
70751
70752
70753
70754
70755
70756
70757
70758 abstract protected function toRegex($str);
70759 }
70760 <?php
70761
70762
70763
70764
70765
70766
70767
70768
70769
70770
70771 namespace Symfony\Component\Finder\Iterator;
70772
70773
70774
70775
70776
70777
70778
70779 class PathFilterIterator extends MultiplePcreFilterIterator
70780 {
70781
70782
70783
70784
70785
70786 public function accept()
70787 {
70788 $filename = $this->current()->getRelativePathname();
70789
70790 if ('\\' === \DIRECTORY_SEPARATOR) {
70791 $filename = str_replace('\\', '/', $filename);
70792 }
70793
70794 return $this->isAccepted($filename);
70795 }
70796
70797
70798
70799
70800
70801
70802
70803
70804
70805
70806
70807
70808
70809
70810
70811 protected function toRegex($str)
70812 {
70813 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
70814 }
70815 }
70816 <?php
70817
70818
70819
70820
70821
70822
70823
70824
70825
70826
70827 namespace Symfony\Component\Finder\Iterator;
70828
70829 use Symfony\Component\Finder\Exception\AccessDeniedException;
70830 use Symfony\Component\Finder\SplFileInfo;
70831
70832
70833
70834
70835
70836
70837 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
70838 {
70839
70840
70841
70842 private $ignoreUnreadableDirs;
70843
70844
70845
70846
70847 private $rewindable;
70848
70849
70850  private $rootPath;
70851 private $subPath;
70852 private $directorySeparator = '/';
70853
70854
70855
70856
70857
70858
70859
70860
70861 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
70862 {
70863 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
70864 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
70865 }
70866
70867 parent::__construct($path, $flags);
70868 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
70869 $this->rootPath = (string) $path;
70870 if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
70871 $this->directorySeparator = \DIRECTORY_SEPARATOR;
70872 }
70873 }
70874
70875
70876
70877
70878
70879
70880 public function current()
70881 {
70882
70883
70884 if (null === $subPathname = $this->subPath) {
70885 $subPathname = $this->subPath = (string) $this->getSubPath();
70886 }
70887 if ('' !== $subPathname) {
70888 $subPathname .= $this->directorySeparator;
70889 }
70890 $subPathname .= $this->getFilename();
70891
70892 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
70893 }
70894
70895
70896
70897
70898
70899
70900 public function getChildren()
70901 {
70902 try {
70903 $children = parent::getChildren();
70904
70905 if ($children instanceof self) {
70906
70907  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
70908
70909
70910  $children->rewindable = &$this->rewindable;
70911 $children->rootPath = $this->rootPath;
70912 }
70913
70914 return $children;
70915 } catch (\UnexpectedValueException $e) {
70916 if ($this->ignoreUnreadableDirs) {
70917
70918  return new \RecursiveArrayIterator(array());
70919 } else {
70920 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
70921 }
70922 }
70923 }
70924
70925
70926
70927
70928 public function rewind()
70929 {
70930 if (false === $this->isRewindable()) {
70931 return;
70932 }
70933
70934
70935  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
70936 parent::next();
70937 }
70938
70939 parent::rewind();
70940 }
70941
70942
70943
70944
70945
70946
70947 public function isRewindable()
70948 {
70949 if (null !== $this->rewindable) {
70950 return $this->rewindable;
70951 }
70952
70953
70954  if ('' === $this->getPath()) {
70955 return $this->rewindable = false;
70956 }
70957
70958 if (false !== $stream = @opendir($this->getPath())) {
70959 $infos = stream_get_meta_data($stream);
70960 closedir($stream);
70961
70962 if ($infos['seekable']) {
70963 return $this->rewindable = true;
70964 }
70965 }
70966
70967 return $this->rewindable = false;
70968 }
70969 }
70970 <?php
70971
70972
70973
70974
70975
70976
70977
70978
70979
70980
70981 namespace Symfony\Component\Finder\Iterator;
70982
70983 use Symfony\Component\Finder\Comparator\NumberComparator;
70984
70985
70986
70987
70988
70989
70990 class SizeRangeFilterIterator extends FilterIterator
70991 {
70992 private $comparators = array();
70993
70994
70995
70996
70997
70998 public function __construct(\Iterator $iterator, array $comparators)
70999 {
71000 $this->comparators = $comparators;
71001
71002 parent::__construct($iterator);
71003 }
71004
71005
71006
71007
71008
71009
71010 public function accept()
71011 {
71012 $fileinfo = $this->current();
71013 if (!$fileinfo->isFile()) {
71014 return true;
71015 }
71016
71017 $filesize = $fileinfo->getSize();
71018 foreach ($this->comparators as $compare) {
71019 if (!$compare->test($filesize)) {
71020 return false;
71021 }
71022 }
71023
71024 return true;
71025 }
71026 }
71027 <?php
71028
71029
71030
71031
71032
71033
71034
71035
71036
71037
71038 namespace Symfony\Component\Finder\Iterator;
71039
71040
71041
71042
71043
71044
71045 class SortableIterator implements \IteratorAggregate
71046 {
71047 const SORT_BY_NAME = 1;
71048 const SORT_BY_TYPE = 2;
71049 const SORT_BY_ACCESSED_TIME = 3;
71050 const SORT_BY_CHANGED_TIME = 4;
71051 const SORT_BY_MODIFIED_TIME = 5;
71052
71053 private $iterator;
71054 private $sort;
71055
71056
71057
71058
71059
71060
71061
71062 public function __construct(\Traversable $iterator, $sort)
71063 {
71064 $this->iterator = $iterator;
71065
71066 if (self::SORT_BY_NAME === $sort) {
71067 $this->sort = function ($a, $b) {
71068 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
71069 };
71070 } elseif (self::SORT_BY_TYPE === $sort) {
71071 $this->sort = function ($a, $b) {
71072 if ($a->isDir() && $b->isFile()) {
71073 return -1;
71074 } elseif ($a->isFile() && $b->isDir()) {
71075 return 1;
71076 }
71077
71078 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
71079 };
71080 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
71081 $this->sort = function ($a, $b) {
71082 return $a->getATime() - $b->getATime();
71083 };
71084 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
71085 $this->sort = function ($a, $b) {
71086 return $a->getCTime() - $b->getCTime();
71087 };
71088 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
71089 $this->sort = function ($a, $b) {
71090 return $a->getMTime() - $b->getMTime();
71091 };
71092 } elseif (\is_callable($sort)) {
71093 $this->sort = $sort;
71094 } else {
71095 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
71096 }
71097 }
71098
71099 public function getIterator()
71100 {
71101 $array = iterator_to_array($this->iterator, true);
71102 uasort($array, $this->sort);
71103
71104 return new \ArrayIterator($array);
71105 }
71106 }
71107 Copyright (c) 2004-2018 Fabien Potencier
71108
71109 Permission is hereby granted, free of charge, to any person obtaining a copy
71110 of this software and associated documentation files (the "Software"), to deal
71111 in the Software without restriction, including without limitation the rights
71112 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71113 copies of the Software, and to permit persons to whom the Software is furnished
71114 to do so, subject to the following conditions:
71115
71116 The above copyright notice and this permission notice shall be included in all
71117 copies or substantial portions of the Software.
71118
71119 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71120 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71121 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71122 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71123 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71124 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71125 THE SOFTWARE.
71126 <?php
71127
71128
71129
71130
71131
71132
71133
71134
71135
71136
71137 namespace Symfony\Component\Finder\Shell;
71138
71139 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71140
71141
71142
71143
71144
71145
71146 class Command
71147 {
71148 private $parent;
71149 private $bits = array();
71150 private $labels = array();
71151
71152
71153
71154
71155 private $errorHandler;
71156
71157 public function __construct(Command $parent = null)
71158 {
71159 $this->parent = $parent;
71160 }
71161
71162
71163
71164
71165
71166
71167 public function __toString()
71168 {
71169 return $this->join();
71170 }
71171
71172
71173
71174
71175
71176
71177 public static function create(Command $parent = null)
71178 {
71179 return new self($parent);
71180 }
71181
71182
71183
71184
71185
71186
71187
71188
71189 public static function escape($input)
71190 {
71191 return escapeshellcmd($input);
71192 }
71193
71194
71195
71196
71197
71198
71199
71200
71201 public static function quote($input)
71202 {
71203 return escapeshellarg($input);
71204 }
71205
71206
71207
71208
71209
71210
71211
71212
71213 public function add($bit)
71214 {
71215 $this->bits[] = $bit;
71216
71217 return $this;
71218 }
71219
71220
71221
71222
71223
71224
71225
71226
71227 public function top($bit)
71228 {
71229 array_unshift($this->bits, $bit);
71230
71231 foreach ($this->labels as $label => $index) {
71232 ++$this->labels[$label];
71233 }
71234
71235 return $this;
71236 }
71237
71238
71239
71240
71241
71242
71243
71244
71245 public function arg($arg)
71246 {
71247 $this->bits[] = self::quote($arg);
71248
71249 return $this;
71250 }
71251
71252
71253
71254
71255
71256
71257
71258
71259 public function cmd($esc)
71260 {
71261 $this->bits[] = self::escape($esc);
71262
71263 return $this;
71264 }
71265
71266
71267
71268
71269
71270
71271
71272
71273
71274
71275 public function ins($label)
71276 {
71277 if (isset($this->labels[$label])) {
71278 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
71279 }
71280
71281 $this->bits[] = self::create($this);
71282 $this->labels[$label] = \count($this->bits) - 1;
71283
71284 return $this->bits[$this->labels[$label]];
71285 }
71286
71287
71288
71289
71290
71291
71292
71293
71294
71295
71296 public function get($label)
71297 {
71298 if (!isset($this->labels[$label])) {
71299 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
71300 }
71301
71302 return $this->bits[$this->labels[$label]];
71303 }
71304
71305
71306
71307
71308
71309
71310
71311
71312 public function end()
71313 {
71314 if (null === $this->parent) {
71315 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
71316 }
71317
71318 return $this->parent;
71319 }
71320
71321
71322
71323
71324
71325
71326 public function length()
71327 {
71328 return \count($this->bits);
71329 }
71330
71331
71332
71333
71334 public function setErrorHandler(\Closure $errorHandler)
71335 {
71336 $this->errorHandler = $errorHandler;
71337
71338 return $this;
71339 }
71340
71341
71342
71343
71344 public function getErrorHandler()
71345 {
71346 return $this->errorHandler;
71347 }
71348
71349
71350
71351
71352
71353
71354
71355
71356 public function execute()
71357 {
71358 if (null === $errorHandler = $this->errorHandler) {
71359 exec($this->join(), $output);
71360 } else {
71361 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
71362 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
71363
71364 if ($error = stream_get_contents($pipes[2])) {
71365 $errorHandler($error);
71366 }
71367
71368 proc_close($process);
71369 }
71370
71371 return $output ?: array();
71372 }
71373
71374
71375
71376
71377
71378
71379 public function join()
71380 {
71381 return implode(' ', array_filter(
71382 array_map(function ($bit) {
71383 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
71384 }, $this->bits),
71385 function ($bit) { return null !== $bit; }
71386 ));
71387 }
71388
71389
71390
71391
71392
71393
71394
71395
71396
71397 public function addAtIndex($bit, $index)
71398 {
71399 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
71400
71401 return $this;
71402 }
71403 }
71404 <?php
71405
71406
71407
71408
71409
71410
71411
71412
71413
71414
71415 namespace Symfony\Component\Finder\Shell;
71416
71417 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71418
71419
71420
71421
71422
71423
71424 class Shell
71425 {
71426 const TYPE_UNIX = 1;
71427 const TYPE_DARWIN = 2;
71428 const TYPE_CYGWIN = 3;
71429 const TYPE_WINDOWS = 4;
71430 const TYPE_BSD = 5;
71431
71432
71433
71434
71435 private $type;
71436
71437
71438
71439
71440
71441
71442 public function getType()
71443 {
71444 if (null === $this->type) {
71445 $this->type = $this->guessType();
71446 }
71447
71448 return $this->type;
71449 }
71450
71451
71452
71453
71454
71455
71456
71457
71458 public function testCommand($command)
71459 {
71460 if (!\function_exists('exec')) {
71461 return false;
71462 }
71463
71464
71465  $testCommand = 'which ';
71466 if (self::TYPE_WINDOWS === $this->type) {
71467 $testCommand = 'where ';
71468 }
71469
71470 $command = escapeshellcmd($command);
71471
71472 exec($testCommand.$command, $output, $code);
71473
71474 return 0 === $code && \count($output) > 0;
71475 }
71476
71477
71478
71479
71480
71481
71482 private function guessType()
71483 {
71484 $os = strtolower(PHP_OS);
71485
71486 if (false !== strpos($os, 'cygwin')) {
71487 return self::TYPE_CYGWIN;
71488 }
71489
71490 if (false !== strpos($os, 'darwin')) {
71491 return self::TYPE_DARWIN;
71492 }
71493
71494 if (false !== strpos($os, 'bsd')) {
71495 return self::TYPE_BSD;
71496 }
71497
71498 if (0 === strpos($os, 'win')) {
71499 return self::TYPE_WINDOWS;
71500 }
71501
71502 return self::TYPE_UNIX;
71503 }
71504 }
71505 <?php
71506
71507
71508
71509
71510
71511
71512
71513
71514
71515
71516 namespace Symfony\Component\Finder;
71517
71518
71519
71520
71521
71522
71523 class SplFileInfo extends \SplFileInfo
71524 {
71525 private $relativePath;
71526 private $relativePathname;
71527
71528
71529
71530
71531
71532
71533 public function __construct($file, $relativePath, $relativePathname)
71534 {
71535 parent::__construct($file);
71536 $this->relativePath = $relativePath;
71537 $this->relativePathname = $relativePathname;
71538 }
71539
71540
71541
71542
71543
71544
71545
71546
71547 public function getRelativePath()
71548 {
71549 return $this->relativePath;
71550 }
71551
71552
71553
71554
71555
71556
71557
71558
71559 public function getRelativePathname()
71560 {
71561 return $this->relativePathname;
71562 }
71563
71564
71565
71566
71567
71568
71569
71570
71571 public function getContents()
71572 {
71573 set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
71574 $content = file_get_contents($this->getPathname());
71575 restore_error_handler();
71576 if (false === $content) {
71577 throw new \RuntimeException($error);
71578 }
71579
71580 return $content;
71581 }
71582 }
71583 <?php
71584
71585
71586
71587
71588
71589
71590
71591
71592
71593
71594 namespace Symfony\Polyfill\Ctype;
71595
71596
71597
71598
71599
71600
71601
71602
71603 final class Ctype
71604 {
71605
71606
71607
71608
71609
71610
71611
71612
71613
71614 public static function ctype_alnum($text)
71615 {
71616 $text = self::convert_int_to_char_for_ctype($text);
71617
71618 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
71619 }
71620
71621
71622
71623
71624
71625
71626
71627
71628
71629
71630 public static function ctype_alpha($text)
71631 {
71632 $text = self::convert_int_to_char_for_ctype($text);
71633
71634 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
71635 }
71636
71637
71638
71639
71640
71641
71642
71643
71644
71645
71646 public static function ctype_cntrl($text)
71647 {
71648 $text = self::convert_int_to_char_for_ctype($text);
71649
71650 return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
71651 }
71652
71653
71654
71655
71656
71657
71658
71659
71660
71661
71662 public static function ctype_digit($text)
71663 {
71664 $text = self::convert_int_to_char_for_ctype($text);
71665
71666 return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
71667 }
71668
71669
71670
71671
71672
71673
71674
71675
71676
71677
71678 public static function ctype_graph($text)
71679 {
71680 $text = self::convert_int_to_char_for_ctype($text);
71681
71682 return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
71683 }
71684
71685
71686
71687
71688
71689
71690
71691
71692
71693
71694 public static function ctype_lower($text)
71695 {
71696 $text = self::convert_int_to_char_for_ctype($text);
71697
71698 return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
71699 }
71700
71701
71702
71703
71704
71705
71706
71707
71708
71709
71710 public static function ctype_print($text)
71711 {
71712 $text = self::convert_int_to_char_for_ctype($text);
71713
71714 return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
71715 }
71716
71717
71718
71719
71720
71721
71722
71723
71724
71725
71726 public static function ctype_punct($text)
71727 {
71728 $text = self::convert_int_to_char_for_ctype($text);
71729
71730 return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
71731 }
71732
71733
71734
71735
71736
71737
71738
71739
71740
71741
71742 public static function ctype_space($text)
71743 {
71744 $text = self::convert_int_to_char_for_ctype($text);
71745
71746 return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
71747 }
71748
71749
71750
71751
71752
71753
71754
71755
71756
71757
71758 public static function ctype_upper($text)
71759 {
71760 $text = self::convert_int_to_char_for_ctype($text);
71761
71762 return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
71763 }
71764
71765
71766
71767
71768
71769
71770
71771
71772
71773
71774 public static function ctype_xdigit($text)
71775 {
71776 $text = self::convert_int_to_char_for_ctype($text);
71777
71778 return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
71779 }
71780
71781
71782
71783
71784
71785
71786
71787
71788
71789
71790
71791
71792
71793 private static function convert_int_to_char_for_ctype($int)
71794 {
71795 if (!\is_int($int)) {
71796 return $int;
71797 }
71798
71799 if ($int < -128 || $int > 255) {
71800 return (string) $int;
71801 }
71802
71803 if ($int < 0) {
71804 $int += 256;
71805 }
71806
71807 return \chr($int);
71808 }
71809 }
71810 Copyright (c) 2018-2019 Fabien Potencier
71811
71812 Permission is hereby granted, free of charge, to any person obtaining a copy
71813 of this software and associated documentation files (the "Software"), to deal
71814 in the Software without restriction, including without limitation the rights
71815 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71816 copies of the Software, and to permit persons to whom the Software is furnished
71817 to do so, subject to the following conditions:
71818
71819 The above copyright notice and this permission notice shall be included in all
71820 copies or substantial portions of the Software.
71821
71822 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71823 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71824 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71825 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71826 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71827 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71828 THE SOFTWARE.
71829 <?php
71830
71831
71832
71833
71834
71835
71836
71837
71838
71839
71840 use Symfony\Polyfill\Ctype as p;
71841
71842 if (!function_exists('ctype_alnum')) {
71843 function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
71844 function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
71845 function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
71846 function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
71847 function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
71848 function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
71849 function ctype_print($text) { return p\Ctype::ctype_print($text); }
71850 function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
71851 function ctype_space($text) { return p\Ctype::ctype_space($text); }
71852 function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
71853 function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
71854 }
71855 Copyright (c) 2015-2019 Fabien Potencier
71856
71857 Permission is hereby granted, free of charge, to any person obtaining a copy
71858 of this software and associated documentation files (the "Software"), to deal
71859 in the Software without restriction, including without limitation the rights
71860 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71861 copies of the Software, and to permit persons to whom the Software is furnished
71862 to do so, subject to the following conditions:
71863
71864 The above copyright notice and this permission notice shall be included in all
71865 copies or substantial portions of the Software.
71866
71867 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71868 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71869 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71870 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71871 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71872 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71873 THE SOFTWARE.
71874 <?php
71875
71876
71877
71878
71879
71880
71881
71882
71883
71884
71885 namespace Symfony\Polyfill\Mbstring;
71886
71887
71888
71889
71890
71891
71892
71893
71894
71895
71896
71897
71898
71899
71900
71901
71902
71903
71904
71905
71906
71907
71908
71909
71910
71911
71912
71913
71914
71915
71916
71917
71918
71919
71920
71921
71922
71923
71924
71925
71926
71927
71928
71929
71930
71931
71932
71933
71934
71935
71936
71937
71938
71939
71940
71941 final class Mbstring
71942 {
71943 const MB_CASE_FOLD = PHP_INT_MAX;
71944
71945 private static $encodingList = array('ASCII', 'UTF-8');
71946 private static $language = 'neutral';
71947 private static $internalEncoding = 'UTF-8';
71948 private static $caseFold = array(
71949 array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"),
71950 array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'),
71951 );
71952
71953 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
71954 {
71955 if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
71956 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
71957 } else {
71958 $fromEncoding = self::getEncoding($fromEncoding);
71959 }
71960
71961 $toEncoding = self::getEncoding($toEncoding);
71962
71963 if ('BASE64' === $fromEncoding) {
71964 $s = base64_decode($s);
71965 $fromEncoding = $toEncoding;
71966 }
71967
71968 if ('BASE64' === $toEncoding) {
71969 return base64_encode($s);
71970 }
71971
71972 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
71973 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
71974 $fromEncoding = 'Windows-1252';
71975 }
71976 if ('UTF-8' !== $fromEncoding) {
71977 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
71978 }
71979
71980 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
71981 }
71982
71983 if ('HTML-ENTITIES' === $fromEncoding) {
71984 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
71985 $fromEncoding = 'UTF-8';
71986 }
71987
71988 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
71989 }
71990
71991 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
71992 {
71993 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
71994
71995 $ok = true;
71996 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
71997 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
71998 $ok = false;
71999 }
72000 });
72001
72002 return $ok ? $fromEncoding : false;
72003 }
72004
72005 public static function mb_decode_mimeheader($s)
72006 {
72007 return iconv_mime_decode($s, 2, self::$internalEncoding);
72008 }
72009
72010 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
72011 {
72012 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
72013 }
72014
72015 public static function mb_decode_numericentity($s, $convmap, $encoding = null)
72016 {
72017 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
72018 trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
72019
72020 return null;
72021 }
72022
72023 if (!\is_array($convmap) || !$convmap) {
72024 return false;
72025 }
72026
72027 if (null !== $encoding && !\is_scalar($encoding)) {
72028 trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
72029
72030 return ''; 
72031  }
72032
72033 $s = (string) $s;
72034 if ('' === $s) {
72035 return '';
72036 }
72037
72038 $encoding = self::getEncoding($encoding);
72039
72040 if ('UTF-8' === $encoding) {
72041 $encoding = null;
72042 if (!preg_match('//u', $s)) {
72043 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
72044 }
72045 } else {
72046 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
72047 }
72048
72049 $cnt = floor(\count($convmap) / 4) * 4;
72050
72051 for ($i = 0; $i < $cnt; $i += 4) {
72052
72053  $convmap[$i] += $convmap[$i + 2];
72054 $convmap[$i + 1] += $convmap[$i + 2];
72055 }
72056
72057 $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
72058 $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
72059 for ($i = 0; $i < $cnt; $i += 4) {
72060 if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
72061 return Mbstring::mb_chr($c - $convmap[$i + 2]);
72062 }
72063 }
72064
72065 return $m[0];
72066 }, $s);
72067
72068 if (null === $encoding) {
72069 return $s;
72070 }
72071
72072 return iconv('UTF-8', $encoding.'//IGNORE', $s);
72073 }
72074
72075 public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
72076 {
72077 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
72078 trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
72079
72080 return null;
72081 }
72082
72083 if (!\is_array($convmap) || !$convmap) {
72084 return false;
72085 }
72086
72087 if (null !== $encoding && !\is_scalar($encoding)) {
72088 trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
72089
72090 return null; 
72091  }
72092
72093 if (null !== $is_hex && !\is_scalar($is_hex)) {
72094 trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING);
72095
72096 return null;
72097 }
72098
72099 $s = (string) $s;
72100 if ('' === $s) {
72101 return '';
72102 }
72103
72104 $encoding = self::getEncoding($encoding);
72105
72106 if ('UTF-8' === $encoding) {
72107 $encoding = null;
72108 if (!preg_match('//u', $s)) {
72109 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
72110 }
72111 } else {
72112 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
72113 }
72114
72115 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
72116
72117 $cnt = floor(\count($convmap) / 4) * 4;
72118 $i = 0;
72119 $len = \strlen($s);
72120 $result = '';
72121
72122 while ($i < $len) {
72123 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
72124 $uchr = substr($s, $i, $ulen);
72125 $i += $ulen;
72126 $c = self::mb_ord($uchr);
72127
72128 for ($j = 0; $j < $cnt; $j += 4) {
72129 if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
72130 $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
72131 $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
72132 continue 2;
72133 }
72134 }
72135 $result .= $uchr;
72136 }
72137
72138 if (null === $encoding) {
72139 return $result;
72140 }
72141
72142 return iconv('UTF-8', $encoding.'//IGNORE', $result);
72143 }
72144
72145 public static function mb_convert_case($s, $mode, $encoding = null)
72146 {
72147 $s = (string) $s;
72148 if ('' === $s) {
72149 return '';
72150 }
72151
72152 $encoding = self::getEncoding($encoding);
72153
72154 if ('UTF-8' === $encoding) {
72155 $encoding = null;
72156 if (!preg_match('//u', $s)) {
72157 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
72158 }
72159 } else {
72160 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
72161 }
72162
72163 if (MB_CASE_TITLE == $mode) {
72164 static $titleRegexp = null;
72165 if (null === $titleRegexp) {
72166 $titleRegexp = self::getData('titleCaseRegexp');
72167 }
72168 $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s);
72169 } else {
72170 if (MB_CASE_UPPER == $mode) {
72171 static $upper = null;
72172 if (null === $upper) {
72173 $upper = self::getData('upperCase');
72174 }
72175 $map = $upper;
72176 } else {
72177 if (self::MB_CASE_FOLD === $mode) {
72178 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
72179 }
72180
72181 static $lower = null;
72182 if (null === $lower) {
72183 $lower = self::getData('lowerCase');
72184 }
72185 $map = $lower;
72186 }
72187
72188 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
72189
72190 $i = 0;
72191 $len = \strlen($s);
72192
72193 while ($i < $len) {
72194 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
72195 $uchr = substr($s, $i, $ulen);
72196 $i += $ulen;
72197
72198 if (isset($map[$uchr])) {
72199 $uchr = $map[$uchr];
72200 $nlen = \strlen($uchr);
72201
72202 if ($nlen == $ulen) {
72203 $nlen = $i;
72204 do {
72205 $s[--$nlen] = $uchr[--$ulen];
72206 } while ($ulen);
72207 } else {
72208 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
72209 $len += $nlen - $ulen;
72210 $i += $nlen - $ulen;
72211 }
72212 }
72213 }
72214 }
72215
72216 if (null === $encoding) {
72217 return $s;
72218 }
72219
72220 return iconv('UTF-8', $encoding.'//IGNORE', $s);
72221 }
72222
72223 public static function mb_internal_encoding($encoding = null)
72224 {
72225 if (null === $encoding) {
72226 return self::$internalEncoding;
72227 }
72228
72229 $encoding = self::getEncoding($encoding);
72230
72231 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
72232 self::$internalEncoding = $encoding;
72233
72234 return true;
72235 }
72236
72237 return false;
72238 }
72239
72240 public static function mb_language($lang = null)
72241 {
72242 if (null === $lang) {
72243 return self::$language;
72244 }
72245
72246 switch ($lang = strtolower($lang)) {
72247 case 'uni':
72248 case 'neutral':
72249 self::$language = $lang;
72250
72251 return true;
72252 }
72253
72254 return false;
72255 }
72256
72257 public static function mb_list_encodings()
72258 {
72259 return array('UTF-8');
72260 }
72261
72262 public static function mb_encoding_aliases($encoding)
72263 {
72264 switch (strtoupper($encoding)) {
72265 case 'UTF8':
72266 case 'UTF-8':
72267 return array('utf8');
72268 }
72269
72270 return false;
72271 }
72272
72273 public static function mb_check_encoding($var = null, $encoding = null)
72274 {
72275 if (null === $encoding) {
72276 if (null === $var) {
72277 return false;
72278 }
72279 $encoding = self::$internalEncoding;
72280 }
72281
72282 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
72283 }
72284
72285 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
72286 {
72287 if (null === $encodingList) {
72288 $encodingList = self::$encodingList;
72289 } else {
72290 if (!\is_array($encodingList)) {
72291 $encodingList = array_map('trim', explode(',', $encodingList));
72292 }
72293 $encodingList = array_map('strtoupper', $encodingList);
72294 }
72295
72296 foreach ($encodingList as $enc) {
72297 switch ($enc) {
72298 case 'ASCII':
72299 if (!preg_match('/[\x80-\xFF]/', $str)) {
72300 return $enc;
72301 }
72302 break;
72303
72304 case 'UTF8':
72305 case 'UTF-8':
72306 if (preg_match('//u', $str)) {
72307 return 'UTF-8';
72308 }
72309 break;
72310
72311 default:
72312 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
72313 return $enc;
72314 }
72315 }
72316 }
72317
72318 return false;
72319 }
72320
72321 public static function mb_detect_order($encodingList = null)
72322 {
72323 if (null === $encodingList) {
72324 return self::$encodingList;
72325 }
72326
72327 if (!\is_array($encodingList)) {
72328 $encodingList = array_map('trim', explode(',', $encodingList));
72329 }
72330 $encodingList = array_map('strtoupper', $encodingList);
72331
72332 foreach ($encodingList as $enc) {
72333 switch ($enc) {
72334 default:
72335 if (strncmp($enc, 'ISO-8859-', 9)) {
72336 return false;
72337 }
72338
72339  case 'ASCII':
72340 case 'UTF8':
72341 case 'UTF-8':
72342 }
72343 }
72344
72345 self::$encodingList = $encodingList;
72346
72347 return true;
72348 }
72349
72350 public static function mb_strlen($s, $encoding = null)
72351 {
72352 $encoding = self::getEncoding($encoding);
72353 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72354 return \strlen($s);
72355 }
72356
72357 return @iconv_strlen($s, $encoding);
72358 }
72359
72360 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
72361 {
72362 $encoding = self::getEncoding($encoding);
72363 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72364 return strpos($haystack, $needle, $offset);
72365 }
72366
72367 $needle = (string) $needle;
72368 if ('' === $needle) {
72369 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
72370
72371 return false;
72372 }
72373
72374 return iconv_strpos($haystack, $needle, $offset, $encoding);
72375 }
72376
72377 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
72378 {
72379 $encoding = self::getEncoding($encoding);
72380 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72381 return strrpos($haystack, $needle, $offset);
72382 }
72383
72384 if ($offset != (int) $offset) {
72385 $offset = 0;
72386 } elseif ($offset = (int) $offset) {
72387 if ($offset < 0) {
72388 if (0 > $offset += self::mb_strlen($needle)) {
72389 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
72390 }
72391 $offset = 0;
72392 } else {
72393 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
72394 }
72395 }
72396
72397 $pos = iconv_strrpos($haystack, $needle, $encoding);
72398
72399 return false !== $pos ? $offset + $pos : false;
72400 }
72401
72402 public static function mb_str_split($string, $split_length = 1, $encoding = null)
72403 {
72404 if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
72405 trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING);
72406
72407 return null;
72408 }
72409
72410 if (1 > $split_length = (int) $split_length) {
72411 trigger_error('The length of each segment must be greater than zero', E_USER_WARNING);
72412
72413 return false;
72414 }
72415
72416 if (null === $encoding) {
72417 $encoding = mb_internal_encoding();
72418 }
72419
72420 if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
72421 return preg_split("/(.{{$split_length}})/u", $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
72422 }
72423
72424 $result = array();
72425 $length = mb_strlen($string, $encoding);
72426
72427 for ($i = 0; $i < $length; $i += $split_length) {
72428 $result[] = mb_substr($string, $i, $split_length, $encoding);
72429 }
72430
72431 return $result;
72432 }
72433
72434 public static function mb_strtolower($s, $encoding = null)
72435 {
72436 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
72437 }
72438
72439 public static function mb_strtoupper($s, $encoding = null)
72440 {
72441 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
72442 }
72443
72444 public static function mb_substitute_character($c = null)
72445 {
72446 if (0 === strcasecmp($c, 'none')) {
72447 return true;
72448 }
72449
72450 return null !== $c ? false : 'none';
72451 }
72452
72453 public static function mb_substr($s, $start, $length = null, $encoding = null)
72454 {
72455 $encoding = self::getEncoding($encoding);
72456 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72457 return (string) substr($s, $start, null === $length ? 2147483647 : $length);
72458 }
72459
72460 if ($start < 0) {
72461 $start = iconv_strlen($s, $encoding) + $start;
72462 if ($start < 0) {
72463 $start = 0;
72464 }
72465 }
72466
72467 if (null === $length) {
72468 $length = 2147483647;
72469 } elseif ($length < 0) {
72470 $length = iconv_strlen($s, $encoding) + $length - $start;
72471 if ($length < 0) {
72472 return '';
72473 }
72474 }
72475
72476 return (string) iconv_substr($s, $start, $length, $encoding);
72477 }
72478
72479 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
72480 {
72481 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
72482 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
72483
72484 return self::mb_strpos($haystack, $needle, $offset, $encoding);
72485 }
72486
72487 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
72488 {
72489 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
72490
72491 return self::getSubpart($pos, $part, $haystack, $encoding);
72492 }
72493
72494 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
72495 {
72496 $encoding = self::getEncoding($encoding);
72497 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72498 return strrchr($haystack, $needle, $part);
72499 }
72500 $needle = self::mb_substr($needle, 0, 1, $encoding);
72501 $pos = iconv_strrpos($haystack, $needle, $encoding);
72502
72503 return self::getSubpart($pos, $part, $haystack, $encoding);
72504 }
72505
72506 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
72507 {
72508 $needle = self::mb_substr($needle, 0, 1, $encoding);
72509 $pos = self::mb_strripos($haystack, $needle, $encoding);
72510
72511 return self::getSubpart($pos, $part, $haystack, $encoding);
72512 }
72513
72514 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
72515 {
72516 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
72517 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
72518
72519 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
72520 }
72521
72522 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
72523 {
72524 $pos = strpos($haystack, $needle);
72525 if (false === $pos) {
72526 return false;
72527 }
72528 if ($part) {
72529 return substr($haystack, 0, $pos);
72530 }
72531
72532 return substr($haystack, $pos);
72533 }
72534
72535 public static function mb_get_info($type = 'all')
72536 {
72537 $info = array(
72538 'internal_encoding' => self::$internalEncoding,
72539 'http_output' => 'pass',
72540 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
72541 'func_overload' => 0,
72542 'func_overload_list' => 'no overload',
72543 'mail_charset' => 'UTF-8',
72544 'mail_header_encoding' => 'BASE64',
72545 'mail_body_encoding' => 'BASE64',
72546 'illegal_chars' => 0,
72547 'encoding_translation' => 'Off',
72548 'language' => self::$language,
72549 'detect_order' => self::$encodingList,
72550 'substitute_character' => 'none',
72551 'strict_detection' => 'Off',
72552 );
72553
72554 if ('all' === $type) {
72555 return $info;
72556 }
72557 if (isset($info[$type])) {
72558 return $info[$type];
72559 }
72560
72561 return false;
72562 }
72563
72564 public static function mb_http_input($type = '')
72565 {
72566 return false;
72567 }
72568
72569 public static function mb_http_output($encoding = null)
72570 {
72571 return null !== $encoding ? 'pass' === $encoding : 'pass';
72572 }
72573
72574 public static function mb_strwidth($s, $encoding = null)
72575 {
72576 $encoding = self::getEncoding($encoding);
72577
72578 if ('UTF-8' !== $encoding) {
72579 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
72580 }
72581
72582 $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
72583
72584 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
72585 }
72586
72587 public static function mb_substr_count($haystack, $needle, $encoding = null)
72588 {
72589 return substr_count($haystack, $needle);
72590 }
72591
72592 public static function mb_output_handler($contents, $status)
72593 {
72594 return $contents;
72595 }
72596
72597 public static function mb_chr($code, $encoding = null)
72598 {
72599 if (0x80 > $code %= 0x200000) {
72600 $s = \chr($code);
72601 } elseif (0x800 > $code) {
72602 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
72603 } elseif (0x10000 > $code) {
72604 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
72605 } else {
72606 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
72607 }
72608
72609 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
72610 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
72611 }
72612
72613 return $s;
72614 }
72615
72616 public static function mb_ord($s, $encoding = null)
72617 {
72618 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
72619 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
72620 }
72621
72622 if (1 === \strlen($s)) {
72623 return \ord($s);
72624 }
72625
72626 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
72627 if (0xF0 <= $code) {
72628 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
72629 }
72630 if (0xE0 <= $code) {
72631 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
72632 }
72633 if (0xC0 <= $code) {
72634 return (($code - 0xC0) << 6) + $s[2] - 0x80;
72635 }
72636
72637 return $code;
72638 }
72639
72640 private static function getSubpart($pos, $part, $haystack, $encoding)
72641 {
72642 if (false === $pos) {
72643 return false;
72644 }
72645 if ($part) {
72646 return self::mb_substr($haystack, 0, $pos, $encoding);
72647 }
72648
72649 return self::mb_substr($haystack, $pos, null, $encoding);
72650 }
72651
72652 private static function html_encoding_callback(array $m)
72653 {
72654 $i = 1;
72655 $entities = '';
72656 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
72657
72658 while (isset($m[$i])) {
72659 if (0x80 > $m[$i]) {
72660 $entities .= \chr($m[$i++]);
72661 continue;
72662 }
72663 if (0xF0 <= $m[$i]) {
72664 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
72665 } elseif (0xE0 <= $m[$i]) {
72666 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
72667 } else {
72668 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
72669 }
72670
72671 $entities .= '&#'.$c.';';
72672 }
72673
72674 return $entities;
72675 }
72676
72677 private static function title_case(array $s)
72678 {
72679 return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8');
72680 }
72681
72682 private static function getData($file)
72683 {
72684 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
72685 return require $file;
72686 }
72687
72688 return false;
72689 }
72690
72691 private static function getEncoding($encoding)
72692 {
72693 if (null === $encoding) {
72694 return self::$internalEncoding;
72695 }
72696
72697 if ('UTF-8' === $encoding) {
72698 return 'UTF-8';
72699 }
72700
72701 $encoding = strtoupper($encoding);
72702
72703 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
72704 return 'CP850';
72705 }
72706
72707 if ('UTF8' === $encoding) {
72708 return 'UTF-8';
72709 }
72710
72711 return $encoding;
72712 }
72713 }
72714 <?php
72715
72716 return array(
72717 'A' => 'a',
72718 'B' => 'b',
72719 'C' => 'c',
72720 'D' => 'd',
72721 'E' => 'e',
72722 'F' => 'f',
72723 'G' => 'g',
72724 'H' => 'h',
72725 'I' => 'i',
72726 'J' => 'j',
72727 'K' => 'k',
72728 'L' => 'l',
72729 'M' => 'm',
72730 'N' => 'n',
72731 'O' => 'o',
72732 'P' => 'p',
72733 'Q' => 'q',
72734 'R' => 'r',
72735 'S' => 's',
72736 'T' => 't',
72737 'U' => 'u',
72738 'V' => 'v',
72739 'W' => 'w',
72740 'X' => 'x',
72741 'Y' => 'y',
72742 'Z' => 'z',
72743 'À' => 'à',
72744 'Á' => 'á',
72745 'Â' => 'â',
72746 'Ã' => 'ã',
72747 'Ä' => 'ä',
72748 'Å' => 'å',
72749 'Æ' => 'æ',
72750 'Ç' => 'ç',
72751 'È' => 'è',
72752 'É' => 'é',
72753 'Ê' => 'ê',
72754 'Ë' => 'ë',
72755 'Ì' => 'ì',
72756 'Í' => 'í',
72757 'Î' => 'î',
72758 'Ï' => 'ï',
72759 'Ð' => 'ð',
72760 'Ñ' => 'ñ',
72761 'Ò' => 'ò',
72762 'Ó' => 'ó',
72763 'Ô' => 'ô',
72764 'Õ' => 'õ',
72765 'Ö' => 'ö',
72766 'Ø' => 'ø',
72767 'Ù' => 'ù',
72768 'Ú' => 'ú',
72769 'Û' => 'û',
72770 'Ü' => 'ü',
72771 'Ý' => 'ý',
72772 'Þ' => 'þ',
72773 'Ā' => 'ā',
72774 'Ă' => 'ă',
72775 'Ą' => 'ą',
72776 'Ć' => 'ć',
72777 'Ĉ' => 'ĉ',
72778 'Ċ' => 'ċ',
72779 'Č' => 'č',
72780 'Ď' => 'ď',
72781 'Đ' => 'đ',
72782 'Ē' => 'ē',
72783 'Ĕ' => 'ĕ',
72784 'Ė' => 'ė',
72785 'Ę' => 'ę',
72786 'Ě' => 'ě',
72787 'Ĝ' => 'ĝ',
72788 'Ğ' => 'ğ',
72789 'Ġ' => 'ġ',
72790 'Ģ' => 'ģ',
72791 'Ĥ' => 'ĥ',
72792 'Ħ' => 'ħ',
72793 'Ĩ' => 'ĩ',
72794 'Ī' => 'ī',
72795 'Ĭ' => 'ĭ',
72796 'Į' => 'į',
72797 'İ' => 'i',
72798 'IJ' => 'ij',
72799 'Ĵ' => 'ĵ',
72800 'Ķ' => 'ķ',
72801 'Ĺ' => 'ĺ',
72802 'Ļ' => 'ļ',
72803 'Ľ' => 'ľ',
72804 'Ŀ' => 'ŀ',
72805 'Ł' => 'ł',
72806 'Ń' => 'ń',
72807 'Ņ' => 'ņ',
72808 'Ň' => 'ň',
72809 'Ŋ' => 'ŋ',
72810 'Ō' => 'ō',
72811 'Ŏ' => 'ŏ',
72812 'Ő' => 'ő',
72813 'Œ' => 'œ',
72814 'Ŕ' => 'ŕ',
72815 'Ŗ' => 'ŗ',
72816 'Ř' => 'ř',
72817 'Ś' => 'ś',
72818 'Ŝ' => 'ŝ',
72819 'Ş' => 'ş',
72820 'Š' => 'š',
72821 'Ţ' => 'ţ',
72822 'Ť' => 'ť',
72823 'Ŧ' => 'ŧ',
72824 'Ũ' => 'ũ',
72825 'Ū' => 'ū',
72826 'Ŭ' => 'ŭ',
72827 'Ů' => 'ů',
72828 'Ű' => 'ű',
72829 'Ų' => 'ų',
72830 'Ŵ' => 'ŵ',
72831 'Ŷ' => 'ŷ',
72832 'Ÿ' => 'ÿ',
72833 'Ź' => 'ź',
72834 'Ż' => 'ż',
72835 'Ž' => 'ž',
72836 'Ɓ' => 'ɓ',
72837 'Ƃ' => 'ƃ',
72838 'Ƅ' => 'ƅ',
72839 'Ɔ' => 'ɔ',
72840 'Ƈ' => 'ƈ',
72841 'Ɖ' => 'ɖ',
72842 'Ɗ' => 'ɗ',
72843 'Ƌ' => 'ƌ',
72844 'Ǝ' => 'ǝ',
72845 'Ə' => 'ə',
72846 'Ɛ' => 'ɛ',
72847 'Ƒ' => 'ƒ',
72848 'Ɠ' => 'ɠ',
72849 'Ɣ' => 'ɣ',
72850 'Ɩ' => 'ɩ',
72851 'Ɨ' => 'ɨ',
72852 'Ƙ' => 'ƙ',
72853 'Ɯ' => 'ɯ',
72854 'Ɲ' => 'ɲ',
72855 'Ɵ' => 'ɵ',
72856 'Ơ' => 'ơ',
72857 'Ƣ' => 'ƣ',
72858 'Ƥ' => 'ƥ',
72859 'Ʀ' => 'ʀ',
72860 'Ƨ' => 'ƨ',
72861 'Ʃ' => 'ʃ',
72862 'Ƭ' => 'ƭ',
72863 'Ʈ' => 'ʈ',
72864 'Ư' => 'ư',
72865 'Ʊ' => 'ʊ',
72866 'Ʋ' => 'ʋ',
72867 'Ƴ' => 'ƴ',
72868 'Ƶ' => 'ƶ',
72869 'Ʒ' => 'ʒ',
72870 'Ƹ' => 'ƹ',
72871 'Ƽ' => 'ƽ',
72872 'DŽ' => 'dž',
72873 'Dž' => 'dž',
72874 'LJ' => 'lj',
72875 'Lj' => 'lj',
72876 'NJ' => 'nj',
72877 'Nj' => 'nj',
72878 'Ǎ' => 'ǎ',
72879 'Ǐ' => 'ǐ',
72880 'Ǒ' => 'ǒ',
72881 'Ǔ' => 'ǔ',
72882 'Ǖ' => 'ǖ',
72883 'Ǘ' => 'ǘ',
72884 'Ǚ' => 'ǚ',
72885 'Ǜ' => 'ǜ',
72886 'Ǟ' => 'ǟ',
72887 'Ǡ' => 'ǡ',
72888 'Ǣ' => 'ǣ',
72889 'Ǥ' => 'ǥ',
72890 'Ǧ' => 'ǧ',
72891 'Ǩ' => 'ǩ',
72892 'Ǫ' => 'ǫ',
72893 'Ǭ' => 'ǭ',
72894 'Ǯ' => 'ǯ',
72895 'DZ' => 'dz',
72896 'Dz' => 'dz',
72897 'Ǵ' => 'ǵ',
72898 'Ƕ' => 'ƕ',
72899 'Ƿ' => 'ƿ',
72900 'Ǹ' => 'ǹ',
72901 'Ǻ' => 'ǻ',
72902 'Ǽ' => 'ǽ',
72903 'Ǿ' => 'ǿ',
72904 'Ȁ' => 'ȁ',
72905 'Ȃ' => 'ȃ',
72906 'Ȅ' => 'ȅ',
72907 'Ȇ' => 'ȇ',
72908 'Ȉ' => 'ȉ',
72909 'Ȋ' => 'ȋ',
72910 'Ȍ' => 'ȍ',
72911 'Ȏ' => 'ȏ',
72912 'Ȑ' => 'ȑ',
72913 'Ȓ' => 'ȓ',
72914 'Ȕ' => 'ȕ',
72915 'Ȗ' => 'ȗ',
72916 'Ș' => 'ș',
72917 'Ț' => 'ț',
72918 'Ȝ' => 'ȝ',
72919 'Ȟ' => 'ȟ',
72920 'Ƞ' => 'ƞ',
72921 'Ȣ' => 'ȣ',
72922 'Ȥ' => 'ȥ',
72923 'Ȧ' => 'ȧ',
72924 'Ȩ' => 'ȩ',
72925 'Ȫ' => 'ȫ',
72926 'Ȭ' => 'ȭ',
72927 'Ȯ' => 'ȯ',
72928 'Ȱ' => 'ȱ',
72929 'Ȳ' => 'ȳ',
72930 'Ⱥ' => 'ⱥ',
72931 'Ȼ' => 'ȼ',
72932 'Ƚ' => 'ƚ',
72933 'Ⱦ' => 'ⱦ',
72934 'Ɂ' => 'ɂ',
72935 'Ƀ' => 'ƀ',
72936 'Ʉ' => 'ʉ',
72937 'Ʌ' => 'ʌ',
72938 'Ɇ' => 'ɇ',
72939 'Ɉ' => 'ɉ',
72940 'Ɋ' => 'ɋ',
72941 'Ɍ' => 'ɍ',
72942 'Ɏ' => 'ɏ',
72943 'Ͱ' => 'ͱ',
72944 'Ͳ' => 'ͳ',
72945 'Ͷ' => 'ͷ',
72946 'Ϳ' => 'ϳ',
72947 'Ά' => 'ά',
72948 'Έ' => 'έ',
72949 'Ή' => 'ή',
72950 'Ί' => 'ί',
72951 'Ό' => 'ό',
72952 'Ύ' => 'ύ',
72953 'Ώ' => 'ώ',
72954 'Α' => 'α',
72955 'Β' => 'β',
72956 'Γ' => 'γ',
72957 'Δ' => 'δ',
72958 'Ε' => 'ε',
72959 'Ζ' => 'ζ',
72960 'Η' => 'η',
72961 'Θ' => 'θ',
72962 'Ι' => 'ι',
72963 'Κ' => 'κ',
72964 'Λ' => 'λ',
72965 'Μ' => 'μ',
72966 'Ν' => 'ν',
72967 'Ξ' => 'ξ',
72968 'Ο' => 'ο',
72969 'Π' => 'π',
72970 'Ρ' => 'ρ',
72971 'Σ' => 'σ',
72972 'Τ' => 'τ',
72973 'Υ' => 'υ',
72974 'Φ' => 'φ',
72975 'Χ' => 'χ',
72976 'Ψ' => 'ψ',
72977 'Ω' => 'ω',
72978 'Ϊ' => 'ϊ',
72979 'Ϋ' => 'ϋ',
72980 'Ϗ' => 'ϗ',
72981 'Ϙ' => 'ϙ',
72982 'Ϛ' => 'ϛ',
72983 'Ϝ' => 'ϝ',
72984 'Ϟ' => 'ϟ',
72985 'Ϡ' => 'ϡ',
72986 'Ϣ' => 'ϣ',
72987 'Ϥ' => 'ϥ',
72988 'Ϧ' => 'ϧ',
72989 'Ϩ' => 'ϩ',
72990 'Ϫ' => 'ϫ',
72991 'Ϭ' => 'ϭ',
72992 'Ϯ' => 'ϯ',
72993 'ϴ' => 'θ',
72994 'Ϸ' => 'ϸ',
72995 'Ϲ' => 'ϲ',
72996 'Ϻ' => 'ϻ',
72997 'Ͻ' => 'ͻ',
72998 'Ͼ' => 'ͼ',
72999 'Ͽ' => 'ͽ',
73000 'Ѐ' => 'ѐ',
73001 'Ё' => 'ё',
73002 'Ђ' => 'ђ',
73003 'Ѓ' => 'ѓ',
73004 'Є' => 'є',
73005 'Ѕ' => 'ѕ',
73006 'І' => 'і',
73007 'Ї' => 'ї',
73008 'Ј' => 'ј',
73009 'Љ' => 'љ',
73010 'Њ' => 'њ',
73011 'Ћ' => 'ћ',
73012 'Ќ' => 'ќ',
73013 'Ѝ' => 'ѝ',
73014 'Ў' => 'ў',
73015 'Џ' => 'џ',
73016 'А' => 'а',
73017 'Б' => 'б',
73018 'В' => 'в',
73019 'Г' => 'г',
73020 'Д' => 'д',
73021 'Е' => 'е',
73022 'Ж' => 'ж',
73023 'З' => 'з',
73024 'И' => 'и',
73025 'Й' => 'й',
73026 'К' => 'к',
73027 'Л' => 'л',
73028 'М' => 'м',
73029 'Н' => 'н',
73030 'О' => 'о',
73031 'П' => 'п',
73032 'Р' => 'р',
73033 'С' => 'с',
73034 'Т' => 'т',
73035 'У' => 'у',
73036 'Ф' => 'ф',
73037 'Х' => 'х',
73038 'Ц' => 'ц',
73039 'Ч' => 'ч',
73040 'Ш' => 'ш',
73041 'Щ' => 'щ',
73042 'Ъ' => 'ъ',
73043 'Ы' => 'ы',
73044 'Ь' => 'ь',
73045 'Э' => 'э',
73046 'Ю' => 'ю',
73047 'Я' => 'я',
73048 'Ѡ' => 'ѡ',
73049 'Ѣ' => 'ѣ',
73050 'Ѥ' => 'ѥ',
73051 'Ѧ' => 'ѧ',
73052 'Ѩ' => 'ѩ',
73053 'Ѫ' => 'ѫ',
73054 'Ѭ' => 'ѭ',
73055 'Ѯ' => 'ѯ',
73056 'Ѱ' => 'ѱ',
73057 'Ѳ' => 'ѳ',
73058 'Ѵ' => 'ѵ',
73059 'Ѷ' => 'ѷ',
73060 'Ѹ' => 'ѹ',
73061 'Ѻ' => 'ѻ',
73062 'Ѽ' => 'ѽ',
73063 'Ѿ' => 'ѿ',
73064 'Ҁ' => 'ҁ',
73065 'Ҋ' => 'ҋ',
73066 'Ҍ' => 'ҍ',
73067 'Ҏ' => 'ҏ',
73068 'Ґ' => 'ґ',
73069 'Ғ' => 'ғ',
73070 'Ҕ' => 'ҕ',
73071 'Җ' => 'җ',
73072 'Ҙ' => 'ҙ',
73073 'Қ' => 'қ',
73074 'Ҝ' => 'ҝ',
73075 'Ҟ' => 'ҟ',
73076 'Ҡ' => 'ҡ',
73077 'Ң' => 'ң',
73078 'Ҥ' => 'ҥ',
73079 'Ҧ' => 'ҧ',
73080 'Ҩ' => 'ҩ',
73081 'Ҫ' => 'ҫ',
73082 'Ҭ' => 'ҭ',
73083 'Ү' => 'ү',
73084 'Ұ' => 'ұ',
73085 'Ҳ' => 'ҳ',
73086 'Ҵ' => 'ҵ',
73087 'Ҷ' => 'ҷ',
73088 'Ҹ' => 'ҹ',
73089 'Һ' => 'һ',
73090 'Ҽ' => 'ҽ',
73091 'Ҿ' => 'ҿ',
73092 'Ӏ' => 'ӏ',
73093 'Ӂ' => 'ӂ',
73094 'Ӄ' => 'ӄ',
73095 'Ӆ' => 'ӆ',
73096 'Ӈ' => 'ӈ',
73097 'Ӊ' => 'ӊ',
73098 'Ӌ' => 'ӌ',
73099 'Ӎ' => 'ӎ',
73100 'Ӑ' => 'ӑ',
73101 'Ӓ' => 'ӓ',
73102 'Ӕ' => 'ӕ',
73103 'Ӗ' => 'ӗ',
73104 'Ә' => 'ә',
73105 'Ӛ' => 'ӛ',
73106 'Ӝ' => 'ӝ',
73107 'Ӟ' => 'ӟ',
73108 'Ӡ' => 'ӡ',
73109 'Ӣ' => 'ӣ',
73110 'Ӥ' => 'ӥ',
73111 'Ӧ' => 'ӧ',
73112 'Ө' => 'ө',
73113 'Ӫ' => 'ӫ',
73114 'Ӭ' => 'ӭ',
73115 'Ӯ' => 'ӯ',
73116 'Ӱ' => 'ӱ',
73117 'Ӳ' => 'ӳ',
73118 'Ӵ' => 'ӵ',
73119 'Ӷ' => 'ӷ',
73120 'Ӹ' => 'ӹ',
73121 'Ӻ' => 'ӻ',
73122 'Ӽ' => 'ӽ',
73123 'Ӿ' => 'ӿ',
73124 'Ԁ' => 'ԁ',
73125 'Ԃ' => 'ԃ',
73126 'Ԅ' => 'ԅ',
73127 'Ԇ' => 'ԇ',
73128 'Ԉ' => 'ԉ',
73129 'Ԋ' => 'ԋ',
73130 'Ԍ' => 'ԍ',
73131 'Ԏ' => 'ԏ',
73132 'Ԑ' => 'ԑ',
73133 'Ԓ' => 'ԓ',
73134 'Ԕ' => 'ԕ',
73135 'Ԗ' => 'ԗ',
73136 'Ԙ' => 'ԙ',
73137 'Ԛ' => 'ԛ',
73138 'Ԝ' => 'ԝ',
73139 'Ԟ' => 'ԟ',
73140 'Ԡ' => 'ԡ',
73141 'Ԣ' => 'ԣ',
73142 'Ԥ' => 'ԥ',
73143 'Ԧ' => 'ԧ',
73144 'Ԩ' => 'ԩ',
73145 'Ԫ' => 'ԫ',
73146 'Ԭ' => 'ԭ',
73147 'Ԯ' => 'ԯ',
73148 'Ա' => 'ա',
73149 'Բ' => 'բ',
73150 'Գ' => 'գ',
73151 'Դ' => 'դ',
73152 'Ե' => 'ե',
73153 'Զ' => 'զ',
73154 'Է' => 'է',
73155 'Ը' => 'ը',
73156 'Թ' => 'թ',
73157 'Ժ' => 'ժ',
73158 'Ի' => 'ի',
73159 'Լ' => 'լ',
73160 'Խ' => 'խ',
73161 'Ծ' => 'ծ',
73162 'Կ' => 'կ',
73163 'Հ' => 'հ',
73164 'Ձ' => 'ձ',
73165 'Ղ' => 'ղ',
73166 'Ճ' => 'ճ',
73167 'Մ' => 'մ',
73168 'Յ' => 'յ',
73169 'Ն' => 'ն',
73170 'Շ' => 'շ',
73171 'Ո' => 'ո',
73172 'Չ' => 'չ',
73173 'Պ' => 'պ',
73174 'Ջ' => 'ջ',
73175 'Ռ' => 'ռ',
73176 'Ս' => 'ս',
73177 'Վ' => 'վ',
73178 'Տ' => 'տ',
73179 'Ր' => 'ր',
73180 'Ց' => 'ց',
73181 'Ւ' => 'ւ',
73182 'Փ' => 'փ',
73183 'Ք' => 'ք',
73184 'Օ' => 'օ',
73185 'Ֆ' => 'ֆ',
73186 'Ⴀ' => 'ⴀ',
73187 'Ⴁ' => 'ⴁ',
73188 'Ⴂ' => 'ⴂ',
73189 'Ⴃ' => 'ⴃ',
73190 'Ⴄ' => 'ⴄ',
73191 'Ⴅ' => 'ⴅ',
73192 'Ⴆ' => 'ⴆ',
73193 'Ⴇ' => 'ⴇ',
73194 'Ⴈ' => 'ⴈ',
73195 'Ⴉ' => 'ⴉ',
73196 'Ⴊ' => 'ⴊ',
73197 'Ⴋ' => 'ⴋ',
73198 'Ⴌ' => 'ⴌ',
73199 'Ⴍ' => 'ⴍ',
73200 'Ⴎ' => 'ⴎ',
73201 'Ⴏ' => 'ⴏ',
73202 'Ⴐ' => 'ⴐ',
73203 'Ⴑ' => 'ⴑ',
73204 'Ⴒ' => 'ⴒ',
73205 'Ⴓ' => 'ⴓ',
73206 'Ⴔ' => 'ⴔ',
73207 'Ⴕ' => 'ⴕ',
73208 'Ⴖ' => 'ⴖ',
73209 'Ⴗ' => 'ⴗ',
73210 'Ⴘ' => 'ⴘ',
73211 'Ⴙ' => 'ⴙ',
73212 'Ⴚ' => 'ⴚ',
73213 'Ⴛ' => 'ⴛ',
73214 'Ⴜ' => 'ⴜ',
73215 'Ⴝ' => 'ⴝ',
73216 'Ⴞ' => 'ⴞ',
73217 'Ⴟ' => 'ⴟ',
73218 'Ⴠ' => 'ⴠ',
73219 'Ⴡ' => 'ⴡ',
73220 'Ⴢ' => 'ⴢ',
73221 'Ⴣ' => 'ⴣ',
73222 'Ⴤ' => 'ⴤ',
73223 'Ⴥ' => 'ⴥ',
73224 'Ⴧ' => 'ⴧ',
73225 'Ⴭ' => 'ⴭ',
73226 'Ḁ' => 'ḁ',
73227 'Ḃ' => 'ḃ',
73228 'Ḅ' => 'ḅ',
73229 'Ḇ' => 'ḇ',
73230 'Ḉ' => 'ḉ',
73231 'Ḋ' => 'ḋ',
73232 'Ḍ' => 'ḍ',
73233 'Ḏ' => 'ḏ',
73234 'Ḑ' => 'ḑ',
73235 'Ḓ' => 'ḓ',
73236 'Ḕ' => 'ḕ',
73237 'Ḗ' => 'ḗ',
73238 'Ḙ' => 'ḙ',
73239 'Ḛ' => 'ḛ',
73240 'Ḝ' => 'ḝ',
73241 'Ḟ' => 'ḟ',
73242 'Ḡ' => 'ḡ',
73243 'Ḣ' => 'ḣ',
73244 'Ḥ' => 'ḥ',
73245 'Ḧ' => 'ḧ',
73246 'Ḩ' => 'ḩ',
73247 'Ḫ' => 'ḫ',
73248 'Ḭ' => 'ḭ',
73249 'Ḯ' => 'ḯ',
73250 'Ḱ' => 'ḱ',
73251 'Ḳ' => 'ḳ',
73252 'Ḵ' => 'ḵ',
73253 'Ḷ' => 'ḷ',
73254 'Ḹ' => 'ḹ',
73255 'Ḻ' => 'ḻ',
73256 'Ḽ' => 'ḽ',
73257 'Ḿ' => 'ḿ',
73258 'Ṁ' => 'ṁ',
73259 'Ṃ' => 'ṃ',
73260 'Ṅ' => 'ṅ',
73261 'Ṇ' => 'ṇ',
73262 'Ṉ' => 'ṉ',
73263 'Ṋ' => 'ṋ',
73264 'Ṍ' => 'ṍ',
73265 'Ṏ' => 'ṏ',
73266 'Ṑ' => 'ṑ',
73267 'Ṓ' => 'ṓ',
73268 'Ṕ' => 'ṕ',
73269 'Ṗ' => 'ṗ',
73270 'Ṙ' => 'ṙ',
73271 'Ṛ' => 'ṛ',
73272 'Ṝ' => 'ṝ',
73273 'Ṟ' => 'ṟ',
73274 'Ṡ' => 'ṡ',
73275 'Ṣ' => 'ṣ',
73276 'Ṥ' => 'ṥ',
73277 'Ṧ' => 'ṧ',
73278 'Ṩ' => 'ṩ',
73279 'Ṫ' => 'ṫ',
73280 'Ṭ' => 'ṭ',
73281 'Ṯ' => 'ṯ',
73282 'Ṱ' => 'ṱ',
73283 'Ṳ' => 'ṳ',
73284 'Ṵ' => 'ṵ',
73285 'Ṷ' => 'ṷ',
73286 'Ṹ' => 'ṹ',
73287 'Ṻ' => 'ṻ',
73288 'Ṽ' => 'ṽ',
73289 'Ṿ' => 'ṿ',
73290 'Ẁ' => 'ẁ',
73291 'Ẃ' => 'ẃ',
73292 'Ẅ' => 'ẅ',
73293 'Ẇ' => 'ẇ',
73294 'Ẉ' => 'ẉ',
73295 'Ẋ' => 'ẋ',
73296 'Ẍ' => 'ẍ',
73297 'Ẏ' => 'ẏ',
73298 'Ẑ' => 'ẑ',
73299 'Ẓ' => 'ẓ',
73300 'Ẕ' => 'ẕ',
73301 'ẞ' => 'ß',
73302 'Ạ' => 'ạ',
73303 'Ả' => 'ả',
73304 'Ấ' => 'ấ',
73305 'Ầ' => 'ầ',
73306 'Ẩ' => 'ẩ',
73307 'Ẫ' => 'ẫ',
73308 'Ậ' => 'ậ',
73309 'Ắ' => 'ắ',
73310 'Ằ' => 'ằ',
73311 'Ẳ' => 'ẳ',
73312 'Ẵ' => 'ẵ',
73313 'Ặ' => 'ặ',
73314 'Ẹ' => 'ẹ',
73315 'Ẻ' => 'ẻ',
73316 'Ẽ' => 'ẽ',
73317 'Ế' => 'ế',
73318 'Ề' => 'ề',
73319 'Ể' => 'ể',
73320 'Ễ' => 'ễ',
73321 'Ệ' => 'ệ',
73322 'Ỉ' => 'ỉ',
73323 'Ị' => 'ị',
73324 'Ọ' => 'ọ',
73325 'Ỏ' => 'ỏ',
73326 'Ố' => 'ố',
73327 'Ồ' => 'ồ',
73328 'Ổ' => 'ổ',
73329 'Ỗ' => 'ỗ',
73330 'Ộ' => 'ộ',
73331 'Ớ' => 'ớ',
73332 'Ờ' => 'ờ',
73333 'Ở' => 'ở',
73334 'Ỡ' => 'ỡ',
73335 'Ợ' => 'ợ',
73336 'Ụ' => 'ụ',
73337 'Ủ' => 'ủ',
73338 'Ứ' => 'ứ',
73339 'Ừ' => 'ừ',
73340 'Ử' => 'ử',
73341 'Ữ' => 'ữ',
73342 'Ự' => 'ự',
73343 'Ỳ' => 'ỳ',
73344 'Ỵ' => 'ỵ',
73345 'Ỷ' => 'ỷ',
73346 'Ỹ' => 'ỹ',
73347 'Ỻ' => 'ỻ',
73348 'Ỽ' => 'ỽ',
73349 'Ỿ' => 'ỿ',
73350 'Ἀ' => 'ἀ',
73351 'Ἁ' => 'ἁ',
73352 'Ἂ' => 'ἂ',
73353 'Ἃ' => 'ἃ',
73354 'Ἄ' => 'ἄ',
73355 'Ἅ' => 'ἅ',
73356 'Ἆ' => 'ἆ',
73357 'Ἇ' => 'ἇ',
73358 'Ἐ' => 'ἐ',
73359 'Ἑ' => 'ἑ',
73360 'Ἒ' => 'ἒ',
73361 'Ἓ' => 'ἓ',
73362 'Ἔ' => 'ἔ',
73363 'Ἕ' => 'ἕ',
73364 'Ἠ' => 'ἠ',
73365 'Ἡ' => 'ἡ',
73366 'Ἢ' => 'ἢ',
73367 'Ἣ' => 'ἣ',
73368 'Ἤ' => 'ἤ',
73369 'Ἥ' => 'ἥ',
73370 'Ἦ' => 'ἦ',
73371 'Ἧ' => 'ἧ',
73372 'Ἰ' => 'ἰ',
73373 'Ἱ' => 'ἱ',
73374 'Ἲ' => 'ἲ',
73375 'Ἳ' => 'ἳ',
73376 'Ἴ' => 'ἴ',
73377 'Ἵ' => 'ἵ',
73378 'Ἶ' => 'ἶ',
73379 'Ἷ' => 'ἷ',
73380 'Ὀ' => 'ὀ',
73381 'Ὁ' => 'ὁ',
73382 'Ὂ' => 'ὂ',
73383 'Ὃ' => 'ὃ',
73384 'Ὄ' => 'ὄ',
73385 'Ὅ' => 'ὅ',
73386 'Ὑ' => 'ὑ',
73387 'Ὓ' => 'ὓ',
73388 'Ὕ' => 'ὕ',
73389 'Ὗ' => 'ὗ',
73390 'Ὠ' => 'ὠ',
73391 'Ὡ' => 'ὡ',
73392 'Ὢ' => 'ὢ',
73393 'Ὣ' => 'ὣ',
73394 'Ὤ' => 'ὤ',
73395 'Ὥ' => 'ὥ',
73396 'Ὦ' => 'ὦ',
73397 'Ὧ' => 'ὧ',
73398 'ᾈ' => 'ᾀ',
73399 'ᾉ' => 'ᾁ',
73400 'ᾊ' => 'ᾂ',
73401 'ᾋ' => 'ᾃ',
73402 'ᾌ' => 'ᾄ',
73403 'ᾍ' => 'ᾅ',
73404 'ᾎ' => 'ᾆ',
73405 'ᾏ' => 'ᾇ',
73406 'ᾘ' => 'ᾐ',
73407 'ᾙ' => 'ᾑ',
73408 'ᾚ' => 'ᾒ',
73409 'ᾛ' => 'ᾓ',
73410 'ᾜ' => 'ᾔ',
73411 'ᾝ' => 'ᾕ',
73412 'ᾞ' => 'ᾖ',
73413 'ᾟ' => 'ᾗ',
73414 'ᾨ' => 'ᾠ',
73415 'ᾩ' => 'ᾡ',
73416 'ᾪ' => 'ᾢ',
73417 'ᾫ' => 'ᾣ',
73418 'ᾬ' => 'ᾤ',
73419 'ᾭ' => 'ᾥ',
73420 'ᾮ' => 'ᾦ',
73421 'ᾯ' => 'ᾧ',
73422 'Ᾰ' => 'ᾰ',
73423 'Ᾱ' => 'ᾱ',
73424 'Ὰ' => 'ὰ',
73425 'Ά' => 'ά',
73426 'ᾼ' => 'ᾳ',
73427 'Ὲ' => 'ὲ',
73428 'Έ' => 'έ',
73429 'Ὴ' => 'ὴ',
73430 'Ή' => 'ή',
73431 'ῌ' => 'ῃ',
73432 'Ῐ' => 'ῐ',
73433 'Ῑ' => 'ῑ',
73434 'Ὶ' => 'ὶ',
73435 'Ί' => 'ί',
73436 'Ῠ' => 'ῠ',
73437 'Ῡ' => 'ῡ',
73438 'Ὺ' => 'ὺ',
73439 'Ύ' => 'ύ',
73440 'Ῥ' => 'ῥ',
73441 'Ὸ' => 'ὸ',
73442 'Ό' => 'ό',
73443 'Ὼ' => 'ὼ',
73444 'Ώ' => 'ώ',
73445 'ῼ' => 'ῳ',
73446 'Ω' => 'ω',
73447 'K' => 'k',
73448 'Å' => 'å',
73449 'Ⅎ' => 'ⅎ',
73450 'Ⅰ' => 'ⅰ',
73451 'Ⅱ' => 'ⅱ',
73452 'Ⅲ' => 'ⅲ',
73453 'Ⅳ' => 'ⅳ',
73454 'Ⅴ' => 'ⅴ',
73455 'Ⅵ' => 'ⅵ',
73456 'Ⅶ' => 'ⅶ',
73457 'Ⅷ' => 'ⅷ',
73458 'Ⅸ' => 'ⅸ',
73459 'Ⅹ' => 'ⅹ',
73460 'Ⅺ' => 'ⅺ',
73461 'Ⅻ' => 'ⅻ',
73462 'Ⅼ' => 'ⅼ',
73463 'Ⅽ' => 'ⅽ',
73464 'Ⅾ' => 'ⅾ',
73465 'Ⅿ' => 'ⅿ',
73466 'Ↄ' => 'ↄ',
73467 'Ⓐ' => 'ⓐ',
73468 'Ⓑ' => 'ⓑ',
73469 'Ⓒ' => 'ⓒ',
73470 'Ⓓ' => 'ⓓ',
73471 'Ⓔ' => 'ⓔ',
73472 'Ⓕ' => 'ⓕ',
73473 'Ⓖ' => 'ⓖ',
73474 'Ⓗ' => 'ⓗ',
73475 'Ⓘ' => 'ⓘ',
73476 'Ⓙ' => 'ⓙ',
73477 'Ⓚ' => 'ⓚ',
73478 'Ⓛ' => 'ⓛ',
73479 'Ⓜ' => 'ⓜ',
73480 'Ⓝ' => 'ⓝ',
73481 'Ⓞ' => 'ⓞ',
73482 'Ⓟ' => 'ⓟ',
73483 'Ⓠ' => 'ⓠ',
73484 'Ⓡ' => 'ⓡ',
73485 'Ⓢ' => 'ⓢ',
73486 'Ⓣ' => 'ⓣ',
73487 'Ⓤ' => 'ⓤ',
73488 'Ⓥ' => 'ⓥ',
73489 'Ⓦ' => 'ⓦ',
73490 'Ⓧ' => 'ⓧ',
73491 'Ⓨ' => 'ⓨ',
73492 'Ⓩ' => 'ⓩ',
73493 'Ⰰ' => 'ⰰ',
73494 'Ⰱ' => 'ⰱ',
73495 'Ⰲ' => 'ⰲ',
73496 'Ⰳ' => 'ⰳ',
73497 'Ⰴ' => 'ⰴ',
73498 'Ⰵ' => 'ⰵ',
73499 'Ⰶ' => 'ⰶ',
73500 'Ⰷ' => 'ⰷ',
73501 'Ⰸ' => 'ⰸ',
73502 'Ⰹ' => 'ⰹ',
73503 'Ⰺ' => 'ⰺ',
73504 'Ⰻ' => 'ⰻ',
73505 'Ⰼ' => 'ⰼ',
73506 'Ⰽ' => 'ⰽ',
73507 'Ⰾ' => 'ⰾ',
73508 'Ⰿ' => 'ⰿ',
73509 'Ⱀ' => 'ⱀ',
73510 'Ⱁ' => 'ⱁ',
73511 'Ⱂ' => 'ⱂ',
73512 'Ⱃ' => 'ⱃ',
73513 'Ⱄ' => 'ⱄ',
73514 'Ⱅ' => 'ⱅ',
73515 'Ⱆ' => 'ⱆ',
73516 'Ⱇ' => 'ⱇ',
73517 'Ⱈ' => 'ⱈ',
73518 'Ⱉ' => 'ⱉ',
73519 'Ⱊ' => 'ⱊ',
73520 'Ⱋ' => 'ⱋ',
73521 'Ⱌ' => 'ⱌ',
73522 'Ⱍ' => 'ⱍ',
73523 'Ⱎ' => 'ⱎ',
73524 'Ⱏ' => 'ⱏ',
73525 'Ⱐ' => 'ⱐ',
73526 'Ⱑ' => 'ⱑ',
73527 'Ⱒ' => 'ⱒ',
73528 'Ⱓ' => 'ⱓ',
73529 'Ⱔ' => 'ⱔ',
73530 'Ⱕ' => 'ⱕ',
73531 'Ⱖ' => 'ⱖ',
73532 'Ⱗ' => 'ⱗ',
73533 'Ⱘ' => 'ⱘ',
73534 'Ⱙ' => 'ⱙ',
73535 'Ⱚ' => 'ⱚ',
73536 'Ⱛ' => 'ⱛ',
73537 'Ⱜ' => 'ⱜ',
73538 'Ⱝ' => 'ⱝ',
73539 'Ⱞ' => 'ⱞ',
73540 'Ⱡ' => 'ⱡ',
73541 'Ɫ' => 'ɫ',
73542 'Ᵽ' => 'ᵽ',
73543 'Ɽ' => 'ɽ',
73544 'Ⱨ' => 'ⱨ',
73545 'Ⱪ' => 'ⱪ',
73546 'Ⱬ' => 'ⱬ',
73547 'Ɑ' => 'ɑ',
73548 'Ɱ' => 'ɱ',
73549 'Ɐ' => 'ɐ',
73550 'Ɒ' => 'ɒ',
73551 'Ⱳ' => 'ⱳ',
73552 'Ⱶ' => 'ⱶ',
73553 'Ȿ' => 'ȿ',
73554 'Ɀ' => 'ɀ',
73555 'Ⲁ' => 'ⲁ',
73556 'Ⲃ' => 'ⲃ',
73557 'Ⲅ' => 'ⲅ',
73558 'Ⲇ' => 'ⲇ',
73559 'Ⲉ' => 'ⲉ',
73560 'Ⲋ' => 'ⲋ',
73561 'Ⲍ' => 'ⲍ',
73562 'Ⲏ' => 'ⲏ',
73563 'Ⲑ' => 'ⲑ',
73564 'Ⲓ' => 'ⲓ',
73565 'Ⲕ' => 'ⲕ',
73566 'Ⲗ' => 'ⲗ',
73567 'Ⲙ' => 'ⲙ',
73568 'Ⲛ' => 'ⲛ',
73569 'Ⲝ' => 'ⲝ',
73570 'Ⲟ' => 'ⲟ',
73571 'Ⲡ' => 'ⲡ',
73572 'Ⲣ' => 'ⲣ',
73573 'Ⲥ' => 'ⲥ',
73574 'Ⲧ' => 'ⲧ',
73575 'Ⲩ' => 'ⲩ',
73576 'Ⲫ' => 'ⲫ',
73577 'Ⲭ' => 'ⲭ',
73578 'Ⲯ' => 'ⲯ',
73579 'Ⲱ' => 'ⲱ',
73580 'Ⲳ' => 'ⲳ',
73581 'Ⲵ' => 'ⲵ',
73582 'Ⲷ' => 'ⲷ',
73583 'Ⲹ' => 'ⲹ',
73584 'Ⲻ' => 'ⲻ',
73585 'Ⲽ' => 'ⲽ',
73586 'Ⲿ' => 'ⲿ',
73587 'Ⳁ' => 'ⳁ',
73588 'Ⳃ' => 'ⳃ',
73589 'Ⳅ' => 'ⳅ',
73590 'Ⳇ' => 'ⳇ',
73591 'Ⳉ' => 'ⳉ',
73592 'Ⳋ' => 'ⳋ',
73593 'Ⳍ' => 'ⳍ',
73594 'Ⳏ' => 'ⳏ',
73595 'Ⳑ' => 'ⳑ',
73596 'Ⳓ' => 'ⳓ',
73597 'Ⳕ' => 'ⳕ',
73598 'Ⳗ' => 'ⳗ',
73599 'Ⳙ' => 'ⳙ',
73600 'Ⳛ' => 'ⳛ',
73601 'Ⳝ' => 'ⳝ',
73602 'Ⳟ' => 'ⳟ',
73603 'Ⳡ' => 'ⳡ',
73604 'Ⳣ' => 'ⳣ',
73605 'Ⳬ' => 'ⳬ',
73606 'Ⳮ' => 'ⳮ',
73607 'Ⳳ' => 'ⳳ',
73608 'Ꙁ' => 'ꙁ',
73609 'Ꙃ' => 'ꙃ',
73610 'Ꙅ' => 'ꙅ',
73611 'Ꙇ' => 'ꙇ',
73612 'Ꙉ' => 'ꙉ',
73613 'Ꙋ' => 'ꙋ',
73614 'Ꙍ' => 'ꙍ',
73615 'Ꙏ' => 'ꙏ',
73616 'Ꙑ' => 'ꙑ',
73617 'Ꙓ' => 'ꙓ',
73618 'Ꙕ' => 'ꙕ',
73619 'Ꙗ' => 'ꙗ',
73620 'Ꙙ' => 'ꙙ',
73621 'Ꙛ' => 'ꙛ',
73622 'Ꙝ' => 'ꙝ',
73623 'Ꙟ' => 'ꙟ',
73624 'Ꙡ' => 'ꙡ',
73625 'Ꙣ' => 'ꙣ',
73626 'Ꙥ' => 'ꙥ',
73627 'Ꙧ' => 'ꙧ',
73628 'Ꙩ' => 'ꙩ',
73629 'Ꙫ' => 'ꙫ',
73630 'Ꙭ' => 'ꙭ',
73631 'Ꚁ' => 'ꚁ',
73632 'Ꚃ' => 'ꚃ',
73633 'Ꚅ' => 'ꚅ',
73634 'Ꚇ' => 'ꚇ',
73635 'Ꚉ' => 'ꚉ',
73636 'Ꚋ' => 'ꚋ',
73637 'Ꚍ' => 'ꚍ',
73638 'Ꚏ' => 'ꚏ',
73639 'Ꚑ' => 'ꚑ',
73640 'Ꚓ' => 'ꚓ',
73641 'Ꚕ' => 'ꚕ',
73642 'Ꚗ' => 'ꚗ',
73643 'Ꚙ' => 'ꚙ',
73644 'Ꚛ' => 'ꚛ',
73645 'Ꜣ' => 'ꜣ',
73646 'Ꜥ' => 'ꜥ',
73647 'Ꜧ' => 'ꜧ',
73648 'Ꜩ' => 'ꜩ',
73649 'Ꜫ' => 'ꜫ',
73650 'Ꜭ' => 'ꜭ',
73651 'Ꜯ' => 'ꜯ',
73652 'Ꜳ' => 'ꜳ',
73653 'Ꜵ' => 'ꜵ',
73654 'Ꜷ' => 'ꜷ',
73655 'Ꜹ' => 'ꜹ',
73656 'Ꜻ' => 'ꜻ',
73657 'Ꜽ' => 'ꜽ',
73658 'Ꜿ' => 'ꜿ',
73659 'Ꝁ' => 'ꝁ',
73660 'Ꝃ' => 'ꝃ',
73661 'Ꝅ' => 'ꝅ',
73662 'Ꝇ' => 'ꝇ',
73663 'Ꝉ' => 'ꝉ',
73664 'Ꝋ' => 'ꝋ',
73665 'Ꝍ' => 'ꝍ',
73666 'Ꝏ' => 'ꝏ',
73667 'Ꝑ' => 'ꝑ',
73668 'Ꝓ' => 'ꝓ',
73669 'Ꝕ' => 'ꝕ',
73670 'Ꝗ' => 'ꝗ',
73671 'Ꝙ' => 'ꝙ',
73672 'Ꝛ' => 'ꝛ',
73673 'Ꝝ' => 'ꝝ',
73674 'Ꝟ' => 'ꝟ',
73675 'Ꝡ' => 'ꝡ',
73676 'Ꝣ' => 'ꝣ',
73677 'Ꝥ' => 'ꝥ',
73678 'Ꝧ' => 'ꝧ',
73679 'Ꝩ' => 'ꝩ',
73680 'Ꝫ' => 'ꝫ',
73681 'Ꝭ' => 'ꝭ',
73682 'Ꝯ' => 'ꝯ',
73683 'Ꝺ' => 'ꝺ',
73684 'Ꝼ' => 'ꝼ',
73685 'Ᵹ' => 'ᵹ',
73686 'Ꝿ' => 'ꝿ',
73687 'Ꞁ' => 'ꞁ',
73688 'Ꞃ' => 'ꞃ',
73689 'Ꞅ' => 'ꞅ',
73690 'Ꞇ' => 'ꞇ',
73691 'Ꞌ' => 'ꞌ',
73692 'Ɥ' => 'ɥ',
73693 'Ꞑ' => 'ꞑ',
73694 'Ꞓ' => 'ꞓ',
73695 'Ꞗ' => 'ꞗ',
73696 'Ꞙ' => 'ꞙ',
73697 'Ꞛ' => 'ꞛ',
73698 'Ꞝ' => 'ꞝ',
73699 'Ꞟ' => 'ꞟ',
73700 'Ꞡ' => 'ꞡ',
73701 'Ꞣ' => 'ꞣ',
73702 'Ꞥ' => 'ꞥ',
73703 'Ꞧ' => 'ꞧ',
73704 'Ꞩ' => 'ꞩ',
73705 'Ɦ' => 'ɦ',
73706 'Ɜ' => 'ɜ',
73707 'Ɡ' => 'ɡ',
73708 'Ɬ' => 'ɬ',
73709 'Ʞ' => 'ʞ',
73710 'Ʇ' => 'ʇ',
73711 'A' => 'a',
73712 'B' => 'b',
73713 'C' => 'c',
73714 'D' => 'd',
73715 'E' => 'e',
73716 'F' => 'f',
73717 'G' => 'g',
73718 'H' => 'h',
73719 'I' => 'i',
73720 'J' => 'j',
73721 'K' => 'k',
73722 'L' => 'l',
73723 'M' => 'm',
73724 'N' => 'n',
73725 'O' => 'o',
73726 'P' => 'p',
73727 'Q' => 'q',
73728 'R' => 'r',
73729 'S' => 's',
73730 'T' => 't',
73731 'U' => 'u',
73732 'V' => 'v',
73733 'W' => 'w',
73734 'X' => 'x',
73735 'Y' => 'y',
73736 'Z' => 'z',
73737 '𐐀' => '𐐨',
73738 '𐐁' => '𐐩',
73739 '𐐂' => '𐐪',
73740 '𐐃' => '𐐫',
73741 '𐐄' => '𐐬',
73742 '𐐅' => '𐐭',
73743 '𐐆' => '𐐮',
73744 '𐐇' => '𐐯',
73745 '𐐈' => '𐐰',
73746 '𐐉' => '𐐱',
73747 '𐐊' => '𐐲',
73748 '𐐋' => '𐐳',
73749 '𐐌' => '𐐴',
73750 '𐐍' => '𐐵',
73751 '𐐎' => '𐐶',
73752 '𐐏' => '𐐷',
73753 '𐐐' => '𐐸',
73754 '𐐑' => '𐐹',
73755 '𐐒' => '𐐺',
73756 '𐐓' => '𐐻',
73757 '𐐔' => '𐐼',
73758 '𐐕' => '𐐽',
73759 '𐐖' => '𐐾',
73760 '𐐗' => '𐐿',
73761 '𐐘' => '𐑀',
73762 '𐐙' => '𐑁',
73763 '𐐚' => '𐑂',
73764 '𐐛' => '𐑃',
73765 '𐐜' => '𐑄',
73766 '𐐝' => '𐑅',
73767 '𐐞' => '𐑆',
73768 '𐐟' => '𐑇',
73769 '𐐠' => '𐑈',
73770 '𐐡' => '𐑉',
73771 '𐐢' => '𐑊',
73772 '𐐣' => '𐑋',
73773 '𐐤' => '𐑌',
73774 '𐐥' => '𐑍',
73775 '𐐦' => '𐑎',
73776 '𐐧' => '𐑏',
73777 '𑢠' => '𑣀',
73778 '𑢡' => '𑣁',
73779 '𑢢' => '𑣂',
73780 '𑢣' => '𑣃',
73781 '𑢤' => '𑣄',
73782 '𑢥' => '𑣅',
73783 '𑢦' => '𑣆',
73784 '𑢧' => '𑣇',
73785 '𑢨' => '𑣈',
73786 '𑢩' => '𑣉',
73787 '𑢪' => '𑣊',
73788 '𑢫' => '𑣋',
73789 '𑢬' => '𑣌',
73790 '𑢭' => '𑣍',
73791 '𑢮' => '𑣎',
73792 '𑢯' => '𑣏',
73793 '𑢰' => '𑣐',
73794 '𑢱' => '𑣑',
73795 '𑢲' => '𑣒',
73796 '𑢳' => '𑣓',
73797 '𑢴' => '𑣔',
73798 '𑢵' => '𑣕',
73799 '𑢶' => '𑣖',
73800 '𑢷' => '𑣗',
73801 '𑢸' => '𑣘',
73802 '𑢹' => '𑣙',
73803 '𑢺' => '𑣚',
73804 '𑢻' => '𑣛',
73805 '𑢼' => '𑣜',
73806 '𑢽' => '𑣝',
73807 '𑢾' => '𑣞',
73808 '𑢿' => '𑣟',
73809 );
73810 <?php
73811
73812
73813
73814 return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u';
73815 <?php
73816
73817 return array(
73818 'a' => 'A',
73819 'b' => 'B',
73820 'c' => 'C',
73821 'd' => 'D',
73822 'e' => 'E',
73823 'f' => 'F',
73824 'g' => 'G',
73825 'h' => 'H',
73826 'i' => 'I',
73827 'j' => 'J',
73828 'k' => 'K',
73829 'l' => 'L',
73830 'm' => 'M',
73831 'n' => 'N',
73832 'o' => 'O',
73833 'p' => 'P',
73834 'q' => 'Q',
73835 'r' => 'R',
73836 's' => 'S',
73837 't' => 'T',
73838 'u' => 'U',
73839 'v' => 'V',
73840 'w' => 'W',
73841 'x' => 'X',
73842 'y' => 'Y',
73843 'z' => 'Z',
73844 'µ' => 'Μ',
73845 'à' => 'À',
73846 'á' => 'Á',
73847 'â' => 'Â',
73848 'ã' => 'Ã',
73849 'ä' => 'Ä',
73850 'å' => 'Å',
73851 'æ' => 'Æ',
73852 'ç' => 'Ç',
73853 'è' => 'È',
73854 'é' => 'É',
73855 'ê' => 'Ê',
73856 'ë' => 'Ë',
73857 'ì' => 'Ì',
73858 'í' => 'Í',
73859 'î' => 'Î',
73860 'ï' => 'Ï',
73861 'ð' => 'Ð',
73862 'ñ' => 'Ñ',
73863 'ò' => 'Ò',
73864 'ó' => 'Ó',
73865 'ô' => 'Ô',
73866 'õ' => 'Õ',
73867 'ö' => 'Ö',
73868 'ø' => 'Ø',
73869 'ù' => 'Ù',
73870 'ú' => 'Ú',
73871 'û' => 'Û',
73872 'ü' => 'Ü',
73873 'ý' => 'Ý',
73874 'þ' => 'Þ',
73875 'ÿ' => 'Ÿ',
73876 'ā' => 'Ā',
73877 'ă' => 'Ă',
73878 'ą' => 'Ą',
73879 'ć' => 'Ć',
73880 'ĉ' => 'Ĉ',
73881 'ċ' => 'Ċ',
73882 'č' => 'Č',
73883 'ď' => 'Ď',
73884 'đ' => 'Đ',
73885 'ē' => 'Ē',
73886 'ĕ' => 'Ĕ',
73887 'ė' => 'Ė',
73888 'ę' => 'Ę',
73889 'ě' => 'Ě',
73890 'ĝ' => 'Ĝ',
73891 'ğ' => 'Ğ',
73892 'ġ' => 'Ġ',
73893 'ģ' => 'Ģ',
73894 'ĥ' => 'Ĥ',
73895 'ħ' => 'Ħ',
73896 'ĩ' => 'Ĩ',
73897 'ī' => 'Ī',
73898 'ĭ' => 'Ĭ',
73899 'į' => 'Į',
73900 'ı' => 'I',
73901 'ij' => 'IJ',
73902 'ĵ' => 'Ĵ',
73903 'ķ' => 'Ķ',
73904 'ĺ' => 'Ĺ',
73905 'ļ' => 'Ļ',
73906 'ľ' => 'Ľ',
73907 'ŀ' => 'Ŀ',
73908 'ł' => 'Ł',
73909 'ń' => 'Ń',
73910 'ņ' => 'Ņ',
73911 'ň' => 'Ň',
73912 'ŋ' => 'Ŋ',
73913 'ō' => 'Ō',
73914 'ŏ' => 'Ŏ',
73915 'ő' => 'Ő',
73916 'œ' => 'Œ',
73917 'ŕ' => 'Ŕ',
73918 'ŗ' => 'Ŗ',
73919 'ř' => 'Ř',
73920 'ś' => 'Ś',
73921 'ŝ' => 'Ŝ',
73922 'ş' => 'Ş',
73923 'š' => 'Š',
73924 'ţ' => 'Ţ',
73925 'ť' => 'Ť',
73926 'ŧ' => 'Ŧ',
73927 'ũ' => 'Ũ',
73928 'ū' => 'Ū',
73929 'ŭ' => 'Ŭ',
73930 'ů' => 'Ů',
73931 'ű' => 'Ű',
73932 'ų' => 'Ų',
73933 'ŵ' => 'Ŵ',
73934 'ŷ' => 'Ŷ',
73935 'ź' => 'Ź',
73936 'ż' => 'Ż',
73937 'ž' => 'Ž',
73938 'ſ' => 'S',
73939 'ƀ' => 'Ƀ',
73940 'ƃ' => 'Ƃ',
73941 'ƅ' => 'Ƅ',
73942 'ƈ' => 'Ƈ',
73943 'ƌ' => 'Ƌ',
73944 'ƒ' => 'Ƒ',
73945 'ƕ' => 'Ƕ',
73946 'ƙ' => 'Ƙ',
73947 'ƚ' => 'Ƚ',
73948 'ƞ' => 'Ƞ',
73949 'ơ' => 'Ơ',
73950 'ƣ' => 'Ƣ',
73951 'ƥ' => 'Ƥ',
73952 'ƨ' => 'Ƨ',
73953 'ƭ' => 'Ƭ',
73954 'ư' => 'Ư',
73955 'ƴ' => 'Ƴ',
73956 'ƶ' => 'Ƶ',
73957 'ƹ' => 'Ƹ',
73958 'ƽ' => 'Ƽ',
73959 'ƿ' => 'Ƿ',
73960 'Dž' => 'DŽ',
73961 'dž' => 'DŽ',
73962 'Lj' => 'LJ',
73963 'lj' => 'LJ',
73964 'Nj' => 'NJ',
73965 'nj' => 'NJ',
73966 'ǎ' => 'Ǎ',
73967 'ǐ' => 'Ǐ',
73968 'ǒ' => 'Ǒ',
73969 'ǔ' => 'Ǔ',
73970 'ǖ' => 'Ǖ',
73971 'ǘ' => 'Ǘ',
73972 'ǚ' => 'Ǚ',
73973 'ǜ' => 'Ǜ',
73974 'ǝ' => 'Ǝ',
73975 'ǟ' => 'Ǟ',
73976 'ǡ' => 'Ǡ',
73977 'ǣ' => 'Ǣ',
73978 'ǥ' => 'Ǥ',
73979 'ǧ' => 'Ǧ',
73980 'ǩ' => 'Ǩ',
73981 'ǫ' => 'Ǫ',
73982 'ǭ' => 'Ǭ',
73983 'ǯ' => 'Ǯ',
73984 'Dz' => 'DZ',
73985 'dz' => 'DZ',
73986 'ǵ' => 'Ǵ',
73987 'ǹ' => 'Ǹ',
73988 'ǻ' => 'Ǻ',
73989 'ǽ' => 'Ǽ',
73990 'ǿ' => 'Ǿ',
73991 'ȁ' => 'Ȁ',
73992 'ȃ' => 'Ȃ',
73993 'ȅ' => 'Ȅ',
73994 'ȇ' => 'Ȇ',
73995 'ȉ' => 'Ȉ',
73996 'ȋ' => 'Ȋ',
73997 'ȍ' => 'Ȍ',
73998 'ȏ' => 'Ȏ',
73999 'ȑ' => 'Ȑ',
74000 'ȓ' => 'Ȓ',
74001 'ȕ' => 'Ȕ',
74002 'ȗ' => 'Ȗ',
74003 'ș' => 'Ș',
74004 'ț' => 'Ț',
74005 'ȝ' => 'Ȝ',
74006 'ȟ' => 'Ȟ',
74007 'ȣ' => 'Ȣ',
74008 'ȥ' => 'Ȥ',
74009 'ȧ' => 'Ȧ',
74010 'ȩ' => 'Ȩ',
74011 'ȫ' => 'Ȫ',
74012 'ȭ' => 'Ȭ',
74013 'ȯ' => 'Ȯ',
74014 'ȱ' => 'Ȱ',
74015 'ȳ' => 'Ȳ',
74016 'ȼ' => 'Ȼ',
74017 'ȿ' => 'Ȿ',
74018 'ɀ' => 'Ɀ',
74019 'ɂ' => 'Ɂ',
74020 'ɇ' => 'Ɇ',
74021 'ɉ' => 'Ɉ',
74022 'ɋ' => 'Ɋ',
74023 'ɍ' => 'Ɍ',
74024 'ɏ' => 'Ɏ',
74025 'ɐ' => 'Ɐ',
74026 'ɑ' => 'Ɑ',
74027 'ɒ' => 'Ɒ',
74028 'ɓ' => 'Ɓ',
74029 'ɔ' => 'Ɔ',
74030 'ɖ' => 'Ɖ',
74031 'ɗ' => 'Ɗ',
74032 'ə' => 'Ə',
74033 'ɛ' => 'Ɛ',
74034 'ɜ' => 'Ɜ',
74035 'ɠ' => 'Ɠ',
74036 'ɡ' => 'Ɡ',
74037 'ɣ' => 'Ɣ',
74038 'ɥ' => 'Ɥ',
74039 'ɦ' => 'Ɦ',
74040 'ɨ' => 'Ɨ',
74041 'ɩ' => 'Ɩ',
74042 'ɫ' => 'Ɫ',
74043 'ɬ' => 'Ɬ',
74044 'ɯ' => 'Ɯ',
74045 'ɱ' => 'Ɱ',
74046 'ɲ' => 'Ɲ',
74047 'ɵ' => 'Ɵ',
74048 'ɽ' => 'Ɽ',
74049 'ʀ' => 'Ʀ',
74050 'ʃ' => 'Ʃ',
74051 'ʇ' => 'Ʇ',
74052 'ʈ' => 'Ʈ',
74053 'ʉ' => 'Ʉ',
74054 'ʊ' => 'Ʊ',
74055 'ʋ' => 'Ʋ',
74056 'ʌ' => 'Ʌ',
74057 'ʒ' => 'Ʒ',
74058 'ʞ' => 'Ʞ',
74059 'ͅ' => 'Ι',
74060 'ͱ' => 'Ͱ',
74061 'ͳ' => 'Ͳ',
74062 'ͷ' => 'Ͷ',
74063 'ͻ' => 'Ͻ',
74064 'ͼ' => 'Ͼ',
74065 'ͽ' => 'Ͽ',
74066 'ά' => 'Ά',
74067 'έ' => 'Έ',
74068 'ή' => 'Ή',
74069 'ί' => 'Ί',
74070 'α' => 'Α',
74071 'β' => 'Β',
74072 'γ' => 'Γ',
74073 'δ' => 'Δ',
74074 'ε' => 'Ε',
74075 'ζ' => 'Ζ',
74076 'η' => 'Η',
74077 'θ' => 'Θ',
74078 'ι' => 'Ι',
74079 'κ' => 'Κ',
74080 'λ' => 'Λ',
74081 'μ' => 'Μ',
74082 'ν' => 'Ν',
74083 'ξ' => 'Ξ',
74084 'ο' => 'Ο',
74085 'π' => 'Π',
74086 'ρ' => 'Ρ',
74087 'ς' => 'Σ',
74088 'σ' => 'Σ',
74089 'τ' => 'Τ',
74090 'υ' => 'Υ',
74091 'φ' => 'Φ',
74092 'χ' => 'Χ',
74093 'ψ' => 'Ψ',
74094 'ω' => 'Ω',
74095 'ϊ' => 'Ϊ',
74096 'ϋ' => 'Ϋ',
74097 'ό' => 'Ό',
74098 'ύ' => 'Ύ',
74099 'ώ' => 'Ώ',
74100 'ϐ' => 'Β',
74101 'ϑ' => 'Θ',
74102 'ϕ' => 'Φ',
74103 'ϖ' => 'Π',
74104 'ϗ' => 'Ϗ',
74105 'ϙ' => 'Ϙ',
74106 'ϛ' => 'Ϛ',
74107 'ϝ' => 'Ϝ',
74108 'ϟ' => 'Ϟ',
74109 'ϡ' => 'Ϡ',
74110 'ϣ' => 'Ϣ',
74111 'ϥ' => 'Ϥ',
74112 'ϧ' => 'Ϧ',
74113 'ϩ' => 'Ϩ',
74114 'ϫ' => 'Ϫ',
74115 'ϭ' => 'Ϭ',
74116 'ϯ' => 'Ϯ',
74117 'ϰ' => 'Κ',
74118 'ϱ' => 'Ρ',
74119 'ϲ' => 'Ϲ',
74120 'ϳ' => 'Ϳ',
74121 'ϵ' => 'Ε',
74122 'ϸ' => 'Ϸ',
74123 'ϻ' => 'Ϻ',
74124 'а' => 'А',
74125 'б' => 'Б',
74126 'в' => 'В',
74127 'г' => 'Г',
74128 'д' => 'Д',
74129 'е' => 'Е',
74130 'ж' => 'Ж',
74131 'з' => 'З',
74132 'и' => 'И',
74133 'й' => 'Й',
74134 'к' => 'К',
74135 'л' => 'Л',
74136 'м' => 'М',
74137 'н' => 'Н',
74138 'о' => 'О',
74139 'п' => 'П',
74140 'р' => 'Р',
74141 'с' => 'С',
74142 'т' => 'Т',
74143 'у' => 'У',
74144 'ф' => 'Ф',
74145 'х' => 'Х',
74146 'ц' => 'Ц',
74147 'ч' => 'Ч',
74148 'ш' => 'Ш',
74149 'щ' => 'Щ',
74150 'ъ' => 'Ъ',
74151 'ы' => 'Ы',
74152 'ь' => 'Ь',
74153 'э' => 'Э',
74154 'ю' => 'Ю',
74155 'я' => 'Я',
74156 'ѐ' => 'Ѐ',
74157 'ё' => 'Ё',
74158 'ђ' => 'Ђ',
74159 'ѓ' => 'Ѓ',
74160 'є' => 'Є',
74161 'ѕ' => 'Ѕ',
74162 'і' => 'І',
74163 'ї' => 'Ї',
74164 'ј' => 'Ј',
74165 'љ' => 'Љ',
74166 'њ' => 'Њ',
74167 'ћ' => 'Ћ',
74168 'ќ' => 'Ќ',
74169 'ѝ' => 'Ѝ',
74170 'ў' => 'Ў',
74171 'џ' => 'Џ',
74172 'ѡ' => 'Ѡ',
74173 'ѣ' => 'Ѣ',
74174 'ѥ' => 'Ѥ',
74175 'ѧ' => 'Ѧ',
74176 'ѩ' => 'Ѩ',
74177 'ѫ' => 'Ѫ',
74178 'ѭ' => 'Ѭ',
74179 'ѯ' => 'Ѯ',
74180 'ѱ' => 'Ѱ',
74181 'ѳ' => 'Ѳ',
74182 'ѵ' => 'Ѵ',
74183 'ѷ' => 'Ѷ',
74184 'ѹ' => 'Ѹ',
74185 'ѻ' => 'Ѻ',
74186 'ѽ' => 'Ѽ',
74187 'ѿ' => 'Ѿ',
74188 'ҁ' => 'Ҁ',
74189 'ҋ' => 'Ҋ',
74190 'ҍ' => 'Ҍ',
74191 'ҏ' => 'Ҏ',
74192 'ґ' => 'Ґ',
74193 'ғ' => 'Ғ',
74194 'ҕ' => 'Ҕ',
74195 'җ' => 'Җ',
74196 'ҙ' => 'Ҙ',
74197 'қ' => 'Қ',
74198 'ҝ' => 'Ҝ',
74199 'ҟ' => 'Ҟ',
74200 'ҡ' => 'Ҡ',
74201 'ң' => 'Ң',
74202 'ҥ' => 'Ҥ',
74203 'ҧ' => 'Ҧ',
74204 'ҩ' => 'Ҩ',
74205 'ҫ' => 'Ҫ',
74206 'ҭ' => 'Ҭ',
74207 'ү' => 'Ү',
74208 'ұ' => 'Ұ',
74209 'ҳ' => 'Ҳ',
74210 'ҵ' => 'Ҵ',
74211 'ҷ' => 'Ҷ',
74212 'ҹ' => 'Ҹ',
74213 'һ' => 'Һ',
74214 'ҽ' => 'Ҽ',
74215 'ҿ' => 'Ҿ',
74216 'ӂ' => 'Ӂ',
74217 'ӄ' => 'Ӄ',
74218 'ӆ' => 'Ӆ',
74219 'ӈ' => 'Ӈ',
74220 'ӊ' => 'Ӊ',
74221 'ӌ' => 'Ӌ',
74222 'ӎ' => 'Ӎ',
74223 'ӏ' => 'Ӏ',
74224 'ӑ' => 'Ӑ',
74225 'ӓ' => 'Ӓ',
74226 'ӕ' => 'Ӕ',
74227 'ӗ' => 'Ӗ',
74228 'ә' => 'Ә',
74229 'ӛ' => 'Ӛ',
74230 'ӝ' => 'Ӝ',
74231 'ӟ' => 'Ӟ',
74232 'ӡ' => 'Ӡ',
74233 'ӣ' => 'Ӣ',
74234 'ӥ' => 'Ӥ',
74235 'ӧ' => 'Ӧ',
74236 'ө' => 'Ө',
74237 'ӫ' => 'Ӫ',
74238 'ӭ' => 'Ӭ',
74239 'ӯ' => 'Ӯ',
74240 'ӱ' => 'Ӱ',
74241 'ӳ' => 'Ӳ',
74242 'ӵ' => 'Ӵ',
74243 'ӷ' => 'Ӷ',
74244 'ӹ' => 'Ӹ',
74245 'ӻ' => 'Ӻ',
74246 'ӽ' => 'Ӽ',
74247 'ӿ' => 'Ӿ',
74248 'ԁ' => 'Ԁ',
74249 'ԃ' => 'Ԃ',
74250 'ԅ' => 'Ԅ',
74251 'ԇ' => 'Ԇ',
74252 'ԉ' => 'Ԉ',
74253 'ԋ' => 'Ԋ',
74254 'ԍ' => 'Ԍ',
74255 'ԏ' => 'Ԏ',
74256 'ԑ' => 'Ԑ',
74257 'ԓ' => 'Ԓ',
74258 'ԕ' => 'Ԕ',
74259 'ԗ' => 'Ԗ',
74260 'ԙ' => 'Ԙ',
74261 'ԛ' => 'Ԛ',
74262 'ԝ' => 'Ԝ',
74263 'ԟ' => 'Ԟ',
74264 'ԡ' => 'Ԡ',
74265 'ԣ' => 'Ԣ',
74266 'ԥ' => 'Ԥ',
74267 'ԧ' => 'Ԧ',
74268 'ԩ' => 'Ԩ',
74269 'ԫ' => 'Ԫ',
74270 'ԭ' => 'Ԭ',
74271 'ԯ' => 'Ԯ',
74272 'ա' => 'Ա',
74273 'բ' => 'Բ',
74274 'գ' => 'Գ',
74275 'դ' => 'Դ',
74276 'ե' => 'Ե',
74277 'զ' => 'Զ',
74278 'է' => 'Է',
74279 'ը' => 'Ը',
74280 'թ' => 'Թ',
74281 'ժ' => 'Ժ',
74282 'ի' => 'Ի',
74283 'լ' => 'Լ',
74284 'խ' => 'Խ',
74285 'ծ' => 'Ծ',
74286 'կ' => 'Կ',
74287 'հ' => 'Հ',
74288 'ձ' => 'Ձ',
74289 'ղ' => 'Ղ',
74290 'ճ' => 'Ճ',
74291 'մ' => 'Մ',
74292 'յ' => 'Յ',
74293 'ն' => 'Ն',
74294 'շ' => 'Շ',
74295 'ո' => 'Ո',
74296 'չ' => 'Չ',
74297 'պ' => 'Պ',
74298 'ջ' => 'Ջ',
74299 'ռ' => 'Ռ',
74300 'ս' => 'Ս',
74301 'վ' => 'Վ',
74302 'տ' => 'Տ',
74303 'ր' => 'Ր',
74304 'ց' => 'Ց',
74305 'ւ' => 'Ւ',
74306 'փ' => 'Փ',
74307 'ք' => 'Ք',
74308 'օ' => 'Օ',
74309 'ֆ' => 'Ֆ',
74310 'ᵹ' => 'Ᵹ',
74311 'ᵽ' => 'Ᵽ',
74312 'ḁ' => 'Ḁ',
74313 'ḃ' => 'Ḃ',
74314 'ḅ' => 'Ḅ',
74315 'ḇ' => 'Ḇ',
74316 'ḉ' => 'Ḉ',
74317 'ḋ' => 'Ḋ',
74318 'ḍ' => 'Ḍ',
74319 'ḏ' => 'Ḏ',
74320 'ḑ' => 'Ḑ',
74321 'ḓ' => 'Ḓ',
74322 'ḕ' => 'Ḕ',
74323 'ḗ' => 'Ḗ',
74324 'ḙ' => 'Ḙ',
74325 'ḛ' => 'Ḛ',
74326 'ḝ' => 'Ḝ',
74327 'ḟ' => 'Ḟ',
74328 'ḡ' => 'Ḡ',
74329 'ḣ' => 'Ḣ',
74330 'ḥ' => 'Ḥ',
74331 'ḧ' => 'Ḧ',
74332 'ḩ' => 'Ḩ',
74333 'ḫ' => 'Ḫ',
74334 'ḭ' => 'Ḭ',
74335 'ḯ' => 'Ḯ',
74336 'ḱ' => 'Ḱ',
74337 'ḳ' => 'Ḳ',
74338 'ḵ' => 'Ḵ',
74339 'ḷ' => 'Ḷ',
74340 'ḹ' => 'Ḹ',
74341 'ḻ' => 'Ḻ',
74342 'ḽ' => 'Ḽ',
74343 'ḿ' => 'Ḿ',
74344 'ṁ' => 'Ṁ',
74345 'ṃ' => 'Ṃ',
74346 'ṅ' => 'Ṅ',
74347 'ṇ' => 'Ṇ',
74348 'ṉ' => 'Ṉ',
74349 'ṋ' => 'Ṋ',
74350 'ṍ' => 'Ṍ',
74351 'ṏ' => 'Ṏ',
74352 'ṑ' => 'Ṑ',
74353 'ṓ' => 'Ṓ',
74354 'ṕ' => 'Ṕ',
74355 'ṗ' => 'Ṗ',
74356 'ṙ' => 'Ṙ',
74357 'ṛ' => 'Ṛ',
74358 'ṝ' => 'Ṝ',
74359 'ṟ' => 'Ṟ',
74360 'ṡ' => 'Ṡ',
74361 'ṣ' => 'Ṣ',
74362 'ṥ' => 'Ṥ',
74363 'ṧ' => 'Ṧ',
74364 'ṩ' => 'Ṩ',
74365 'ṫ' => 'Ṫ',
74366 'ṭ' => 'Ṭ',
74367 'ṯ' => 'Ṯ',
74368 'ṱ' => 'Ṱ',
74369 'ṳ' => 'Ṳ',
74370 'ṵ' => 'Ṵ',
74371 'ṷ' => 'Ṷ',
74372 'ṹ' => 'Ṹ',
74373 'ṻ' => 'Ṻ',
74374 'ṽ' => 'Ṽ',
74375 'ṿ' => 'Ṿ',
74376 'ẁ' => 'Ẁ',
74377 'ẃ' => 'Ẃ',
74378 'ẅ' => 'Ẅ',
74379 'ẇ' => 'Ẇ',
74380 'ẉ' => 'Ẉ',
74381 'ẋ' => 'Ẋ',
74382 'ẍ' => 'Ẍ',
74383 'ẏ' => 'Ẏ',
74384 'ẑ' => 'Ẑ',
74385 'ẓ' => 'Ẓ',
74386 'ẕ' => 'Ẕ',
74387 'ẛ' => 'Ṡ',
74388 'ạ' => 'Ạ',
74389 'ả' => 'Ả',
74390 'ấ' => 'Ấ',
74391 'ầ' => 'Ầ',
74392 'ẩ' => 'Ẩ',
74393 'ẫ' => 'Ẫ',
74394 'ậ' => 'Ậ',
74395 'ắ' => 'Ắ',
74396 'ằ' => 'Ằ',
74397 'ẳ' => 'Ẳ',
74398 'ẵ' => 'Ẵ',
74399 'ặ' => 'Ặ',
74400 'ẹ' => 'Ẹ',
74401 'ẻ' => 'Ẻ',
74402 'ẽ' => 'Ẽ',
74403 'ế' => 'Ế',
74404 'ề' => 'Ề',
74405 'ể' => 'Ể',
74406 'ễ' => 'Ễ',
74407 'ệ' => 'Ệ',
74408 'ỉ' => 'Ỉ',
74409 'ị' => 'Ị',
74410 'ọ' => 'Ọ',
74411 'ỏ' => 'Ỏ',
74412 'ố' => 'Ố',
74413 'ồ' => 'Ồ',
74414 'ổ' => 'Ổ',
74415 'ỗ' => 'Ỗ',
74416 'ộ' => 'Ộ',
74417 'ớ' => 'Ớ',
74418 'ờ' => 'Ờ',
74419 'ở' => 'Ở',
74420 'ỡ' => 'Ỡ',
74421 'ợ' => 'Ợ',
74422 'ụ' => 'Ụ',
74423 'ủ' => 'Ủ',
74424 'ứ' => 'Ứ',
74425 'ừ' => 'Ừ',
74426 'ử' => 'Ử',
74427 'ữ' => 'Ữ',
74428 'ự' => 'Ự',
74429 'ỳ' => 'Ỳ',
74430 'ỵ' => 'Ỵ',
74431 'ỷ' => 'Ỷ',
74432 'ỹ' => 'Ỹ',
74433 'ỻ' => 'Ỻ',
74434 'ỽ' => 'Ỽ',
74435 'ỿ' => 'Ỿ',
74436 'ἀ' => 'Ἀ',
74437 'ἁ' => 'Ἁ',
74438 'ἂ' => 'Ἂ',
74439 'ἃ' => 'Ἃ',
74440 'ἄ' => 'Ἄ',
74441 'ἅ' => 'Ἅ',
74442 'ἆ' => 'Ἆ',
74443 'ἇ' => 'Ἇ',
74444 'ἐ' => 'Ἐ',
74445 'ἑ' => 'Ἑ',
74446 'ἒ' => 'Ἒ',
74447 'ἓ' => 'Ἓ',
74448 'ἔ' => 'Ἔ',
74449 'ἕ' => 'Ἕ',
74450 'ἠ' => 'Ἠ',
74451 'ἡ' => 'Ἡ',
74452 'ἢ' => 'Ἢ',
74453 'ἣ' => 'Ἣ',
74454 'ἤ' => 'Ἤ',
74455 'ἥ' => 'Ἥ',
74456 'ἦ' => 'Ἦ',
74457 'ἧ' => 'Ἧ',
74458 'ἰ' => 'Ἰ',
74459 'ἱ' => 'Ἱ',
74460 'ἲ' => 'Ἲ',
74461 'ἳ' => 'Ἳ',
74462 'ἴ' => 'Ἴ',
74463 'ἵ' => 'Ἵ',
74464 'ἶ' => 'Ἶ',
74465 'ἷ' => 'Ἷ',
74466 'ὀ' => 'Ὀ',
74467 'ὁ' => 'Ὁ',
74468 'ὂ' => 'Ὂ',
74469 'ὃ' => 'Ὃ',
74470 'ὄ' => 'Ὄ',
74471 'ὅ' => 'Ὅ',
74472 'ὑ' => 'Ὑ',
74473 'ὓ' => 'Ὓ',
74474 'ὕ' => 'Ὕ',
74475 'ὗ' => 'Ὗ',
74476 'ὠ' => 'Ὠ',
74477 'ὡ' => 'Ὡ',
74478 'ὢ' => 'Ὢ',
74479 'ὣ' => 'Ὣ',
74480 'ὤ' => 'Ὤ',
74481 'ὥ' => 'Ὥ',
74482 'ὦ' => 'Ὦ',
74483 'ὧ' => 'Ὧ',
74484 'ὰ' => 'Ὰ',
74485 'ά' => 'Ά',
74486 'ὲ' => 'Ὲ',
74487 'έ' => 'Έ',
74488 'ὴ' => 'Ὴ',
74489 'ή' => 'Ή',
74490 'ὶ' => 'Ὶ',
74491 'ί' => 'Ί',
74492 'ὸ' => 'Ὸ',
74493 'ό' => 'Ό',
74494 'ὺ' => 'Ὺ',
74495 'ύ' => 'Ύ',
74496 'ὼ' => 'Ὼ',
74497 'ώ' => 'Ώ',
74498 'ᾀ' => 'ᾈ',
74499 'ᾁ' => 'ᾉ',
74500 'ᾂ' => 'ᾊ',
74501 'ᾃ' => 'ᾋ',
74502 'ᾄ' => 'ᾌ',
74503 'ᾅ' => 'ᾍ',
74504 'ᾆ' => 'ᾎ',
74505 'ᾇ' => 'ᾏ',
74506 'ᾐ' => 'ᾘ',
74507 'ᾑ' => 'ᾙ',
74508 'ᾒ' => 'ᾚ',
74509 'ᾓ' => 'ᾛ',
74510 'ᾔ' => 'ᾜ',
74511 'ᾕ' => 'ᾝ',
74512 'ᾖ' => 'ᾞ',
74513 'ᾗ' => 'ᾟ',
74514 'ᾠ' => 'ᾨ',
74515 'ᾡ' => 'ᾩ',
74516 'ᾢ' => 'ᾪ',
74517 'ᾣ' => 'ᾫ',
74518 'ᾤ' => 'ᾬ',
74519 'ᾥ' => 'ᾭ',
74520 'ᾦ' => 'ᾮ',
74521 'ᾧ' => 'ᾯ',
74522 'ᾰ' => 'Ᾰ',
74523 'ᾱ' => 'Ᾱ',
74524 'ᾳ' => 'ᾼ',
74525 'ι' => 'Ι',
74526 'ῃ' => 'ῌ',
74527 'ῐ' => 'Ῐ',
74528 'ῑ' => 'Ῑ',
74529 'ῠ' => 'Ῠ',
74530 'ῡ' => 'Ῡ',
74531 'ῥ' => 'Ῥ',
74532 'ῳ' => 'ῼ',
74533 'ⅎ' => 'Ⅎ',
74534 'ⅰ' => 'Ⅰ',
74535 'ⅱ' => 'Ⅱ',
74536 'ⅲ' => 'Ⅲ',
74537 'ⅳ' => 'Ⅳ',
74538 'ⅴ' => 'Ⅴ',
74539 'ⅵ' => 'Ⅵ',
74540 'ⅶ' => 'Ⅶ',
74541 'ⅷ' => 'Ⅷ',
74542 'ⅸ' => 'Ⅸ',
74543 'ⅹ' => 'Ⅹ',
74544 'ⅺ' => 'Ⅺ',
74545 'ⅻ' => 'Ⅻ',
74546 'ⅼ' => 'Ⅼ',
74547 'ⅽ' => 'Ⅽ',
74548 'ⅾ' => 'Ⅾ',
74549 'ⅿ' => 'Ⅿ',
74550 'ↄ' => 'Ↄ',
74551 'ⓐ' => 'Ⓐ',
74552 'ⓑ' => 'Ⓑ',
74553 'ⓒ' => 'Ⓒ',
74554 'ⓓ' => 'Ⓓ',
74555 'ⓔ' => 'Ⓔ',
74556 'ⓕ' => 'Ⓕ',
74557 'ⓖ' => 'Ⓖ',
74558 'ⓗ' => 'Ⓗ',
74559 'ⓘ' => 'Ⓘ',
74560 'ⓙ' => 'Ⓙ',
74561 'ⓚ' => 'Ⓚ',
74562 'ⓛ' => 'Ⓛ',
74563 'ⓜ' => 'Ⓜ',
74564 'ⓝ' => 'Ⓝ',
74565 'ⓞ' => 'Ⓞ',
74566 'ⓟ' => 'Ⓟ',
74567 'ⓠ' => 'Ⓠ',
74568 'ⓡ' => 'Ⓡ',
74569 'ⓢ' => 'Ⓢ',
74570 'ⓣ' => 'Ⓣ',
74571 'ⓤ' => 'Ⓤ',
74572 'ⓥ' => 'Ⓥ',
74573 'ⓦ' => 'Ⓦ',
74574 'ⓧ' => 'Ⓧ',
74575 'ⓨ' => 'Ⓨ',
74576 'ⓩ' => 'Ⓩ',
74577 'ⰰ' => 'Ⰰ',
74578 'ⰱ' => 'Ⰱ',
74579 'ⰲ' => 'Ⰲ',
74580 'ⰳ' => 'Ⰳ',
74581 'ⰴ' => 'Ⰴ',
74582 'ⰵ' => 'Ⰵ',
74583 'ⰶ' => 'Ⰶ',
74584 'ⰷ' => 'Ⰷ',
74585 'ⰸ' => 'Ⰸ',
74586 'ⰹ' => 'Ⰹ',
74587 'ⰺ' => 'Ⰺ',
74588 'ⰻ' => 'Ⰻ',
74589 'ⰼ' => 'Ⰼ',
74590 'ⰽ' => 'Ⰽ',
74591 'ⰾ' => 'Ⰾ',
74592 'ⰿ' => 'Ⰿ',
74593 'ⱀ' => 'Ⱀ',
74594 'ⱁ' => 'Ⱁ',
74595 'ⱂ' => 'Ⱂ',
74596 'ⱃ' => 'Ⱃ',
74597 'ⱄ' => 'Ⱄ',
74598 'ⱅ' => 'Ⱅ',
74599 'ⱆ' => 'Ⱆ',
74600 'ⱇ' => 'Ⱇ',
74601 'ⱈ' => 'Ⱈ',
74602 'ⱉ' => 'Ⱉ',
74603 'ⱊ' => 'Ⱊ',
74604 'ⱋ' => 'Ⱋ',
74605 'ⱌ' => 'Ⱌ',
74606 'ⱍ' => 'Ⱍ',
74607 'ⱎ' => 'Ⱎ',
74608 'ⱏ' => 'Ⱏ',
74609 'ⱐ' => 'Ⱐ',
74610 'ⱑ' => 'Ⱑ',
74611 'ⱒ' => 'Ⱒ',
74612 'ⱓ' => 'Ⱓ',
74613 'ⱔ' => 'Ⱔ',
74614 'ⱕ' => 'Ⱕ',
74615 'ⱖ' => 'Ⱖ',
74616 'ⱗ' => 'Ⱗ',
74617 'ⱘ' => 'Ⱘ',
74618 'ⱙ' => 'Ⱙ',
74619 'ⱚ' => 'Ⱚ',
74620 'ⱛ' => 'Ⱛ',
74621 'ⱜ' => 'Ⱜ',
74622 'ⱝ' => 'Ⱝ',
74623 'ⱞ' => 'Ⱞ',
74624 'ⱡ' => 'Ⱡ',
74625 'ⱥ' => 'Ⱥ',
74626 'ⱦ' => 'Ⱦ',
74627 'ⱨ' => 'Ⱨ',
74628 'ⱪ' => 'Ⱪ',
74629 'ⱬ' => 'Ⱬ',
74630 'ⱳ' => 'Ⱳ',
74631 'ⱶ' => 'Ⱶ',
74632 'ⲁ' => 'Ⲁ',
74633 'ⲃ' => 'Ⲃ',
74634 'ⲅ' => 'Ⲅ',
74635 'ⲇ' => 'Ⲇ',
74636 'ⲉ' => 'Ⲉ',
74637 'ⲋ' => 'Ⲋ',
74638 'ⲍ' => 'Ⲍ',
74639 'ⲏ' => 'Ⲏ',
74640 'ⲑ' => 'Ⲑ',
74641 'ⲓ' => 'Ⲓ',
74642 'ⲕ' => 'Ⲕ',
74643 'ⲗ' => 'Ⲗ',
74644 'ⲙ' => 'Ⲙ',
74645 'ⲛ' => 'Ⲛ',
74646 'ⲝ' => 'Ⲝ',
74647 'ⲟ' => 'Ⲟ',
74648 'ⲡ' => 'Ⲡ',
74649 'ⲣ' => 'Ⲣ',
74650 'ⲥ' => 'Ⲥ',
74651 'ⲧ' => 'Ⲧ',
74652 'ⲩ' => 'Ⲩ',
74653 'ⲫ' => 'Ⲫ',
74654 'ⲭ' => 'Ⲭ',
74655 'ⲯ' => 'Ⲯ',
74656 'ⲱ' => 'Ⲱ',
74657 'ⲳ' => 'Ⲳ',
74658 'ⲵ' => 'Ⲵ',
74659 'ⲷ' => 'Ⲷ',
74660 'ⲹ' => 'Ⲹ',
74661 'ⲻ' => 'Ⲻ',
74662 'ⲽ' => 'Ⲽ',
74663 'ⲿ' => 'Ⲿ',
74664 'ⳁ' => 'Ⳁ',
74665 'ⳃ' => 'Ⳃ',
74666 'ⳅ' => 'Ⳅ',
74667 'ⳇ' => 'Ⳇ',
74668 'ⳉ' => 'Ⳉ',
74669 'ⳋ' => 'Ⳋ',
74670 'ⳍ' => 'Ⳍ',
74671 'ⳏ' => 'Ⳏ',
74672 'ⳑ' => 'Ⳑ',
74673 'ⳓ' => 'Ⳓ',
74674 'ⳕ' => 'Ⳕ',
74675 'ⳗ' => 'Ⳗ',
74676 'ⳙ' => 'Ⳙ',
74677 'ⳛ' => 'Ⳛ',
74678 'ⳝ' => 'Ⳝ',
74679 'ⳟ' => 'Ⳟ',
74680 'ⳡ' => 'Ⳡ',
74681 'ⳣ' => 'Ⳣ',
74682 'ⳬ' => 'Ⳬ',
74683 'ⳮ' => 'Ⳮ',
74684 'ⳳ' => 'Ⳳ',
74685 'ⴀ' => 'Ⴀ',
74686 'ⴁ' => 'Ⴁ',
74687 'ⴂ' => 'Ⴂ',
74688 'ⴃ' => 'Ⴃ',
74689 'ⴄ' => 'Ⴄ',
74690 'ⴅ' => 'Ⴅ',
74691 'ⴆ' => 'Ⴆ',
74692 'ⴇ' => 'Ⴇ',
74693 'ⴈ' => 'Ⴈ',
74694 'ⴉ' => 'Ⴉ',
74695 'ⴊ' => 'Ⴊ',
74696 'ⴋ' => 'Ⴋ',
74697 'ⴌ' => 'Ⴌ',
74698 'ⴍ' => 'Ⴍ',
74699 'ⴎ' => 'Ⴎ',
74700 'ⴏ' => 'Ⴏ',
74701 'ⴐ' => 'Ⴐ',
74702 'ⴑ' => 'Ⴑ',
74703 'ⴒ' => 'Ⴒ',
74704 'ⴓ' => 'Ⴓ',
74705 'ⴔ' => 'Ⴔ',
74706 'ⴕ' => 'Ⴕ',
74707 'ⴖ' => 'Ⴖ',
74708 'ⴗ' => 'Ⴗ',
74709 'ⴘ' => 'Ⴘ',
74710 'ⴙ' => 'Ⴙ',
74711 'ⴚ' => 'Ⴚ',
74712 'ⴛ' => 'Ⴛ',
74713 'ⴜ' => 'Ⴜ',
74714 'ⴝ' => 'Ⴝ',
74715 'ⴞ' => 'Ⴞ',
74716 'ⴟ' => 'Ⴟ',
74717 'ⴠ' => 'Ⴠ',
74718 'ⴡ' => 'Ⴡ',
74719 'ⴢ' => 'Ⴢ',
74720 'ⴣ' => 'Ⴣ',
74721 'ⴤ' => 'Ⴤ',
74722 'ⴥ' => 'Ⴥ',
74723 'ⴧ' => 'Ⴧ',
74724 'ⴭ' => 'Ⴭ',
74725 'ꙁ' => 'Ꙁ',
74726 'ꙃ' => 'Ꙃ',
74727 'ꙅ' => 'Ꙅ',
74728 'ꙇ' => 'Ꙇ',
74729 'ꙉ' => 'Ꙉ',
74730 'ꙋ' => 'Ꙋ',
74731 'ꙍ' => 'Ꙍ',
74732 'ꙏ' => 'Ꙏ',
74733 'ꙑ' => 'Ꙑ',
74734 'ꙓ' => 'Ꙓ',
74735 'ꙕ' => 'Ꙕ',
74736 'ꙗ' => 'Ꙗ',
74737 'ꙙ' => 'Ꙙ',
74738 'ꙛ' => 'Ꙛ',
74739 'ꙝ' => 'Ꙝ',
74740 'ꙟ' => 'Ꙟ',
74741 'ꙡ' => 'Ꙡ',
74742 'ꙣ' => 'Ꙣ',
74743 'ꙥ' => 'Ꙥ',
74744 'ꙧ' => 'Ꙧ',
74745 'ꙩ' => 'Ꙩ',
74746 'ꙫ' => 'Ꙫ',
74747 'ꙭ' => 'Ꙭ',
74748 'ꚁ' => 'Ꚁ',
74749 'ꚃ' => 'Ꚃ',
74750 'ꚅ' => 'Ꚅ',
74751 'ꚇ' => 'Ꚇ',
74752 'ꚉ' => 'Ꚉ',
74753 'ꚋ' => 'Ꚋ',
74754 'ꚍ' => 'Ꚍ',
74755 'ꚏ' => 'Ꚏ',
74756 'ꚑ' => 'Ꚑ',
74757 'ꚓ' => 'Ꚓ',
74758 'ꚕ' => 'Ꚕ',
74759 'ꚗ' => 'Ꚗ',
74760 'ꚙ' => 'Ꚙ',
74761 'ꚛ' => 'Ꚛ',
74762 'ꜣ' => 'Ꜣ',
74763 'ꜥ' => 'Ꜥ',
74764 'ꜧ' => 'Ꜧ',
74765 'ꜩ' => 'Ꜩ',
74766 'ꜫ' => 'Ꜫ',
74767 'ꜭ' => 'Ꜭ',
74768 'ꜯ' => 'Ꜯ',
74769 'ꜳ' => 'Ꜳ',
74770 'ꜵ' => 'Ꜵ',
74771 'ꜷ' => 'Ꜷ',
74772 'ꜹ' => 'Ꜹ',
74773 'ꜻ' => 'Ꜻ',
74774 'ꜽ' => 'Ꜽ',
74775 'ꜿ' => 'Ꜿ',
74776 'ꝁ' => 'Ꝁ',
74777 'ꝃ' => 'Ꝃ',
74778 'ꝅ' => 'Ꝅ',
74779 'ꝇ' => 'Ꝇ',
74780 'ꝉ' => 'Ꝉ',
74781 'ꝋ' => 'Ꝋ',
74782 'ꝍ' => 'Ꝍ',
74783 'ꝏ' => 'Ꝏ',
74784 'ꝑ' => 'Ꝑ',
74785 'ꝓ' => 'Ꝓ',
74786 'ꝕ' => 'Ꝕ',
74787 'ꝗ' => 'Ꝗ',
74788 'ꝙ' => 'Ꝙ',
74789 'ꝛ' => 'Ꝛ',
74790 'ꝝ' => 'Ꝝ',
74791 'ꝟ' => 'Ꝟ',
74792 'ꝡ' => 'Ꝡ',
74793 'ꝣ' => 'Ꝣ',
74794 'ꝥ' => 'Ꝥ',
74795 'ꝧ' => 'Ꝧ',
74796 'ꝩ' => 'Ꝩ',
74797 'ꝫ' => 'Ꝫ',
74798 'ꝭ' => 'Ꝭ',
74799 'ꝯ' => 'Ꝯ',
74800 'ꝺ' => 'Ꝺ',
74801 'ꝼ' => 'Ꝼ',
74802 'ꝿ' => 'Ꝿ',
74803 'ꞁ' => 'Ꞁ',
74804 'ꞃ' => 'Ꞃ',
74805 'ꞅ' => 'Ꞅ',
74806 'ꞇ' => 'Ꞇ',
74807 'ꞌ' => 'Ꞌ',
74808 'ꞑ' => 'Ꞑ',
74809 'ꞓ' => 'Ꞓ',
74810 'ꞗ' => 'Ꞗ',
74811 'ꞙ' => 'Ꞙ',
74812 'ꞛ' => 'Ꞛ',
74813 'ꞝ' => 'Ꞝ',
74814 'ꞟ' => 'Ꞟ',
74815 'ꞡ' => 'Ꞡ',
74816 'ꞣ' => 'Ꞣ',
74817 'ꞥ' => 'Ꞥ',
74818 'ꞧ' => 'Ꞧ',
74819 'ꞩ' => 'Ꞩ',
74820 'a' => 'A',
74821 'b' => 'B',
74822 'c' => 'C',
74823 'd' => 'D',
74824 'e' => 'E',
74825 'f' => 'F',
74826 'g' => 'G',
74827 'h' => 'H',
74828 'i' => 'I',
74829 'j' => 'J',
74830 'k' => 'K',
74831 'l' => 'L',
74832 'm' => 'M',
74833 'n' => 'N',
74834 'o' => 'O',
74835 'p' => 'P',
74836 'q' => 'Q',
74837 'r' => 'R',
74838 's' => 'S',
74839 't' => 'T',
74840 'u' => 'U',
74841 'v' => 'V',
74842 'w' => 'W',
74843 'x' => 'X',
74844 'y' => 'Y',
74845 'z' => 'Z',
74846 '𐐨' => '𐐀',
74847 '𐐩' => '𐐁',
74848 '𐐪' => '𐐂',
74849 '𐐫' => '𐐃',
74850 '𐐬' => '𐐄',
74851 '𐐭' => '𐐅',
74852 '𐐮' => '𐐆',
74853 '𐐯' => '𐐇',
74854 '𐐰' => '𐐈',
74855 '𐐱' => '𐐉',
74856 '𐐲' => '𐐊',
74857 '𐐳' => '𐐋',
74858 '𐐴' => '𐐌',
74859 '𐐵' => '𐐍',
74860 '𐐶' => '𐐎',
74861 '𐐷' => '𐐏',
74862 '𐐸' => '𐐐',
74863 '𐐹' => '𐐑',
74864 '𐐺' => '𐐒',
74865 '𐐻' => '𐐓',
74866 '𐐼' => '𐐔',
74867 '𐐽' => '𐐕',
74868 '𐐾' => '𐐖',
74869 '𐐿' => '𐐗',
74870 '𐑀' => '𐐘',
74871 '𐑁' => '𐐙',
74872 '𐑂' => '𐐚',
74873 '𐑃' => '𐐛',
74874 '𐑄' => '𐐜',
74875 '𐑅' => '𐐝',
74876 '𐑆' => '𐐞',
74877 '𐑇' => '𐐟',
74878 '𐑈' => '𐐠',
74879 '𐑉' => '𐐡',
74880 '𐑊' => '𐐢',
74881 '𐑋' => '𐐣',
74882 '𐑌' => '𐐤',
74883 '𐑍' => '𐐥',
74884 '𐑎' => '𐐦',
74885 '𐑏' => '𐐧',
74886 '𑣀' => '𑢠',
74887 '𑣁' => '𑢡',
74888 '𑣂' => '𑢢',
74889 '𑣃' => '𑢣',
74890 '𑣄' => '𑢤',
74891 '𑣅' => '𑢥',
74892 '𑣆' => '𑢦',
74893 '𑣇' => '𑢧',
74894 '𑣈' => '𑢨',
74895 '𑣉' => '𑢩',
74896 '𑣊' => '𑢪',
74897 '𑣋' => '𑢫',
74898 '𑣌' => '𑢬',
74899 '𑣍' => '𑢭',
74900 '𑣎' => '𑢮',
74901 '𑣏' => '𑢯',
74902 '𑣐' => '𑢰',
74903 '𑣑' => '𑢱',
74904 '𑣒' => '𑢲',
74905 '𑣓' => '𑢳',
74906 '𑣔' => '𑢴',
74907 '𑣕' => '𑢵',
74908 '𑣖' => '𑢶',
74909 '𑣗' => '𑢷',
74910 '𑣘' => '𑢸',
74911 '𑣙' => '𑢹',
74912 '𑣚' => '𑢺',
74913 '𑣛' => '𑢻',
74914 '𑣜' => '𑢼',
74915 '𑣝' => '𑢽',
74916 '𑣞' => '𑢾',
74917 '𑣟' => '𑢿',
74918 );
74919 <?php
74920
74921
74922
74923
74924
74925
74926
74927
74928
74929
74930 use Symfony\Polyfill\Mbstring as p;
74931
74932 if (!function_exists('mb_strlen')) {
74933 define('MB_CASE_UPPER', 0);
74934 define('MB_CASE_LOWER', 1);
74935 define('MB_CASE_TITLE', 2);
74936
74937 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
74938 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
74939 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
74940 function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
74941 function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
74942 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
74943 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
74944 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
74945 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
74946 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
74947 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
74948 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
74949 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
74950 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
74951 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
74952 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
74953 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
74954 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
74955 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
74956 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
74957 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
74958 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
74959 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
74960 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
74961 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
74962 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
74963 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
74964 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
74965 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
74966 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
74967 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
74968 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
74969 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
74970 function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); }
74971 }
74972 if (!function_exists('mb_chr')) {
74973 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
74974 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
74975 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
74976 }
74977
74978 if (!function_exists('mb_str_split')) {
74979 function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
74980 }
74981 <?php
74982
74983
74984
74985
74986
74987
74988
74989
74990
74991
74992 namespace Symfony\Component\Process\Exception;
74993
74994
74995
74996
74997
74998
74999 interface ExceptionInterface
75000 {
75001 }
75002 <?php
75003
75004
75005
75006
75007
75008
75009
75010
75011
75012
75013 namespace Symfony\Component\Process\Exception;
75014
75015
75016
75017
75018
75019
75020 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
75021 {
75022 }
75023 <?php
75024
75025
75026
75027
75028
75029
75030
75031
75032
75033
75034 namespace Symfony\Component\Process\Exception;
75035
75036
75037
75038
75039
75040
75041 class LogicException extends \LogicException implements ExceptionInterface
75042 {
75043 }
75044 <?php
75045
75046
75047
75048
75049
75050
75051
75052
75053
75054
75055 namespace Symfony\Component\Process\Exception;
75056
75057 use Symfony\Component\Process\Process;
75058
75059
75060
75061
75062
75063
75064 class ProcessFailedException extends RuntimeException
75065 {
75066 private $process;
75067
75068 public function __construct(Process $process)
75069 {
75070 if ($process->isSuccessful()) {
75071 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
75072 }
75073
75074 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
75075 $process->getCommandLine(),
75076 $process->getExitCode(),
75077 $process->getExitCodeText(),
75078 $process->getWorkingDirectory()
75079 );
75080
75081 if (!$process->isOutputDisabled()) {
75082 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
75083 $process->getOutput(),
75084 $process->getErrorOutput()
75085 );
75086 }
75087
75088 parent::__construct($error);
75089
75090 $this->process = $process;
75091 }
75092
75093 public function getProcess()
75094 {
75095 return $this->process;
75096 }
75097 }
75098 <?php
75099
75100
75101
75102
75103
75104
75105
75106
75107
75108
75109 namespace Symfony\Component\Process\Exception;
75110
75111 use Symfony\Component\Process\Process;
75112
75113
75114
75115
75116
75117
75118 class ProcessTimedOutException extends RuntimeException
75119 {
75120 const TYPE_GENERAL = 1;
75121 const TYPE_IDLE = 2;
75122
75123 private $process;
75124 private $timeoutType;
75125
75126 public function __construct(Process $process, $timeoutType)
75127 {
75128 $this->process = $process;
75129 $this->timeoutType = $timeoutType;
75130
75131 parent::__construct(sprintf(
75132 'The process "%s" exceeded the timeout of %s seconds.',
75133 $process->getCommandLine(),
75134 $this->getExceededTimeout()
75135 ));
75136 }
75137
75138 public function getProcess()
75139 {
75140 return $this->process;
75141 }
75142
75143 public function isGeneralTimeout()
75144 {
75145 return self::TYPE_GENERAL === $this->timeoutType;
75146 }
75147
75148 public function isIdleTimeout()
75149 {
75150 return self::TYPE_IDLE === $this->timeoutType;
75151 }
75152
75153 public function getExceededTimeout()
75154 {
75155 switch ($this->timeoutType) {
75156 case self::TYPE_GENERAL:
75157 return $this->process->getTimeout();
75158
75159 case self::TYPE_IDLE:
75160 return $this->process->getIdleTimeout();
75161
75162 default:
75163 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
75164 }
75165 }
75166 }
75167 <?php
75168
75169
75170
75171
75172
75173
75174
75175
75176
75177
75178 namespace Symfony\Component\Process\Exception;
75179
75180
75181
75182
75183
75184
75185 class RuntimeException extends \RuntimeException implements ExceptionInterface
75186 {
75187 }
75188 <?php
75189
75190
75191
75192
75193
75194
75195
75196
75197
75198
75199 namespace Symfony\Component\Process;
75200
75201
75202
75203
75204
75205
75206
75207 class ExecutableFinder
75208 {
75209 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
75210
75211
75212
75213
75214 public function setSuffixes(array $suffixes)
75215 {
75216 $this->suffixes = $suffixes;
75217 }
75218
75219
75220
75221
75222
75223
75224 public function addSuffix($suffix)
75225 {
75226 $this->suffixes[] = $suffix;
75227 }
75228
75229
75230
75231
75232
75233
75234
75235
75236
75237
75238 public function find($name, $default = null, array $extraDirs = array())
75239 {
75240 if (ini_get('open_basedir')) {
75241 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
75242 $dirs = array();
75243 foreach ($searchPath as $path) {
75244
75245  if (@is_dir($path)) {
75246 $dirs[] = $path;
75247 } else {
75248 if (basename($path) == $name && @is_executable($path)) {
75249 return $path;
75250 }
75251 }
75252 }
75253 } else {
75254 $dirs = array_merge(
75255 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
75256 $extraDirs
75257 );
75258 }
75259
75260 $suffixes = array('');
75261 if ('\\' === \DIRECTORY_SEPARATOR) {
75262 $pathExt = getenv('PATHEXT');
75263 $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
75264 }
75265 foreach ($suffixes as $suffix) {
75266 foreach ($dirs as $dir) {
75267 if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
75268 return $file;
75269 }
75270 }
75271 }
75272
75273 return $default;
75274 }
75275 }
75276 Copyright (c) 2004-2018 Fabien Potencier
75277
75278 Permission is hereby granted, free of charge, to any person obtaining a copy
75279 of this software and associated documentation files (the "Software"), to deal
75280 in the Software without restriction, including without limitation the rights
75281 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75282 copies of the Software, and to permit persons to whom the Software is furnished
75283 to do so, subject to the following conditions:
75284
75285 The above copyright notice and this permission notice shall be included in all
75286 copies or substantial portions of the Software.
75287
75288 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75289 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75290 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75291 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75292 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75293 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75294 THE SOFTWARE.
75295 <?php
75296
75297
75298
75299
75300
75301
75302
75303
75304
75305
75306 namespace Symfony\Component\Process;
75307
75308
75309
75310
75311
75312
75313
75314 class PhpExecutableFinder
75315 {
75316 private $executableFinder;
75317
75318 public function __construct()
75319 {
75320 $this->executableFinder = new ExecutableFinder();
75321 }
75322
75323
75324
75325
75326
75327
75328
75329
75330 public function find($includeArgs = true)
75331 {
75332 $args = $this->findArguments();
75333 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
75334
75335
75336  if (\defined('HHVM_VERSION')) {
75337 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
75338 }
75339
75340
75341  if (\defined('PHP_BINARY') && PHP_BINARY && \in_array(\PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) {
75342 return PHP_BINARY.$args;
75343 }
75344
75345 if ($php = getenv('PHP_PATH')) {
75346 if (!@is_executable($php)) {
75347 return false;
75348 }
75349
75350 return $php;
75351 }
75352
75353 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
75354 if (@is_executable($php)) {
75355 return $php;
75356 }
75357 }
75358
75359 if (@is_executable($php = PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
75360 return $php;
75361 }
75362
75363 $dirs = array(PHP_BINDIR);
75364 if ('\\' === \DIRECTORY_SEPARATOR) {
75365 $dirs[] = 'C:\xampp\php\\';
75366 }
75367
75368 return $this->executableFinder->find('php', false, $dirs);
75369 }
75370
75371
75372
75373
75374
75375
75376 public function findArguments()
75377 {
75378 $arguments = array();
75379
75380 if (\defined('HHVM_VERSION')) {
75381 $arguments[] = '--php';
75382 } elseif ('phpdbg' === \PHP_SAPI) {
75383 $arguments[] = '-qrr';
75384 }
75385
75386 return $arguments;
75387 }
75388 }
75389 <?php
75390
75391
75392
75393
75394
75395
75396
75397
75398
75399
75400 namespace Symfony\Component\Process;
75401
75402 use Symfony\Component\Process\Exception\RuntimeException;
75403
75404
75405
75406
75407
75408
75409
75410
75411
75412
75413 class PhpProcess extends Process
75414 {
75415
75416
75417
75418
75419
75420
75421
75422 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
75423 {
75424 $executableFinder = new PhpExecutableFinder();
75425 if (false === $php = $executableFinder->find()) {
75426 $php = null;
75427 }
75428 if ('phpdbg' === \PHP_SAPI) {
75429 $file = tempnam(sys_get_temp_dir(), 'dbg');
75430 file_put_contents($file, $script);
75431 register_shutdown_function('unlink', $file);
75432 $php .= ' '.ProcessUtils::escapeArgument($file);
75433 $script = null;
75434 }
75435 if ('\\' !== \DIRECTORY_SEPARATOR && null !== $php) {
75436
75437  
75438  
75439  $php = 'exec '.$php;
75440 }
75441
75442 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
75443 }
75444
75445
75446
75447
75448 public function setPhpBinary($php)
75449 {
75450 $this->setCommandLine($php);
75451 }
75452
75453
75454
75455
75456 public function start($callback = null)
75457 {
75458 if (null === $this->getCommandLine()) {
75459 throw new RuntimeException('Unable to find the PHP executable.');
75460 }
75461
75462 parent::start($callback);
75463 }
75464 }
75465 <?php
75466
75467
75468
75469
75470
75471
75472
75473
75474
75475
75476 namespace Symfony\Component\Process\Pipes;
75477
75478
75479
75480
75481
75482
75483 abstract class AbstractPipes implements PipesInterface
75484 {
75485 public $pipes = array();
75486
75487 private $inputBuffer = '';
75488 private $input;
75489 private $blocked = true;
75490 private $lastError;
75491
75492
75493
75494
75495 public function __construct($input)
75496 {
75497 if (\is_resource($input)) {
75498 $this->input = $input;
75499 } elseif (\is_string($input)) {
75500 $this->inputBuffer = $input;
75501 } else {
75502 $this->inputBuffer = (string) $input;
75503 }
75504 }
75505
75506
75507
75508
75509 public function close()
75510 {
75511 foreach ($this->pipes as $pipe) {
75512 fclose($pipe);
75513 }
75514 $this->pipes = array();
75515 }
75516
75517
75518
75519
75520
75521
75522 protected function hasSystemCallBeenInterrupted()
75523 {
75524 $lastError = $this->lastError;
75525 $this->lastError = null;
75526
75527
75528  return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
75529 }
75530
75531
75532
75533
75534 protected function unblock()
75535 {
75536 if (!$this->blocked) {
75537 return;
75538 }
75539
75540 foreach ($this->pipes as $pipe) {
75541 stream_set_blocking($pipe, 0);
75542 }
75543 if (null !== $this->input) {
75544 stream_set_blocking($this->input, 0);
75545 }
75546
75547 $this->blocked = false;
75548 }
75549
75550
75551
75552
75553 protected function write()
75554 {
75555 if (!isset($this->pipes[0])) {
75556 return;
75557 }
75558 $input = $this->input;
75559 $r = $e = array();
75560 $w = array($this->pipes[0]);
75561
75562
75563  if (false === @stream_select($r, $w, $e, 0, 0)) {
75564 return;
75565 }
75566
75567 foreach ($w as $stdin) {
75568 if (isset($this->inputBuffer[0])) {
75569 $written = fwrite($stdin, $this->inputBuffer);
75570 $this->inputBuffer = substr($this->inputBuffer, $written);
75571 if (isset($this->inputBuffer[0])) {
75572 return array($this->pipes[0]);
75573 }
75574 }
75575
75576 if ($input) {
75577 for (;;) {
75578 $data = fread($input, self::CHUNK_SIZE);
75579 if (!isset($data[0])) {
75580 break;
75581 }
75582 $written = fwrite($stdin, $data);
75583 $data = substr($data, $written);
75584 if (isset($data[0])) {
75585 $this->inputBuffer = $data;
75586
75587 return array($this->pipes[0]);
75588 }
75589 }
75590 if (feof($input)) {
75591
75592  
75593  $this->input = null;
75594 }
75595 }
75596 }
75597
75598
75599  if (null === $this->input && !isset($this->inputBuffer[0])) {
75600 fclose($this->pipes[0]);
75601 unset($this->pipes[0]);
75602 } elseif (!$w) {
75603 return array($this->pipes[0]);
75604 }
75605 }
75606
75607
75608
75609
75610 public function handleError($type, $msg)
75611 {
75612 $this->lastError = $msg;
75613 }
75614 }
75615 <?php
75616
75617
75618
75619
75620
75621
75622
75623
75624
75625
75626 namespace Symfony\Component\Process\Pipes;
75627
75628
75629
75630
75631
75632
75633
75634
75635 interface PipesInterface
75636 {
75637 const CHUNK_SIZE = 16384;
75638
75639
75640
75641
75642
75643
75644 public function getDescriptors();
75645
75646
75647
75648
75649
75650
75651 public function getFiles();
75652
75653
75654
75655
75656
75657
75658
75659
75660
75661 public function readAndWrite($blocking, $close = false);
75662
75663
75664
75665
75666
75667
75668 public function areOpen();
75669
75670
75671
75672
75673 public function close();
75674 }
75675 <?php
75676
75677
75678
75679
75680
75681
75682
75683
75684
75685
75686 namespace Symfony\Component\Process\Pipes;
75687
75688 use Symfony\Component\Process\Process;
75689
75690
75691
75692
75693
75694
75695
75696
75697 class UnixPipes extends AbstractPipes
75698 {
75699 private $ttyMode;
75700 private $ptyMode;
75701 private $disableOutput;
75702
75703 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
75704 {
75705 $this->ttyMode = (bool) $ttyMode;
75706 $this->ptyMode = (bool) $ptyMode;
75707 $this->disableOutput = (bool) $disableOutput;
75708
75709 parent::__construct($input);
75710 }
75711
75712 public function __destruct()
75713 {
75714 $this->close();
75715 }
75716
75717
75718
75719
75720 public function getDescriptors()
75721 {
75722 if ($this->disableOutput) {
75723 $nullstream = fopen('/dev/null', 'c');
75724
75725 return array(
75726 array('pipe', 'r'),
75727 $nullstream,
75728 $nullstream,
75729 );
75730 }
75731
75732 if ($this->ttyMode) {
75733 return array(
75734 array('file', '/dev/tty', 'r'),
75735 array('file', '/dev/tty', 'w'),
75736 array('file', '/dev/tty', 'w'),
75737 );
75738 }
75739
75740 if ($this->ptyMode && Process::isPtySupported()) {
75741 return array(
75742 array('pty'),
75743 array('pty'),
75744 array('pty'),
75745 );
75746 }
75747
75748 return array(
75749 array('pipe', 'r'),
75750 array('pipe', 'w'), 
75751  array('pipe', 'w'), 
75752  );
75753 }
75754
75755
75756
75757
75758 public function getFiles()
75759 {
75760 return array();
75761 }
75762
75763
75764
75765
75766 public function readAndWrite($blocking, $close = false)
75767 {
75768 $this->unblock();
75769 $w = $this->write();
75770
75771 $read = $e = array();
75772 $r = $this->pipes;
75773 unset($r[0]);
75774
75775
75776  set_error_handler(array($this, 'handleError'));
75777 if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
75778 restore_error_handler();
75779
75780  
75781  if (!$this->hasSystemCallBeenInterrupted()) {
75782 $this->pipes = array();
75783 }
75784
75785 return $read;
75786 }
75787 restore_error_handler();
75788
75789 foreach ($r as $pipe) {
75790
75791  
75792  $read[$type = array_search($pipe, $this->pipes, true)] = '';
75793
75794 do {
75795 $data = fread($pipe, self::CHUNK_SIZE);
75796 $read[$type] .= $data;
75797 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
75798
75799 if (!isset($read[$type][0])) {
75800 unset($read[$type]);
75801 }
75802
75803 if ($close && feof($pipe)) {
75804 fclose($pipe);
75805 unset($this->pipes[$type]);
75806 }
75807 }
75808
75809 return $read;
75810 }
75811
75812
75813
75814
75815 public function areOpen()
75816 {
75817 return (bool) $this->pipes;
75818 }
75819
75820
75821
75822
75823
75824
75825
75826
75827
75828 public static function create(Process $process, $input)
75829 {
75830 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
75831 }
75832 }
75833 <?php
75834
75835
75836
75837
75838
75839
75840
75841
75842
75843
75844 namespace Symfony\Component\Process\Pipes;
75845
75846 use Symfony\Component\Process\Exception\RuntimeException;
75847 use Symfony\Component\Process\Process;
75848
75849
75850
75851
75852
75853
75854
75855
75856
75857
75858
75859 class WindowsPipes extends AbstractPipes
75860 {
75861 private $files = array();
75862 private $fileHandles = array();
75863 private $lockHandles = array();
75864 private $readBytes = array(
75865 Process::STDOUT => 0,
75866 Process::STDERR => 0,
75867 );
75868 private $disableOutput;
75869
75870 public function __construct($disableOutput, $input)
75871 {
75872 $this->disableOutput = (bool) $disableOutput;
75873
75874 if (!$this->disableOutput) {
75875
75876  
75877  
75878  
75879  $pipes = array(
75880 Process::STDOUT => Process::OUT,
75881 Process::STDERR => Process::ERR,
75882 );
75883 $tmpDir = sys_get_temp_dir();
75884 $lastError = 'unknown reason';
75885 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
75886 for ($i = 0;; ++$i) {
75887 foreach ($pipes as $pipe => $name) {
75888 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
75889
75890 if (!$h = fopen($file.'.lock', 'w')) {
75891 restore_error_handler();
75892 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $lastError));
75893 }
75894 if (!flock($h, LOCK_EX | LOCK_NB)) {
75895 continue 2;
75896 }
75897 if (isset($this->lockHandles[$pipe])) {
75898 flock($this->lockHandles[$pipe], LOCK_UN);
75899 fclose($this->lockHandles[$pipe]);
75900 }
75901 $this->lockHandles[$pipe] = $h;
75902
75903 if (!fclose(fopen($file, 'w')) || !$h = fopen($file, 'r')) {
75904 flock($this->lockHandles[$pipe], LOCK_UN);
75905 fclose($this->lockHandles[$pipe]);
75906 unset($this->lockHandles[$pipe]);
75907 continue 2;
75908 }
75909 $this->fileHandles[$pipe] = $h;
75910 $this->files[$pipe] = $file;
75911 }
75912 break;
75913 }
75914 restore_error_handler();
75915 }
75916
75917 parent::__construct($input);
75918 }
75919
75920 public function __destruct()
75921 {
75922 $this->close();
75923 }
75924
75925
75926
75927
75928 public function getDescriptors()
75929 {
75930 if ($this->disableOutput) {
75931 $nullstream = fopen('NUL', 'c');
75932
75933 return array(
75934 array('pipe', 'r'),
75935 $nullstream,
75936 $nullstream,
75937 );
75938 }
75939
75940
75941  
75942  
75943  return array(
75944 array('pipe', 'r'),
75945 array('file', 'NUL', 'w'),
75946 array('file', 'NUL', 'w'),
75947 );
75948 }
75949
75950
75951
75952
75953 public function getFiles()
75954 {
75955 return $this->files;
75956 }
75957
75958
75959
75960
75961 public function readAndWrite($blocking, $close = false)
75962 {
75963 $this->unblock();
75964 $w = $this->write();
75965 $read = $r = $e = array();
75966
75967 if ($blocking) {
75968 if ($w) {
75969 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
75970 } elseif ($this->fileHandles) {
75971 usleep(Process::TIMEOUT_PRECISION * 1E6);
75972 }
75973 }
75974 foreach ($this->fileHandles as $type => $fileHandle) {
75975 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
75976
75977 if (isset($data[0])) {
75978 $this->readBytes[$type] += \strlen($data);
75979 $read[$type] = $data;
75980 }
75981 if ($close) {
75982 ftruncate($fileHandle, 0);
75983 fclose($fileHandle);
75984 flock($this->lockHandles[$type], LOCK_UN);
75985 fclose($this->lockHandles[$type]);
75986 unset($this->fileHandles[$type], $this->lockHandles[$type]);
75987 }
75988 }
75989
75990 return $read;
75991 }
75992
75993
75994
75995
75996 public function areOpen()
75997 {
75998 return $this->pipes && $this->fileHandles;
75999 }
76000
76001
76002
76003
76004 public function close()
76005 {
76006 parent::close();
76007 foreach ($this->fileHandles as $type => $handle) {
76008 ftruncate($handle, 0);
76009 fclose($handle);
76010 flock($this->lockHandles[$type], LOCK_UN);
76011 fclose($this->lockHandles[$type]);
76012 }
76013 $this->fileHandles = $this->lockHandles = array();
76014 }
76015
76016
76017
76018
76019
76020
76021
76022
76023
76024 public static function create(Process $process, $input)
76025 {
76026 return new static($process->isOutputDisabled(), $input);
76027 }
76028 }
76029 <?php
76030
76031
76032
76033
76034
76035
76036
76037
76038
76039
76040 namespace Symfony\Component\Process;
76041
76042 use Symfony\Component\Process\Exception\InvalidArgumentException;
76043 use Symfony\Component\Process\Exception\LogicException;
76044 use Symfony\Component\Process\Exception\ProcessFailedException;
76045 use Symfony\Component\Process\Exception\ProcessTimedOutException;
76046 use Symfony\Component\Process\Exception\RuntimeException;
76047 use Symfony\Component\Process\Pipes\PipesInterface;
76048 use Symfony\Component\Process\Pipes\UnixPipes;
76049 use Symfony\Component\Process\Pipes\WindowsPipes;
76050
76051
76052
76053
76054
76055
76056
76057
76058 class Process
76059 {
76060 const ERR = 'err';
76061 const OUT = 'out';
76062
76063 const STATUS_READY = 'ready';
76064 const STATUS_STARTED = 'started';
76065 const STATUS_TERMINATED = 'terminated';
76066
76067 const STDIN = 0;
76068 const STDOUT = 1;
76069 const STDERR = 2;
76070
76071
76072  const TIMEOUT_PRECISION = 0.2;
76073
76074 private $callback;
76075 private $commandline;
76076 private $cwd;
76077 private $env;
76078 private $input;
76079 private $starttime;
76080 private $lastOutputTime;
76081 private $timeout;
76082 private $idleTimeout;
76083 private $options;
76084 private $exitcode;
76085 private $fallbackStatus = array();
76086 private $processInformation;
76087 private $outputDisabled = false;
76088 private $stdout;
76089 private $stderr;
76090 private $enhanceWindowsCompatibility = true;
76091 private $enhanceSigchildCompatibility;
76092 private $process;
76093 private $status = self::STATUS_READY;
76094 private $incrementalOutputOffset = 0;
76095 private $incrementalErrorOutputOffset = 0;
76096 private $tty;
76097 private $pty;
76098
76099 private $useFileHandles = false;
76100
76101 private $processPipes;
76102
76103 private $latestSignal;
76104
76105 private static $sigchild;
76106
76107
76108
76109
76110
76111
76112 public static $exitCodes = array(
76113 0 => 'OK',
76114 1 => 'General error',
76115 2 => 'Misuse of shell builtins',
76116
76117 126 => 'Invoked command cannot execute',
76118 127 => 'Command not found',
76119 128 => 'Invalid exit argument',
76120
76121
76122  129 => 'Hangup',
76123 130 => 'Interrupt',
76124 131 => 'Quit and dump core',
76125 132 => 'Illegal instruction',
76126 133 => 'Trace/breakpoint trap',
76127 134 => 'Process aborted',
76128 135 => 'Bus error: "access to undefined portion of memory object"',
76129 136 => 'Floating point exception: "erroneous arithmetic operation"',
76130 137 => 'Kill (terminate immediately)',
76131 138 => 'User-defined 1',
76132 139 => 'Segmentation violation',
76133 140 => 'User-defined 2',
76134 141 => 'Write to pipe with no one reading',
76135 142 => 'Signal raised by alarm',
76136 143 => 'Termination (request to terminate)',
76137
76138  145 => 'Child process terminated, stopped (or continued*)',
76139 146 => 'Continue if stopped',
76140 147 => 'Stop executing temporarily',
76141 148 => 'Terminal stop signal',
76142 149 => 'Background process attempting to read from tty ("in")',
76143 150 => 'Background process attempting to write to tty ("out")',
76144 151 => 'Urgent data available on socket',
76145 152 => 'CPU time limit exceeded',
76146 153 => 'File size limit exceeded',
76147 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
76148 155 => 'Profiling timer expired',
76149
76150  157 => 'Pollable event',
76151
76152  159 => 'Bad syscall',
76153 );
76154
76155
76156
76157
76158
76159
76160
76161
76162
76163
76164
76165 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
76166 {
76167 if (!\function_exists('proc_open')) {
76168 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
76169 }
76170
76171 $this->commandline = $commandline;
76172 $this->cwd = $cwd;
76173
76174
76175  
76176  
76177  
76178  if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
76179 $this->cwd = getcwd();
76180 }
76181 if (null !== $env) {
76182 $this->setEnv($env);
76183 }
76184
76185 $this->setInput($input);
76186 $this->setTimeout($timeout);
76187 $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR;
76188 $this->pty = false;
76189 $this->enhanceSigchildCompatibility = '\\' !== \DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
76190 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
76191 }
76192
76193 public function __destruct()
76194 {
76195 $this->stop(0);
76196 }
76197
76198 public function __clone()
76199 {
76200 $this->resetProcessData();
76201 }
76202
76203
76204
76205
76206
76207
76208
76209
76210
76211
76212
76213
76214
76215
76216
76217
76218
76219
76220
76221
76222 public function run($callback = null)
76223 {
76224 $this->start($callback);
76225
76226 return $this->wait();
76227 }
76228
76229
76230
76231
76232
76233
76234
76235
76236
76237
76238
76239
76240
76241
76242 public function mustRun($callback = null)
76243 {
76244 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76245 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
76246 }
76247
76248 if (0 !== $this->run($callback)) {
76249 throw new ProcessFailedException($this);
76250 }
76251
76252 return $this;
76253 }
76254
76255
76256
76257
76258
76259
76260
76261
76262
76263
76264
76265
76266
76267
76268
76269
76270
76271
76272
76273
76274 public function start($callback = null)
76275 {
76276 if ($this->isRunning()) {
76277 throw new RuntimeException('Process is already running');
76278 }
76279 if ($this->outputDisabled && null !== $callback) {
76280 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
76281 }
76282
76283 $this->resetProcessData();
76284 $this->starttime = $this->lastOutputTime = microtime(true);
76285 $this->callback = $this->buildCallback($callback);
76286 $descriptors = $this->getDescriptors();
76287
76288 $commandline = $this->commandline;
76289
76290 if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
76291 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
76292 foreach ($this->processPipes->getFiles() as $offset => $filename) {
76293 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
76294 }
76295 $commandline .= '"';
76296
76297 if (!isset($this->options['bypass_shell'])) {
76298 $this->options['bypass_shell'] = true;
76299 }
76300 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76301
76302  $descriptors[3] = array('pipe', 'w');
76303
76304
76305  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
76306 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
76307
76308
76309  
76310  $ptsWorkaround = fopen(__FILE__, 'r');
76311 }
76312
76313 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
76314
76315 if (!\is_resource($this->process)) {
76316 throw new RuntimeException('Unable to launch a new process.');
76317 }
76318 $this->status = self::STATUS_STARTED;
76319
76320 if (isset($descriptors[3])) {
76321 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
76322 }
76323
76324 if ($this->tty) {
76325 return;
76326 }
76327
76328 $this->updateStatus(false);
76329 $this->checkTimeout();
76330 }
76331
76332
76333
76334
76335
76336
76337
76338
76339
76340
76341
76342
76343
76344
76345
76346
76347 public function restart($callback = null)
76348 {
76349 if ($this->isRunning()) {
76350 throw new RuntimeException('Process is already running');
76351 }
76352
76353 $process = clone $this;
76354 $process->start($callback);
76355
76356 return $process;
76357 }
76358
76359
76360
76361
76362
76363
76364
76365
76366
76367
76368
76369
76370
76371
76372
76373
76374 public function wait($callback = null)
76375 {
76376 $this->requireProcessIsStarted(__FUNCTION__);
76377
76378 $this->updateStatus(false);
76379 if (null !== $callback) {
76380 $this->callback = $this->buildCallback($callback);
76381 }
76382
76383 do {
76384 $this->checkTimeout();
76385 $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
76386 $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
76387 } while ($running);
76388
76389 while ($this->isRunning()) {
76390 usleep(1000);
76391 }
76392
76393 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
76394 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
76395 }
76396
76397 return $this->exitcode;
76398 }
76399
76400
76401
76402
76403
76404
76405 public function getPid()
76406 {
76407 return $this->isRunning() ? $this->processInformation['pid'] : null;
76408 }
76409
76410
76411
76412
76413
76414
76415
76416
76417
76418
76419
76420
76421 public function signal($signal)
76422 {
76423 $this->doSignal($signal, true);
76424
76425 return $this;
76426 }
76427
76428
76429
76430
76431
76432
76433
76434
76435
76436 public function disableOutput()
76437 {
76438 if ($this->isRunning()) {
76439 throw new RuntimeException('Disabling output while the process is running is not possible.');
76440 }
76441 if (null !== $this->idleTimeout) {
76442 throw new LogicException('Output can not be disabled while an idle timeout is set.');
76443 }
76444
76445 $this->outputDisabled = true;
76446
76447 return $this;
76448 }
76449
76450
76451
76452
76453
76454
76455
76456
76457 public function enableOutput()
76458 {
76459 if ($this->isRunning()) {
76460 throw new RuntimeException('Enabling output while the process is running is not possible.');
76461 }
76462
76463 $this->outputDisabled = false;
76464
76465 return $this;
76466 }
76467
76468
76469
76470
76471
76472
76473 public function isOutputDisabled()
76474 {
76475 return $this->outputDisabled;
76476 }
76477
76478
76479
76480
76481
76482
76483
76484
76485
76486 public function getOutput()
76487 {
76488 $this->readPipesForOutput(__FUNCTION__);
76489
76490 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
76491 return '';
76492 }
76493
76494 return $ret;
76495 }
76496
76497
76498
76499
76500
76501
76502
76503
76504
76505
76506
76507
76508 public function getIncrementalOutput()
76509 {
76510 $this->readPipesForOutput(__FUNCTION__);
76511
76512 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
76513 $this->incrementalOutputOffset = ftell($this->stdout);
76514
76515 if (false === $latest) {
76516 return '';
76517 }
76518
76519 return $latest;
76520 }
76521
76522
76523
76524
76525
76526
76527 public function clearOutput()
76528 {
76529 ftruncate($this->stdout, 0);
76530 fseek($this->stdout, 0);
76531 $this->incrementalOutputOffset = 0;
76532
76533 return $this;
76534 }
76535
76536
76537
76538
76539
76540
76541
76542
76543
76544 public function getErrorOutput()
76545 {
76546 $this->readPipesForOutput(__FUNCTION__);
76547
76548 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
76549 return '';
76550 }
76551
76552 return $ret;
76553 }
76554
76555
76556
76557
76558
76559
76560
76561
76562
76563
76564
76565
76566
76567 public function getIncrementalErrorOutput()
76568 {
76569 $this->readPipesForOutput(__FUNCTION__);
76570
76571 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
76572 $this->incrementalErrorOutputOffset = ftell($this->stderr);
76573
76574 if (false === $latest) {
76575 return '';
76576 }
76577
76578 return $latest;
76579 }
76580
76581
76582
76583
76584
76585
76586 public function clearErrorOutput()
76587 {
76588 ftruncate($this->stderr, 0);
76589 fseek($this->stderr, 0);
76590 $this->incrementalErrorOutputOffset = 0;
76591
76592 return $this;
76593 }
76594
76595
76596
76597
76598
76599
76600
76601
76602 public function getExitCode()
76603 {
76604 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76605 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
76606 }
76607
76608 $this->updateStatus(false);
76609
76610 return $this->exitcode;
76611 }
76612
76613
76614
76615
76616
76617
76618
76619
76620
76621
76622
76623
76624 public function getExitCodeText()
76625 {
76626 if (null === $exitcode = $this->getExitCode()) {
76627 return;
76628 }
76629
76630 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
76631 }
76632
76633
76634
76635
76636
76637
76638 public function isSuccessful()
76639 {
76640 return 0 === $this->getExitCode();
76641 }
76642
76643
76644
76645
76646
76647
76648
76649
76650
76651
76652
76653 public function hasBeenSignaled()
76654 {
76655 $this->requireProcessIsTerminated(__FUNCTION__);
76656
76657 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76658 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
76659 }
76660
76661 return $this->processInformation['signaled'];
76662 }
76663
76664
76665
76666
76667
76668
76669
76670
76671
76672
76673
76674 public function getTermSignal()
76675 {
76676 $this->requireProcessIsTerminated(__FUNCTION__);
76677
76678 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
76679 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
76680 }
76681
76682 return $this->processInformation['termsig'];
76683 }
76684
76685
76686
76687
76688
76689
76690
76691
76692
76693
76694 public function hasBeenStopped()
76695 {
76696 $this->requireProcessIsTerminated(__FUNCTION__);
76697
76698 return $this->processInformation['stopped'];
76699 }
76700
76701
76702
76703
76704
76705
76706
76707
76708
76709
76710 public function getStopSignal()
76711 {
76712 $this->requireProcessIsTerminated(__FUNCTION__);
76713
76714 return $this->processInformation['stopsig'];
76715 }
76716
76717
76718
76719
76720
76721
76722 public function isRunning()
76723 {
76724 if (self::STATUS_STARTED !== $this->status) {
76725 return false;
76726 }
76727
76728 $this->updateStatus(false);
76729
76730 return $this->processInformation['running'];
76731 }
76732
76733
76734
76735
76736
76737
76738 public function isStarted()
76739 {
76740 return self::STATUS_READY != $this->status;
76741 }
76742
76743
76744
76745
76746
76747
76748 public function isTerminated()
76749 {
76750 $this->updateStatus(false);
76751
76752 return self::STATUS_TERMINATED == $this->status;
76753 }
76754
76755
76756
76757
76758
76759
76760
76761
76762 public function getStatus()
76763 {
76764 $this->updateStatus(false);
76765
76766 return $this->status;
76767 }
76768
76769
76770
76771
76772
76773
76774
76775
76776
76777 public function stop($timeout = 10, $signal = null)
76778 {
76779 $timeoutMicro = microtime(true) + $timeout;
76780 if ($this->isRunning()) {
76781
76782  $this->doSignal(15, false);
76783 do {
76784 usleep(1000);
76785 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
76786
76787 if ($this->isRunning()) {
76788
76789  
76790  $this->doSignal($signal ?: 9, false);
76791 }
76792 }
76793
76794 if ($this->isRunning()) {
76795 if (isset($this->fallbackStatus['pid'])) {
76796 unset($this->fallbackStatus['pid']);
76797
76798 return $this->stop(0, $signal);
76799 }
76800 $this->close();
76801 }
76802
76803 return $this->exitcode;
76804 }
76805
76806
76807
76808
76809
76810
76811
76812
76813 public function addOutput($line)
76814 {
76815 $this->lastOutputTime = microtime(true);
76816
76817 fseek($this->stdout, 0, SEEK_END);
76818 fwrite($this->stdout, $line);
76819 fseek($this->stdout, $this->incrementalOutputOffset);
76820 }
76821
76822
76823
76824
76825
76826
76827
76828
76829 public function addErrorOutput($line)
76830 {
76831 $this->lastOutputTime = microtime(true);
76832
76833 fseek($this->stderr, 0, SEEK_END);
76834 fwrite($this->stderr, $line);
76835 fseek($this->stderr, $this->incrementalErrorOutputOffset);
76836 }
76837
76838
76839
76840
76841
76842
76843 public function getCommandLine()
76844 {
76845 return $this->commandline;
76846 }
76847
76848
76849
76850
76851
76852
76853
76854
76855 public function setCommandLine($commandline)
76856 {
76857 $this->commandline = $commandline;
76858
76859 return $this;
76860 }
76861
76862
76863
76864
76865
76866
76867 public function getTimeout()
76868 {
76869 return $this->timeout;
76870 }
76871
76872
76873
76874
76875
76876
76877 public function getIdleTimeout()
76878 {
76879 return $this->idleTimeout;
76880 }
76881
76882
76883
76884
76885
76886
76887
76888
76889
76890
76891
76892
76893 public function setTimeout($timeout)
76894 {
76895 $this->timeout = $this->validateTimeout($timeout);
76896
76897 return $this;
76898 }
76899
76900
76901
76902
76903
76904
76905
76906
76907
76908
76909
76910
76911
76912 public function setIdleTimeout($timeout)
76913 {
76914 if (null !== $timeout && $this->outputDisabled) {
76915 throw new LogicException('Idle timeout can not be set while the output is disabled.');
76916 }
76917
76918 $this->idleTimeout = $this->validateTimeout($timeout);
76919
76920 return $this;
76921 }
76922
76923
76924
76925
76926
76927
76928
76929
76930
76931
76932 public function setTty($tty)
76933 {
76934 if ('\\' === \DIRECTORY_SEPARATOR && $tty) {
76935 throw new RuntimeException('TTY mode is not supported on Windows platform.');
76936 }
76937 if ($tty) {
76938 static $isTtySupported;
76939
76940 if (null === $isTtySupported) {
76941 $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', array(array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w')), $pipes);
76942 }
76943
76944 if (!$isTtySupported) {
76945 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
76946 }
76947 }
76948
76949 $this->tty = (bool) $tty;
76950
76951 return $this;
76952 }
76953
76954
76955
76956
76957
76958
76959 public function isTty()
76960 {
76961 return $this->tty;
76962 }
76963
76964
76965
76966
76967
76968
76969
76970
76971 public function setPty($bool)
76972 {
76973 $this->pty = (bool) $bool;
76974
76975 return $this;
76976 }
76977
76978
76979
76980
76981
76982
76983 public function isPty()
76984 {
76985 return $this->pty;
76986 }
76987
76988
76989
76990
76991
76992
76993 public function getWorkingDirectory()
76994 {
76995 if (null === $this->cwd) {
76996
76997  
76998  return getcwd() ?: null;
76999 }
77000
77001 return $this->cwd;
77002 }
77003
77004
77005
77006
77007
77008
77009
77010
77011 public function setWorkingDirectory($cwd)
77012 {
77013 $this->cwd = $cwd;
77014
77015 return $this;
77016 }
77017
77018
77019
77020
77021
77022
77023 public function getEnv()
77024 {
77025 return $this->env;
77026 }
77027
77028
77029
77030
77031
77032
77033
77034
77035
77036
77037
77038
77039
77040
77041 public function setEnv(array $env)
77042 {
77043
77044  $env = array_filter($env, function ($value) {
77045 return !\is_array($value);
77046 });
77047
77048 $this->env = array();
77049 foreach ($env as $key => $value) {
77050 $this->env[$key] = (string) $value;
77051 }
77052
77053 return $this;
77054 }
77055
77056
77057
77058
77059
77060
77061
77062
77063
77064
77065 public function getStdin()
77066 {
77067 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the getInput() method instead.', E_USER_DEPRECATED);
77068
77069 return $this->getInput();
77070 }
77071
77072
77073
77074
77075
77076
77077 public function getInput()
77078 {
77079 return $this->input;
77080 }
77081
77082
77083
77084
77085
77086
77087
77088
77089
77090
77091
77092
77093
77094
77095 public function setStdin($stdin)
77096 {
77097 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the setInput() method instead.', E_USER_DEPRECATED);
77098
77099 return $this->setInput($stdin);
77100 }
77101
77102
77103
77104
77105
77106
77107
77108
77109
77110
77111
77112
77113
77114
77115 public function setInput($input)
77116 {
77117 if ($this->isRunning()) {
77118 throw new LogicException('Input can not be set while the process is running.');
77119 }
77120
77121 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
77122
77123 return $this;
77124 }
77125
77126
77127
77128
77129
77130
77131 public function getOptions()
77132 {
77133 return $this->options;
77134 }
77135
77136
77137
77138
77139
77140
77141
77142
77143 public function setOptions(array $options)
77144 {
77145 $this->options = $options;
77146
77147 return $this;
77148 }
77149
77150
77151
77152
77153
77154
77155
77156
77157 public function getEnhanceWindowsCompatibility()
77158 {
77159 return $this->enhanceWindowsCompatibility;
77160 }
77161
77162
77163
77164
77165
77166
77167
77168
77169 public function setEnhanceWindowsCompatibility($enhance)
77170 {
77171 $this->enhanceWindowsCompatibility = (bool) $enhance;
77172
77173 return $this;
77174 }
77175
77176
77177
77178
77179
77180
77181 public function getEnhanceSigchildCompatibility()
77182 {
77183 return $this->enhanceSigchildCompatibility;
77184 }
77185
77186
77187
77188
77189
77190
77191
77192
77193
77194
77195
77196
77197 public function setEnhanceSigchildCompatibility($enhance)
77198 {
77199 $this->enhanceSigchildCompatibility = (bool) $enhance;
77200
77201 return $this;
77202 }
77203
77204
77205
77206
77207
77208
77209
77210
77211
77212 public function checkTimeout()
77213 {
77214 if (self::STATUS_STARTED !== $this->status) {
77215 return;
77216 }
77217
77218 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
77219 $this->stop(0);
77220
77221 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
77222 }
77223
77224 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
77225 $this->stop(0);
77226
77227 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
77228 }
77229 }
77230
77231
77232
77233
77234
77235
77236 public static function isPtySupported()
77237 {
77238 static $result;
77239
77240 if (null !== $result) {
77241 return $result;
77242 }
77243
77244 if ('\\' === \DIRECTORY_SEPARATOR) {
77245 return $result = false;
77246 }
77247
77248 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
77249 }
77250
77251
77252
77253
77254
77255
77256 private function getDescriptors()
77257 {
77258 if ('\\' === \DIRECTORY_SEPARATOR) {
77259 $this->processPipes = WindowsPipes::create($this, $this->input);
77260 } else {
77261 $this->processPipes = UnixPipes::create($this, $this->input);
77262 }
77263
77264 return $this->processPipes->getDescriptors();
77265 }
77266
77267
77268
77269
77270
77271
77272
77273
77274
77275
77276
77277 protected function buildCallback($callback)
77278 {
77279 $that = $this;
77280 $out = self::OUT;
77281 $callback = function ($type, $data) use ($that, $callback, $out) {
77282 if ($out == $type) {
77283 $that->addOutput($data);
77284 } else {
77285 $that->addErrorOutput($data);
77286 }
77287
77288 if (null !== $callback) {
77289 \call_user_func($callback, $type, $data);
77290 }
77291 };
77292
77293 return $callback;
77294 }
77295
77296
77297
77298
77299
77300
77301 protected function updateStatus($blocking)
77302 {
77303 if (self::STATUS_STARTED !== $this->status) {
77304 return;
77305 }
77306
77307 $this->processInformation = proc_get_status($this->process);
77308 $running = $this->processInformation['running'];
77309
77310 $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);
77311
77312 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
77313 $this->processInformation = $this->fallbackStatus + $this->processInformation;
77314 }
77315
77316 if (!$running) {
77317 $this->close();
77318 }
77319 }
77320
77321
77322
77323
77324
77325
77326 protected function isSigchildEnabled()
77327 {
77328 if (null !== self::$sigchild) {
77329 return self::$sigchild;
77330 }
77331
77332 if (!\function_exists('phpinfo') || \defined('HHVM_VERSION')) {
77333 return self::$sigchild = false;
77334 }
77335
77336 ob_start();
77337 phpinfo(INFO_GENERAL);
77338
77339 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
77340 }
77341
77342
77343
77344
77345
77346
77347
77348
77349 private function readPipesForOutput($caller)
77350 {
77351 if ($this->outputDisabled) {
77352 throw new LogicException('Output has been disabled.');
77353 }
77354
77355 $this->requireProcessIsStarted($caller);
77356
77357 $this->updateStatus(false);
77358 }
77359
77360
77361
77362
77363
77364
77365
77366
77367
77368
77369 private function validateTimeout($timeout)
77370 {
77371 $timeout = (float) $timeout;
77372
77373 if (0.0 === $timeout) {
77374 $timeout = null;
77375 } elseif ($timeout < 0) {
77376 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
77377 }
77378
77379 return $timeout;
77380 }
77381
77382
77383
77384
77385
77386
77387
77388 private function readPipes($blocking, $close)
77389 {
77390 $result = $this->processPipes->readAndWrite($blocking, $close);
77391
77392 $callback = $this->callback;
77393 foreach ($result as $type => $data) {
77394 if (3 !== $type) {
77395 $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
77396 } elseif (!isset($this->fallbackStatus['signaled'])) {
77397 $this->fallbackStatus['exitcode'] = (int) $data;
77398 }
77399 }
77400 }
77401
77402
77403
77404
77405
77406
77407 private function close()
77408 {
77409 $this->processPipes->close();
77410 if (\is_resource($this->process)) {
77411 proc_close($this->process);
77412 }
77413 $this->exitcode = $this->processInformation['exitcode'];
77414 $this->status = self::STATUS_TERMINATED;
77415
77416 if (-1 === $this->exitcode) {
77417 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
77418
77419  $this->exitcode = 128 + $this->processInformation['termsig'];
77420 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
77421 $this->processInformation['signaled'] = true;
77422 $this->processInformation['termsig'] = -1;
77423 }
77424 }
77425
77426
77427  
77428  
77429  $this->callback = null;
77430
77431 return $this->exitcode;
77432 }
77433
77434
77435
77436
77437 private function resetProcessData()
77438 {
77439 $this->starttime = null;
77440 $this->callback = null;
77441 $this->exitcode = null;
77442 $this->fallbackStatus = array();
77443 $this->processInformation = null;
77444 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
77445 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
77446 $this->process = null;
77447 $this->latestSignal = null;
77448 $this->status = self::STATUS_READY;
77449 $this->incrementalOutputOffset = 0;
77450 $this->incrementalErrorOutputOffset = 0;
77451 }
77452
77453
77454
77455
77456
77457
77458
77459
77460
77461
77462
77463
77464
77465 private function doSignal($signal, $throwException)
77466 {
77467 if (null === $pid = $this->getPid()) {
77468 if ($throwException) {
77469 throw new LogicException('Can not send signal on a non running process.');
77470 }
77471
77472 return false;
77473 }
77474
77475 if ('\\' === \DIRECTORY_SEPARATOR) {
77476 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
77477 if ($exitCode && $this->isRunning()) {
77478 if ($throwException) {
77479 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
77480 }
77481
77482 return false;
77483 }
77484 } else {
77485 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
77486 $ok = @proc_terminate($this->process, $signal);
77487 } elseif (\function_exists('posix_kill')) {
77488 $ok = @posix_kill($pid, $signal);
77489 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
77490 $ok = false === fgets($pipes[2]);
77491 }
77492 if (!$ok) {
77493 if ($throwException) {
77494 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
77495 }
77496
77497 return false;
77498 }
77499 }
77500
77501 $this->latestSignal = (int) $signal;
77502 $this->fallbackStatus['signaled'] = true;
77503 $this->fallbackStatus['exitcode'] = -1;
77504 $this->fallbackStatus['termsig'] = $this->latestSignal;
77505
77506 return true;
77507 }
77508
77509
77510
77511
77512
77513
77514
77515
77516 private function requireProcessIsStarted($functionName)
77517 {
77518 if (!$this->isStarted()) {
77519 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
77520 }
77521 }
77522
77523
77524
77525
77526
77527
77528
77529
77530 private function requireProcessIsTerminated($functionName)
77531 {
77532 if (!$this->isTerminated()) {
77533 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
77534 }
77535 }
77536 }
77537 <?php
77538
77539
77540
77541
77542
77543
77544
77545
77546
77547
77548 namespace Symfony\Component\Process;
77549
77550 use Symfony\Component\Process\Exception\InvalidArgumentException;
77551 use Symfony\Component\Process\Exception\LogicException;
77552
77553
77554
77555
77556 class ProcessBuilder
77557 {
77558 private $arguments;
77559 private $cwd;
77560 private $env = array();
77561 private $input;
77562 private $timeout = 60;
77563 private $options = array();
77564 private $inheritEnv = true;
77565 private $prefix = array();
77566 private $outputDisabled = false;
77567
77568
77569
77570
77571 public function __construct(array $arguments = array())
77572 {
77573 $this->arguments = $arguments;
77574 }
77575
77576
77577
77578
77579
77580
77581
77582
77583 public static function create(array $arguments = array())
77584 {
77585 return new static($arguments);
77586 }
77587
77588
77589
77590
77591
77592
77593
77594
77595 public function add($argument)
77596 {
77597 $this->arguments[] = $argument;
77598
77599 return $this;
77600 }
77601
77602
77603
77604
77605
77606
77607
77608
77609
77610
77611 public function setPrefix($prefix)
77612 {
77613 $this->prefix = \is_array($prefix) ? $prefix : array($prefix);
77614
77615 return $this;
77616 }
77617
77618
77619
77620
77621
77622
77623
77624
77625
77626
77627
77628 public function setArguments(array $arguments)
77629 {
77630 $this->arguments = $arguments;
77631
77632 return $this;
77633 }
77634
77635
77636
77637
77638
77639
77640
77641
77642 public function setWorkingDirectory($cwd)
77643 {
77644 $this->cwd = $cwd;
77645
77646 return $this;
77647 }
77648
77649
77650
77651
77652
77653
77654
77655
77656 public function inheritEnvironmentVariables($inheritEnv = true)
77657 {
77658 $this->inheritEnv = $inheritEnv;
77659
77660 return $this;
77661 }
77662
77663
77664
77665
77666
77667
77668
77669
77670
77671
77672
77673
77674 public function setEnv($name, $value)
77675 {
77676 $this->env[$name] = $value;
77677
77678 return $this;
77679 }
77680
77681
77682
77683
77684
77685
77686
77687
77688
77689
77690
77691
77692 public function addEnvironmentVariables(array $variables)
77693 {
77694 $this->env = array_replace($this->env, $variables);
77695
77696 return $this;
77697 }
77698
77699
77700
77701
77702
77703
77704
77705
77706
77707
77708
77709
77710 public function setInput($input)
77711 {
77712 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
77713
77714 return $this;
77715 }
77716
77717
77718
77719
77720
77721
77722
77723
77724
77725
77726
77727
77728 public function setTimeout($timeout)
77729 {
77730 if (null === $timeout) {
77731 $this->timeout = null;
77732
77733 return $this;
77734 }
77735
77736 $timeout = (float) $timeout;
77737
77738 if ($timeout < 0) {
77739 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
77740 }
77741
77742 $this->timeout = $timeout;
77743
77744 return $this;
77745 }
77746
77747
77748
77749
77750
77751
77752
77753
77754
77755 public function setOption($name, $value)
77756 {
77757 $this->options[$name] = $value;
77758
77759 return $this;
77760 }
77761
77762
77763
77764
77765
77766
77767 public function disableOutput()
77768 {
77769 $this->outputDisabled = true;
77770
77771 return $this;
77772 }
77773
77774
77775
77776
77777
77778
77779 public function enableOutput()
77780 {
77781 $this->outputDisabled = false;
77782
77783 return $this;
77784 }
77785
77786
77787
77788
77789
77790
77791
77792
77793 public function getProcess()
77794 {
77795 if (0 === \count($this->prefix) && 0 === \count($this->arguments)) {
77796 throw new LogicException('You must add() command arguments before calling getProcess().');
77797 }
77798
77799 $options = $this->options;
77800
77801 $arguments = array_merge($this->prefix, $this->arguments);
77802 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
77803
77804 if ($this->inheritEnv) {
77805
77806  $env = array_replace($_ENV, $_SERVER, $this->env);
77807 } else {
77808 $env = $this->env;
77809 }
77810
77811 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
77812
77813 if ($this->outputDisabled) {
77814 $process->disableOutput();
77815 }
77816
77817 return $process;
77818 }
77819 }
77820 <?php
77821
77822
77823
77824
77825
77826
77827
77828
77829
77830
77831 namespace Symfony\Component\Process;
77832
77833 use Symfony\Component\Process\Exception\InvalidArgumentException;
77834
77835
77836
77837
77838
77839
77840
77841
77842 class ProcessUtils
77843 {
77844
77845
77846
77847 private function __construct()
77848 {
77849 }
77850
77851
77852
77853
77854
77855
77856
77857
77858 public static function escapeArgument($argument)
77859 {
77860
77861  
77862  
77863  
77864  if ('\\' === \DIRECTORY_SEPARATOR) {
77865 if ('' === $argument) {
77866 return escapeshellarg($argument);
77867 }
77868
77869 $escapedArgument = '';
77870 $quote = false;
77871 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
77872 if ('"' === $part) {
77873 $escapedArgument .= '\\"';
77874 } elseif (self::isSurroundedBy($part, '%')) {
77875
77876  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
77877 } else {
77878
77879  if ('\\' === substr($part, -1)) {
77880 $part .= '\\';
77881 }
77882 $quote = true;
77883 $escapedArgument .= $part;
77884 }
77885 }
77886 if ($quote) {
77887 $escapedArgument = '"'.$escapedArgument.'"';
77888 }
77889
77890 return $escapedArgument;
77891 }
77892
77893 return "'".str_replace("'", "'\\''", $argument)."'";
77894 }
77895
77896
77897
77898
77899
77900
77901
77902
77903
77904
77905
77906
77907
77908 public static function validateInput($caller, $input)
77909 {
77910 if (null !== $input) {
77911 if (\is_resource($input)) {
77912 return $input;
77913 }
77914 if (\is_string($input)) {
77915 return $input;
77916 }
77917 if (is_scalar($input)) {
77918 return (string) $input;
77919 }
77920
77921  if (\is_object($input) && method_exists($input, '__toString')) {
77922 @trigger_error('Passing an object as an input is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
77923
77924 return (string) $input;
77925 }
77926
77927 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
77928 }
77929
77930 return $input;
77931 }
77932
77933 private static function isSurroundedBy($arg, $char)
77934 {
77935 return 2 < \strlen($arg) && $char === $arg[0] && $char === $arg[\strlen($arg) - 1];
77936 }
77937 }
77938 Copyright (c) 2011 Jordi Boggiano
77939
77940 Permission is hereby granted, free of charge, to any person obtaining a copy
77941 of this software and associated documentation files (the "Software"), to deal
77942 in the Software without restriction, including without limitation the rights
77943 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
77944 copies of the Software, and to permit persons to whom the Software is furnished
77945 to do so, subject to the following conditions:
77946
77947 The above copyright notice and this permission notice shall be included in all
77948 copies or substantial portions of the Software.
77949
77950 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
77951 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77952 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
77953 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
77954 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77955 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
77956 THE SOFTWARE.
77957 <?php
77958
77959
77960
77961
77962
77963
77964
77965
77966
77967
77968 namespace Seld\JsonLint;
77969
77970 class DuplicateKeyException extends ParsingException
77971 {
77972 public function __construct($message, $key, array $details = array())
77973 {
77974 $details['key'] = $key;
77975 parent::__construct($message, $details);
77976 }
77977
77978 public function getKey()
77979 {
77980 return $this->details['key'];
77981 }
77982 }
77983 <?php
77984
77985
77986
77987
77988
77989
77990
77991
77992
77993
77994 namespace Seld\JsonLint;
77995 use stdClass;
77996
77997
77998
77999
78000
78001
78002
78003
78004
78005
78006
78007
78008
78009
78010 class JsonParser
78011 {
78012 const DETECT_KEY_CONFLICTS = 1;
78013 const ALLOW_DUPLICATE_KEYS = 2;
78014 const PARSE_TO_ASSOC = 4;
78015
78016 private $lexer;
78017
78018 private $flags;
78019 private $stack;
78020 private $vstack; 
78021  private $lstack; 
78022
78023 private $symbols = array(
78024 'error' => 2,
78025 'JSONString' => 3,
78026 'STRING' => 4,
78027 'JSONNumber' => 5,
78028 'NUMBER' => 6,
78029 'JSONNullLiteral' => 7,
78030 'NULL' => 8,
78031 'JSONBooleanLiteral' => 9,
78032 'TRUE' => 10,
78033 'FALSE' => 11,
78034 'JSONText' => 12,
78035 'JSONValue' => 13,
78036 'EOF' => 14,
78037 'JSONObject' => 15,
78038 'JSONArray' => 16,
78039 '{' => 17,
78040 '}' => 18,
78041 'JSONMemberList' => 19,
78042 'JSONMember' => 20,
78043 ':' => 21,
78044 ',' => 22,
78045 '[' => 23,
78046 ']' => 24,
78047 'JSONElementList' => 25,
78048 '$accept' => 0,
78049 '$end' => 1,
78050 );
78051
78052 private $terminals_ = array(
78053 2 => "error",
78054 4 => "STRING",
78055 6 => "NUMBER",
78056 8 => "NULL",
78057 10 => "TRUE",
78058 11 => "FALSE",
78059 14 => "EOF",
78060 17 => "{",
78061 18 => "}",
78062 21 => ":",
78063 22 => ",",
78064 23 => "[",
78065 24 => "]",
78066 );
78067
78068 private $productions_ = array(
78069 0,
78070 array(3, 1),
78071 array(5, 1),
78072 array(7, 1),
78073 array(9, 1),
78074 array(9, 1),
78075 array(12, 2),
78076 array(13, 1),
78077 array(13, 1),
78078 array(13, 1),
78079 array(13, 1),
78080 array(13, 1),
78081 array(13, 1),
78082 array(15, 2),
78083 array(15, 3),
78084 array(20, 3),
78085 array(19, 1),
78086 array(19, 3),
78087 array(16, 2),
78088 array(16, 3),
78089 array(25, 1),
78090 array(25, 3)
78091 );
78092
78093 private $table = array(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)), array( 1 => array(3)), array( 14 => array(1,16)), array( 14 => array(2,7), 18 => array(2,7), 22 => array(2,7), 24 => array(2,7)), array( 14 => array(2,8), 18 => array(2,8), 22 => array(2,8), 24 => array(2,8)), array( 14 => array(2,9), 18 => array(2,9), 22 => array(2,9), 24 => array(2,9)), array( 14 => array(2,10), 18 => array(2,10), 22 => array(2,10), 24 => array(2,10)), array( 14 => array(2,11), 18 => array(2,11), 22 => array(2,11), 24 => array(2,11)), array( 14 => array(2,12), 18 => array(2,12), 22 => array(2,12), 24 => array(2,12)), array( 14 => array(2,3), 18 => array(2,3), 22 => array(2,3), 24 => array(2,3)), array( 14 => array(2,4), 18 => array(2,4), 22 => array(2,4), 24 => array(2,4)), array( 14 => array(2,5), 18 => array(2,5), 22 => array(2,5), 24 => array(2,5)), array( 14 => array(2,1), 18 => array(2,1), 21 => array(2,1), 22 => array(2,1), 24 => array(2,1)), array( 14 => array(2,2), 18 => array(2,2), 22 => array(2,2), 24 => array(2,2)), array( 3 => 20, 4 => array(1,12), 18 => array(1,17), 19 => 18, 20 => 19 ), 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 ), array( 1 => array(2,6)), array( 14 => array(2,13), 18 => array(2,13), 22 => array(2,13), 24 => array(2,13)), array( 18 => array(1,24), 22 => array(1,25)), array( 18 => array(2,16), 22 => array(2,16)), array( 21 => array(1,26)), array( 14 => array(2,18), 18 => array(2,18), 22 => array(2,18), 24 => array(2,18)), array( 22 => array(1,28), 24 => array(1,27)), array( 22 => array(2,20), 24 => array(2,20)), array( 14 => array(2,14), 18 => array(2,14), 22 => array(2,14), 24 => array(2,14)), array( 3 => 20, 4 => array(1,12), 20 => 29 ), 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)), array( 14 => array(2,19), 18 => array(2,19), 22 => array(2,19), 24 => array(2,19)), 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)), array( 18 => array(2,17), 22 => array(2,17)), array( 18 => array(2,15), 22 => array(2,15)), array( 22 => array(2,21), 24 => array(2,21)),
78094 );
78095
78096 private $defaultActions = array(
78097 16 => array(2, 6)
78098 );
78099
78100
78101
78102
78103
78104
78105 public function lint($input, $flags = 0)
78106 {
78107 try {
78108 $this->parse($input, $flags);
78109 } catch (ParsingException $e) {
78110 return $e;
78111 }
78112 }
78113
78114
78115
78116
78117
78118
78119
78120 public function parse($input, $flags = 0)
78121 {
78122 $this->failOnBOM($input);
78123
78124 $this->flags = $flags;
78125
78126 $this->stack = array(0);
78127 $this->vstack = array(null);
78128 $this->lstack = array();
78129
78130 $yytext = '';
78131 $yylineno = 0;
78132 $yyleng = 0;
78133 $recovering = 0;
78134 $TERROR = 2;
78135 $EOF = 1;
78136
78137 $this->lexer = new Lexer();
78138 $this->lexer->setInput($input);
78139
78140 $yyloc = $this->lexer->yylloc;
78141 $this->lstack[] = $yyloc;
78142
78143 $symbol = null;
78144 $preErrorSymbol = null;
78145 $state = null;
78146 $action = null;
78147 $a = null;
78148 $r = null;
78149 $yyval = new stdClass;
78150 $p = null;
78151 $len = null;
78152 $newState = null;
78153 $expected = null;
78154 $errStr = null;
78155
78156 while (true) {
78157
78158  $state = $this->stack[count($this->stack)-1];
78159
78160
78161  if (isset($this->defaultActions[$state])) {
78162 $action = $this->defaultActions[$state];
78163 } else {
78164 if ($symbol == null) {
78165 $symbol = $this->lex();
78166 }
78167
78168  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
78169 }
78170
78171
78172  if (!$action || !$action[0]) {
78173 if (!$recovering) {
78174
78175  $expected = array();
78176 foreach ($this->table[$state] as $p => $ignore) {
78177 if (isset($this->terminals_[$p]) && $p > 2) {
78178 $expected[] = "'" . $this->terminals_[$p] . "'";
78179 }
78180 }
78181
78182 $message = null;
78183 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
78184 $message = "Invalid string";
78185 if ("'" === substr($this->lexer->match, 0, 1)) {
78186 $message .= ", it appears you used single quotes instead of double quotes";
78187 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
78188 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
78189 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
78190 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
78191 }
78192 }
78193
78194 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
78195 $errStr .= $this->lexer->showPosition() . "\n";
78196 if ($message) {
78197 $errStr .= $message;
78198 } else {
78199 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
78200 $errStr .= implode(', ', $expected);
78201 }
78202
78203 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
78204 $errStr .= " - It appears you have an extra trailing comma";
78205 }
78206
78207 $this->parseError($errStr, array(
78208 'text' => $this->lexer->match,
78209 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
78210 'line' => $this->lexer->yylineno,
78211 'loc' => $yyloc,
78212 'expected' => $expected,
78213 ));
78214 }
78215
78216
78217  if ($recovering == 3) {
78218 if ($symbol == $EOF) {
78219 throw new ParsingException($errStr ?: 'Parsing halted.');
78220 }
78221
78222
78223  $yyleng = $this->lexer->yyleng;
78224 $yytext = $this->lexer->yytext;
78225 $yylineno = $this->lexer->yylineno;
78226 $yyloc = $this->lexer->yylloc;
78227 $symbol = $this->lex();
78228 }
78229
78230
78231  while (true) {
78232
78233  if (array_key_exists($TERROR, $this->table[$state])) {
78234 break;
78235 }
78236 if ($state == 0) {
78237 throw new ParsingException($errStr ?: 'Parsing halted.');
78238 }
78239 $this->popStack(1);
78240 $state = $this->stack[count($this->stack)-1];
78241 }
78242
78243 $preErrorSymbol = $symbol; 
78244  $symbol = $TERROR; 
78245  $state = $this->stack[count($this->stack)-1];
78246 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
78247 $recovering = 3; 
78248  }
78249
78250
78251  if (is_array($action[0]) && count($action) > 1) {
78252 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
78253 }
78254
78255 switch ($action[0]) {
78256 case 1: 
78257  $this->stack[] = $symbol;
78258 $this->vstack[] = $this->lexer->yytext;
78259 $this->lstack[] = $this->lexer->yylloc;
78260 $this->stack[] = $action[1]; 
78261  $symbol = null;
78262 if (!$preErrorSymbol) { 
78263  $yyleng = $this->lexer->yyleng;
78264 $yytext = $this->lexer->yytext;
78265 $yylineno = $this->lexer->yylineno;
78266 $yyloc = $this->lexer->yylloc;
78267 if ($recovering > 0) {
78268 $recovering--;
78269 }
78270 } else { 
78271  $symbol = $preErrorSymbol;
78272 $preErrorSymbol = null;
78273 }
78274 break;
78275
78276 case 2: 
78277  $len = $this->productions_[$action[1]][1];
78278
78279
78280  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
78281  
78282  $yyval->store = array( 
78283  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
78284 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
78285 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
78286 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
78287 );
78288 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
78289
78290 if (!$r instanceof Undefined) {
78291 return $r;
78292 }
78293
78294 if ($len) {
78295 $this->popStack($len);
78296 }
78297
78298 $this->stack[] = $this->productions_[$action[1]][0]; 
78299  $this->vstack[] = $yyval->token;
78300 $this->lstack[] = $yyval->store;
78301 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
78302 $this->stack[] = $newState;
78303 break;
78304
78305 case 3: 
78306
78307 return true;
78308 }
78309 }
78310
78311 return true;
78312 }
78313
78314 protected function parseError($str, $hash)
78315 {
78316 throw new ParsingException($str, $hash);
78317 }
78318
78319
78320  
78321  
78322  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
78323 {
78324
78325  $len = count($tokens) - 1;
78326 switch ($yystate) {
78327 case 1:
78328 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
78329 $yyval->token = $yytext;
78330 break;
78331 case 2:
78332 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
78333 $yyval->token = floatval($yytext);
78334 } else {
78335 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
78336 }
78337 break;
78338 case 3:
78339 $yyval->token = null;
78340 break;
78341 case 4:
78342 $yyval->token = true;
78343 break;
78344 case 5:
78345 $yyval->token = false;
78346 break;
78347 case 6:
78348 return $yyval->token = $tokens[$len-1];
78349 case 13:
78350 if ($this->flags & self::PARSE_TO_ASSOC) {
78351 $yyval->token = array();
78352 } else {
78353 $yyval->token = new stdClass;
78354 }
78355 break;
78356 case 14:
78357 $yyval->token = $tokens[$len-1];
78358 break;
78359 case 15:
78360 $yyval->token = array($tokens[$len-2], $tokens[$len]);
78361 break;
78362 case 16:
78363 if (PHP_VERSION_ID < 70100) {
78364 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
78365 } else {
78366 $property = $tokens[$len][0];
78367 }
78368 if ($this->flags & self::PARSE_TO_ASSOC) {
78369 $yyval->token = array();
78370 $yyval->token[$property] = $tokens[$len][1];
78371 } else {
78372 $yyval->token = new stdClass;
78373 $yyval->token->$property = $tokens[$len][1];
78374 }
78375 break;
78376 case 17:
78377 if ($this->flags & self::PARSE_TO_ASSOC) {
78378 $yyval->token =& $tokens[$len-2];
78379 $key = $tokens[$len][0];
78380 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
78381 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
78382 $errStr .= $this->lexer->showPosition() . "\n";
78383 $errStr .= "Duplicate key: ".$tokens[$len][0];
78384 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
78385 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
78386 $duplicateCount = 1;
78387 do {
78388 $duplicateKey = $key . '.' . $duplicateCount++;
78389 } while (isset($tokens[$len-2][$duplicateKey]));
78390 $key = $duplicateKey;
78391 }
78392 $tokens[$len-2][$key] = $tokens[$len][1];
78393 } else {
78394 $yyval->token = $tokens[$len-2];
78395 if (PHP_VERSION_ID < 70100) {
78396 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
78397 } else {
78398 $key = $tokens[$len][0];
78399 }
78400 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
78401 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
78402 $errStr .= $this->lexer->showPosition() . "\n";
78403 $errStr .= "Duplicate key: ".$tokens[$len][0];
78404 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
78405 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
78406 $duplicateCount = 1;
78407 do {
78408 $duplicateKey = $key . '.' . $duplicateCount++;
78409 } while (isset($tokens[$len-2]->$duplicateKey));
78410 $key = $duplicateKey;
78411 }
78412 $tokens[$len-2]->$key = $tokens[$len][1];
78413 }
78414 break;
78415 case 18:
78416 $yyval->token = array();
78417 break;
78418 case 19:
78419 $yyval->token = $tokens[$len-1];
78420 break;
78421 case 20:
78422 $yyval->token = array($tokens[$len]);
78423 break;
78424 case 21:
78425 $tokens[$len-2][] = $tokens[$len];
78426 $yyval->token = $tokens[$len-2];
78427 break;
78428 }
78429
78430 return new Undefined();
78431 }
78432
78433 private function stringInterpolation($match)
78434 {
78435 switch ($match[0]) {
78436 case '\\\\':
78437 return '\\';
78438 case '\"':
78439 return '"';
78440 case '\b':
78441 return chr(8);
78442 case '\f':
78443 return chr(12);
78444 case '\n':
78445 return "\n";
78446 case '\r':
78447 return "\r";
78448 case '\t':
78449 return "\t";
78450 case '\/':
78451 return "/";
78452 default:
78453 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', ENT_QUOTES, 'UTF-8');
78454 }
78455 }
78456
78457 private function popStack($n)
78458 {
78459 $this->stack = array_slice($this->stack, 0, - (2 * $n));
78460 $this->vstack = array_slice($this->vstack, 0, - $n);
78461 $this->lstack = array_slice($this->lstack, 0, - $n);
78462 }
78463
78464 private function lex()
78465 {
78466 $token = $this->lexer->lex() ?: 1; 
78467  
78468  if (!is_numeric($token)) {
78469 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
78470 }
78471
78472 return $token;
78473 }
78474
78475 private function failOnBOM($input)
78476 {
78477
78478  $bom = "\xEF\xBB\xBF";
78479
78480 if (substr($input, 0, 3) === $bom) {
78481 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
78482 }
78483 }
78484 }
78485 <?php
78486
78487
78488
78489
78490
78491
78492
78493
78494
78495
78496 namespace Seld\JsonLint;
78497
78498
78499
78500
78501
78502
78503 class Lexer
78504 {
78505 private $EOF = 1;
78506 private $rules = array(
78507 0 => '/^\s+/',
78508 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
78509 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
78510 3 => '/^\{/',
78511 4 => '/^\}/',
78512 5 => '/^\[/',
78513 6 => '/^\]/',
78514 7 => '/^,/',
78515 8 => '/^:/',
78516 9 => '/^true\b/',
78517 10 => '/^false\b/',
78518 11 => '/^null\b/',
78519 12 => '/^$/',
78520 13 => '/^./',
78521 );
78522
78523 private $conditions = array(
78524 "INITIAL" => array(
78525 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
78526 "inclusive" => true,
78527 ),
78528 );
78529
78530 private $conditionStack;
78531 private $input;
78532 private $more;
78533 private $done;
78534 private $matched;
78535
78536 public $match;
78537 public $yylineno;
78538 public $yyleng;
78539 public $yytext;
78540 public $yylloc;
78541
78542 public function lex()
78543 {
78544 $r = $this->next();
78545 if (!$r instanceof Undefined) {
78546 return $r;
78547 }
78548
78549 return $this->lex();
78550 }
78551
78552 public function setInput($input)
78553 {
78554 $this->input = $input;
78555 $this->more = false;
78556 $this->done = false;
78557 $this->yylineno = $this->yyleng = 0;
78558 $this->yytext = $this->matched = $this->match = '';
78559 $this->conditionStack = array('INITIAL');
78560 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
78561
78562 return $this;
78563 }
78564
78565 public function showPosition()
78566 {
78567 $pre = str_replace("\n", '', $this->getPastInput());
78568 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
78569
78570 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
78571 }
78572
78573 public function getPastInput()
78574 {
78575 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
78576
78577 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
78578 }
78579
78580 public function getUpcomingInput()
78581 {
78582 $next = $this->match;
78583 if (strlen($next) < 20) {
78584 $next .= substr($this->input, 0, 20 - strlen($next));
78585 }
78586
78587 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
78588 }
78589
78590 protected function parseError($str, $hash)
78591 {
78592 throw new \Exception($str);
78593 }
78594
78595 private function next()
78596 {
78597 if ($this->done) {
78598 return $this->EOF;
78599 }
78600 if ($this->input === '') {
78601 $this->done = true;
78602 }
78603
78604 $token = null;
78605 $match = null;
78606 $col = null;
78607 $lines = null;
78608
78609 if (!$this->more) {
78610 $this->yytext = '';
78611 $this->match = '';
78612 }
78613
78614 $rules = $this->getCurrentRules();
78615 $rulesLen = count($rules);
78616
78617 for ($i=0; $i < $rulesLen; $i++) {
78618 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
78619 preg_match_all('/\n.*/', $match[0], $lines);
78620 $lines = $lines[0];
78621 if ($lines) {
78622 $this->yylineno += count($lines);
78623 }
78624
78625 $this->yylloc = array(
78626 'first_line' => $this->yylloc['last_line'],
78627 'last_line' => $this->yylineno+1,
78628 'first_column' => $this->yylloc['last_column'],
78629 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
78630 );
78631 $this->yytext .= $match[0];
78632 $this->match .= $match[0];
78633 $this->yyleng = strlen($this->yytext);
78634 $this->more = false;
78635 $this->input = substr($this->input, strlen($match[0]));
78636 $this->matched .= $match[0];
78637 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
78638 if ($token) {
78639 return $token;
78640 }
78641
78642 return new Undefined();
78643 }
78644 }
78645
78646 if ($this->input === "") {
78647 return $this->EOF;
78648 }
78649
78650 $this->parseError(
78651 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
78652 array(
78653 'text' => "",
78654 'token' => null,
78655 'line' => $this->yylineno,
78656 )
78657 );
78658 }
78659
78660 private function getCurrentRules()
78661 {
78662 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
78663 }
78664
78665 private function performAction($avoiding_name_collisions, $YY_START)
78666 {
78667 switch ($avoiding_name_collisions) {
78668 case 0:
78669 break;
78670 case 1:
78671 return 6;
78672 break;
78673 case 2:
78674 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
78675
78676 return 4;
78677 case 3:
78678 return 17;
78679 case 4:
78680 return 18;
78681 case 5:
78682 return 23;
78683 case 6:
78684 return 24;
78685 case 7:
78686 return 22;
78687 case 8:
78688 return 21;
78689 case 9:
78690 return 10;
78691 case 10:
78692 return 11;
78693 case 11:
78694 return 8;
78695 case 12:
78696 return 14;
78697 case 13:
78698 return 'INVALID';
78699 }
78700 }
78701 }
78702 <?php
78703
78704
78705
78706
78707
78708
78709
78710
78711
78712
78713 namespace Seld\JsonLint;
78714
78715 class ParsingException extends \Exception
78716 {
78717 protected $details;
78718
78719 public function __construct($message, $details = array())
78720 {
78721 $this->details = $details;
78722 parent::__construct($message);
78723 }
78724
78725 public function getDetails()
78726 {
78727 return $this->details;
78728 }
78729 }
78730 <?php
78731
78732
78733
78734
78735
78736
78737
78738
78739
78740
78741 namespace Seld\JsonLint;
78742
78743 class Undefined
78744 {
78745 }
78746 MIT License
78747
78748 Copyright (c) 2016
78749
78750 Permission is hereby granted, free of charge, to any person obtaining a copy
78751 of this software and associated documentation files (the "Software"), to deal
78752 in the Software without restriction, including without limitation the rights
78753 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
78754 copies of the Software, and to permit persons to whom the Software is
78755 furnished to do so, subject to the following conditions:
78756
78757 The above copyright notice and this permission notice shall be included in all
78758 copies or substantial portions of the Software.
78759
78760 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
78761 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
78762 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
78763 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
78764 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
78765 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
78766 SOFTWARE.
78767 <?php
78768
78769 require __DIR__ . '/../vendor/autoload.php';
78770
78771 $data = json_decode(file_get_contents('data.json'));
78772
78773
78774 $validator = new JsonSchema\Validator();
78775 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
78776
78777 if ($validator->isValid()) {
78778 echo "The supplied JSON validates against the schema.\n";
78779 } else {
78780 echo "JSON does not validate. Violations:\n";
78781 foreach ($validator->getErrors() as $error) {
78782 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
78783 }
78784 }
78785 <?php
78786
78787
78788
78789
78790
78791
78792
78793
78794 namespace JsonSchema\Constraints;
78795
78796 use JsonSchema\Entity\JsonPointer;
78797 use JsonSchema\Exception\InvalidArgumentException;
78798 use JsonSchema\Exception\ValidationException;
78799 use JsonSchema\Validator;
78800
78801
78802
78803
78804
78805 class BaseConstraint
78806 {
78807
78808
78809
78810 protected $errors = array();
78811
78812
78813
78814
78815 protected $errorMask = Validator::ERROR_NONE;
78816
78817
78818
78819
78820 protected $factory;
78821
78822
78823
78824
78825 public function __construct(Factory $factory = null)
78826 {
78827 $this->factory = $factory ?: new Factory();
78828 }
78829
78830 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
78831 {
78832 $error = array(
78833 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
78834 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
78835 'message' => $message,
78836 'constraint' => $constraint,
78837 'context' => $this->factory->getErrorContext(),
78838 );
78839
78840 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
78841 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
78842 }
78843
78844 if (is_array($more) && count($more) > 0) {
78845 $error += $more;
78846 }
78847
78848 $this->errors[] = $error;
78849 $this->errorMask |= $error['context'];
78850 }
78851
78852 public function addErrors(array $errors)
78853 {
78854 if ($errors) {
78855 $this->errors = array_merge($this->errors, $errors);
78856 $errorMask = &$this->errorMask;
78857 array_walk($errors, function ($error) use (&$errorMask) {
78858 if (isset($error['context'])) {
78859 $errorMask |= $error['context'];
78860 }
78861 });
78862 }
78863 }
78864
78865 public function getErrors($errorContext = Validator::ERROR_ALL)
78866 {
78867 if ($errorContext === Validator::ERROR_ALL) {
78868 return $this->errors;
78869 }
78870
78871 return array_filter($this->errors, function ($error) use ($errorContext) {
78872 if ($errorContext & $error['context']) {
78873 return true;
78874 }
78875 });
78876 }
78877
78878 public function numErrors($errorContext = Validator::ERROR_ALL)
78879 {
78880 if ($errorContext === Validator::ERROR_ALL) {
78881 return count($this->errors);
78882 }
78883
78884 return count($this->getErrors($errorContext));
78885 }
78886
78887 public function isValid()
78888 {
78889 return !$this->getErrors();
78890 }
78891
78892
78893
78894
78895
78896 public function reset()
78897 {
78898 $this->errors = array();
78899 $this->errorMask = Validator::ERROR_NONE;
78900 }
78901
78902
78903
78904
78905
78906
78907 public function getErrorMask()
78908 {
78909 return $this->errorMask;
78910 }
78911
78912
78913
78914
78915
78916
78917
78918
78919 public static function arrayToObjectRecursive($array)
78920 {
78921 $json = json_encode($array);
78922 if (json_last_error() !== \JSON_ERROR_NONE) {
78923 $message = 'Unable to encode schema array as JSON';
78924 if (function_exists('json_last_error_msg')) {
78925 $message .= ': ' . json_last_error_msg();
78926 }
78927 throw new InvalidArgumentException($message);
78928 }
78929
78930 return (object) json_decode($json);
78931 }
78932 }
78933 <?php
78934
78935
78936
78937
78938
78939
78940
78941
78942 namespace JsonSchema\Constraints;
78943
78944 use JsonSchema\Entity\JsonPointer;
78945
78946
78947
78948
78949
78950
78951
78952 class CollectionConstraint extends Constraint
78953 {
78954
78955
78956
78957 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
78958 {
78959
78960  if (isset($schema->minItems) && count($value) < $schema->minItems) {
78961 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
78962 }
78963
78964
78965  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
78966 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
78967 }
78968
78969
78970  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
78971 $unique = $value;
78972 if (is_array($value) && count($value)) {
78973 $unique = array_map(function ($e) {
78974 return var_export($e, true);
78975 }, $value);
78976 }
78977 if (count(array_unique($unique)) != count($value)) {
78978 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
78979 }
78980 }
78981
78982
78983  if (isset($schema->items)) {
78984 $this->validateItems($value, $schema, $path, $i);
78985 }
78986 }
78987
78988
78989
78990
78991
78992
78993
78994
78995
78996 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
78997 {
78998 if (is_object($schema->items)) {
78999
79000  foreach ($value as $k => &$v) {
79001 $initErrors = $this->getErrors();
79002
79003
79004  $this->checkUndefined($v, $schema->items, $path, $k);
79005
79006
79007  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
79008 $secondErrors = $this->getErrors();
79009 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
79010 }
79011
79012
79013  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
79014 $this->errors = $secondErrors;
79015 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
79016 $this->errors = $initErrors;
79017 }
79018 }
79019 unset($v); 
79020
79021 } else {
79022
79023  foreach ($value as $k => &$v) {
79024 if (array_key_exists($k, $schema->items)) {
79025 $this->checkUndefined($v, $schema->items[$k], $path, $k);
79026 } else {
79027
79028  if (property_exists($schema, 'additionalItems')) {
79029 if ($schema->additionalItems !== false) {
79030 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
79031 } else {
79032 $this->addError(
79033 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
79034 }
79035 } else {
79036
79037  $this->checkUndefined($v, new \stdClass(), $path, $k);
79038 }
79039 }
79040 }
79041 unset($v); 
79042
79043
79044
79045  if (count($value) > 0) {
79046 for ($k = count($value); $k < count($schema->items); $k++) {
79047 $undefinedInstance = $this->factory->createInstanceFor('undefined');
79048 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
79049 }
79050 }
79051 }
79052 }
79053 }
79054 <?php
79055
79056
79057
79058
79059
79060
79061
79062
79063 namespace JsonSchema\Constraints;
79064
79065 use JsonSchema\Entity\JsonPointer;
79066
79067
79068
79069
79070
79071
79072
79073 abstract class Constraint extends BaseConstraint implements ConstraintInterface
79074 {
79075 protected $inlineSchemaProperty = '$schema';
79076
79077 const CHECK_MODE_NONE = 0x00000000;
79078 const CHECK_MODE_NORMAL = 0x00000001;
79079 const CHECK_MODE_TYPE_CAST = 0x00000002;
79080 const CHECK_MODE_COERCE_TYPES = 0x00000004;
79081 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
79082 const CHECK_MODE_EXCEPTIONS = 0x00000010;
79083 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
79084 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
79085 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
79086
79087
79088
79089
79090
79091
79092
79093
79094
79095 protected function incrementPath(JsonPointer $path = null, $i)
79096 {
79097 $path = $path ?: new JsonPointer('');
79098 $path = $path->withPropertyPaths(
79099 array_merge(
79100 $path->getPropertyPaths(),
79101 array_filter(array($i), 'strlen')
79102 )
79103 );
79104
79105 return $path;
79106 }
79107
79108
79109
79110
79111
79112
79113
79114
79115
79116 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
79117 {
79118 $validator = $this->factory->createInstanceFor('collection');
79119 $validator->check($value, $schema, $path, $i);
79120
79121 $this->addErrors($validator->getErrors());
79122 }
79123
79124
79125
79126
79127
79128
79129
79130
79131
79132
79133
79134 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
79135 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
79136 {
79137 $validator = $this->factory->createInstanceFor('object');
79138 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
79139
79140 $this->addErrors($validator->getErrors());
79141 }
79142
79143
79144
79145
79146
79147
79148
79149
79150
79151 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
79152 {
79153 $validator = $this->factory->createInstanceFor('type');
79154 $validator->check($value, $schema, $path, $i);
79155
79156 $this->addErrors($validator->getErrors());
79157 }
79158
79159
79160
79161
79162
79163
79164
79165
79166
79167 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
79168 {
79169 $validator = $this->factory->createInstanceFor('undefined');
79170
79171 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
79172
79173 $this->addErrors($validator->getErrors());
79174 }
79175
79176
79177
79178
79179
79180
79181
79182
79183
79184 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
79185 {
79186 $validator = $this->factory->createInstanceFor('string');
79187 $validator->check($value, $schema, $path, $i);
79188
79189 $this->addErrors($validator->getErrors());
79190 }
79191
79192
79193
79194
79195
79196
79197
79198
79199
79200 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
79201 {
79202 $validator = $this->factory->createInstanceFor('number');
79203 $validator->check($value, $schema, $path, $i);
79204
79205 $this->addErrors($validator->getErrors());
79206 }
79207
79208
79209
79210
79211
79212
79213
79214
79215
79216 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
79217 {
79218 $validator = $this->factory->createInstanceFor('enum');
79219 $validator->check($value, $schema, $path, $i);
79220
79221 $this->addErrors($validator->getErrors());
79222 }
79223
79224
79225
79226
79227
79228
79229
79230
79231
79232 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
79233 {
79234 $validator = $this->factory->createInstanceFor('format');
79235 $validator->check($value, $schema, $path, $i);
79236
79237 $this->addErrors($validator->getErrors());
79238 }
79239
79240
79241
79242
79243
79244
79245 protected function getTypeCheck()
79246 {
79247 return $this->factory->getTypeCheck();
79248 }
79249
79250
79251
79252
79253
79254
79255 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
79256 {
79257 $result = array_map(
79258 function ($path) {
79259 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
79260 },
79261 $pointer->getPropertyPaths()
79262 );
79263
79264 return trim(implode('', $result), '.');
79265 }
79266 }
79267 <?php
79268
79269
79270
79271
79272
79273
79274
79275
79276 namespace JsonSchema\Constraints;
79277
79278 use JsonSchema\Entity\JsonPointer;
79279
79280
79281
79282
79283
79284
79285 interface ConstraintInterface
79286 {
79287
79288
79289
79290
79291
79292 public function getErrors();
79293
79294
79295
79296
79297
79298
79299 public function addErrors(array $errors);
79300
79301
79302
79303
79304
79305
79306
79307
79308
79309 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
79310
79311
79312
79313
79314
79315
79316 public function isValid();
79317
79318
79319
79320
79321
79322
79323
79324
79325
79326
79327
79328
79329
79330 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
79331 }
79332 <?php
79333
79334
79335
79336
79337
79338
79339
79340
79341 namespace JsonSchema\Constraints;
79342
79343 use JsonSchema\Entity\JsonPointer;
79344
79345
79346
79347
79348
79349
79350
79351 class EnumConstraint extends Constraint
79352 {
79353
79354
79355
79356 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
79357 {
79358
79359  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
79360 return;
79361 }
79362 $type = gettype($element);
79363
79364 foreach ($schema->enum as $enum) {
79365 $enumType = gettype($enum);
79366 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
79367 if ((object) $element == $enum) {
79368 return;
79369 }
79370 }
79371
79372 if ($type === gettype($enum)) {
79373 if ($type == 'object') {
79374 if ($element == $enum) {
79375 return;
79376 }
79377 } elseif ($element === $enum) {
79378 return;
79379 }
79380 }
79381 }
79382
79383 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
79384 }
79385 }
79386 <?php
79387
79388
79389
79390
79391
79392
79393
79394
79395 namespace JsonSchema\Constraints;
79396
79397 use JsonSchema\Exception\InvalidArgumentException;
79398 use JsonSchema\SchemaStorage;
79399 use JsonSchema\SchemaStorageInterface;
79400 use JsonSchema\Uri\UriRetriever;
79401 use JsonSchema\UriRetrieverInterface;
79402 use JsonSchema\Validator;
79403
79404
79405
79406
79407 class Factory
79408 {
79409
79410
79411
79412 protected $schemaStorage;
79413
79414
79415
79416
79417 protected $uriRetriever;
79418
79419
79420
79421
79422 private $checkMode = Constraint::CHECK_MODE_NORMAL;
79423
79424
79425
79426
79427 private $typeCheck = array();
79428
79429
79430
79431
79432 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
79433
79434
79435
79436
79437 protected $constraintMap = array(
79438 'array' => 'JsonSchema\Constraints\CollectionConstraint',
79439 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
79440 'object' => 'JsonSchema\Constraints\ObjectConstraint',
79441 'type' => 'JsonSchema\Constraints\TypeConstraint',
79442 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
79443 'string' => 'JsonSchema\Constraints\StringConstraint',
79444 'number' => 'JsonSchema\Constraints\NumberConstraint',
79445 'enum' => 'JsonSchema\Constraints\EnumConstraint',
79446 'format' => 'JsonSchema\Constraints\FormatConstraint',
79447 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
79448 'validator' => 'JsonSchema\Validator'
79449 );
79450
79451
79452
79453
79454 private $instanceCache = array();
79455
79456
79457
79458
79459
79460
79461 public function __construct(
79462 SchemaStorageInterface $schemaStorage = null,
79463 UriRetrieverInterface $uriRetriever = null,
79464 $checkMode = Constraint::CHECK_MODE_NORMAL
79465 ) {
79466
79467  $this->setConfig($checkMode);
79468
79469 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
79470 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
79471 }
79472
79473
79474
79475
79476
79477
79478 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
79479 {
79480 $this->checkMode = $checkMode;
79481 }
79482
79483
79484
79485
79486
79487
79488 public function addConfig($options)
79489 {
79490 $this->checkMode |= $options;
79491 }
79492
79493
79494
79495
79496
79497
79498 public function removeConfig($options)
79499 {
79500 $this->checkMode &= ~$options;
79501 }
79502
79503
79504
79505
79506
79507
79508
79509
79510 public function getConfig($options = null)
79511 {
79512 if ($options === null) {
79513 return $this->checkMode;
79514 }
79515
79516 return $this->checkMode & $options;
79517 }
79518
79519
79520
79521
79522 public function getUriRetriever()
79523 {
79524 return $this->uriRetriever;
79525 }
79526
79527 public function getSchemaStorage()
79528 {
79529 return $this->schemaStorage;
79530 }
79531
79532 public function getTypeCheck()
79533 {
79534 if (!isset($this->typeCheck[$this->checkMode])) {
79535 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
79536 ? new TypeCheck\LooseTypeCheck()
79537 : new TypeCheck\StrictTypeCheck();
79538 }
79539
79540 return $this->typeCheck[$this->checkMode];
79541 }
79542
79543
79544
79545
79546
79547
79548
79549 public function setConstraintClass($name, $class)
79550 {
79551
79552  if (!class_exists($class)) {
79553 throw new InvalidArgumentException('Unknown constraint ' . $name);
79554 }
79555
79556  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
79557 throw new InvalidArgumentException('Invalid class ' . $name);
79558 }
79559 $this->constraintMap[$name] = $class;
79560
79561 return $this;
79562 }
79563
79564
79565
79566
79567
79568
79569
79570
79571
79572
79573 public function createInstanceFor($constraintName)
79574 {
79575 if (!isset($this->constraintMap[$constraintName])) {
79576 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
79577 }
79578
79579 if (!isset($this->instanceCache[$constraintName])) {
79580 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
79581 }
79582
79583 return clone $this->instanceCache[$constraintName];
79584 }
79585
79586
79587
79588
79589
79590
79591 public function getErrorContext()
79592 {
79593 return $this->errorContext;
79594 }
79595
79596
79597
79598
79599
79600
79601 public function setErrorContext($errorContext)
79602 {
79603 $this->errorContext = $errorContext;
79604 }
79605 }
79606 <?php
79607
79608
79609
79610
79611
79612
79613
79614
79615 namespace JsonSchema\Constraints;
79616
79617 use JsonSchema\Entity\JsonPointer;
79618 use JsonSchema\Rfc3339;
79619
79620
79621
79622
79623
79624
79625
79626
79627 class FormatConstraint extends Constraint
79628 {
79629
79630
79631
79632 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
79633 {
79634 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
79635 return;
79636 }
79637
79638 switch ($schema->format) {
79639 case 'date':
79640 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
79641 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
79642 }
79643 break;
79644
79645 case 'time':
79646 if (!$this->validateDateTime($element, 'H:i:s')) {
79647 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
79648 }
79649 break;
79650
79651 case 'date-time':
79652 if (null === Rfc3339::createFromString($element)) {
79653 $this->addError($path, sprintf('Invalid date-time %s, expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm', json_encode($element)), 'format', array('format' => $schema->format));
79654 }
79655 break;
79656
79657 case 'utc-millisec':
79658 if (!$this->validateDateTime($element, 'U')) {
79659 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
79660 }
79661 break;
79662
79663 case 'regex':
79664 if (!$this->validateRegex($element)) {
79665 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
79666 }
79667 break;
79668
79669 case 'color':
79670 if (!$this->validateColor($element)) {
79671 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
79672 }
79673 break;
79674
79675 case 'style':
79676 if (!$this->validateStyle($element)) {
79677 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
79678 }
79679 break;
79680
79681 case 'phone':
79682 if (!$this->validatePhone($element)) {
79683 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
79684 }
79685 break;
79686
79687 case 'uri':
79688 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
79689 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
79690 }
79691 break;
79692
79693 case 'uriref':
79694 case 'uri-reference':
79695 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
79696
79697  
79698  
79699  if (substr($element, 0, 2) === '//') { 
79700  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
79701 } elseif (substr($element, 0, 1) === '/') { 
79702  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
79703 } elseif (strlen($element)) { 
79704  $pathParts = explode('/', $element, 2);
79705 if (strpos($pathParts[0], ':') !== false) {
79706 $validURL = null;
79707 } else {
79708 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
79709 }
79710 } else {
79711 $validURL = null;
79712 }
79713 if ($validURL === null) {
79714 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
79715 }
79716 }
79717 break;
79718
79719 case 'email':
79720 $filterFlags = FILTER_NULL_ON_FAILURE;
79721 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
79722
79723  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
79724  }
79725 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
79726 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
79727 }
79728 break;
79729
79730 case 'ip-address':
79731 case 'ipv4':
79732 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
79733 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
79734 }
79735 break;
79736
79737 case 'ipv6':
79738 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
79739 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
79740 }
79741 break;
79742
79743 case 'host-name':
79744 case 'hostname':
79745 if (!$this->validateHostname($element)) {
79746 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
79747 }
79748 break;
79749
79750 default:
79751
79752  
79753  
79754  
79755  
79756  
79757  break;
79758 }
79759 }
79760
79761 protected function validateDateTime($datetime, $format)
79762 {
79763 $dt = \DateTime::createFromFormat($format, $datetime);
79764
79765 if (!$dt) {
79766 return false;
79767 }
79768
79769 if ($datetime === $dt->format($format)) {
79770 return true;
79771 }
79772
79773
79774  
79775  
79776  
79777  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
79778 return true;
79779 }
79780
79781 return false;
79782 }
79783
79784 protected function validateRegex($regex)
79785 {
79786 return false !== @preg_match('/' . $regex . '/u', '');
79787 }
79788
79789 protected function validateColor($color)
79790 {
79791 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
79792 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
79793 'red', 'silver', 'teal', 'white', 'yellow'))) {
79794 return true;
79795 }
79796
79797 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
79798 }
79799
79800 protected function validateStyle($style)
79801 {
79802 $properties = explode(';', rtrim($style, ';'));
79803 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
79804
79805 return empty($invalidEntries);
79806 }
79807
79808 protected function validatePhone($phone)
79809 {
79810 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
79811 }
79812
79813 protected function validateHostname($host)
79814 {
79815 $hostnameRegex = '/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/i';
79816
79817 return preg_match($hostnameRegex, $host);
79818 }
79819 }
79820 <?php
79821
79822
79823
79824
79825
79826
79827
79828
79829 namespace JsonSchema\Constraints;
79830
79831 use JsonSchema\Entity\JsonPointer;
79832
79833
79834
79835
79836
79837
79838
79839 class NumberConstraint extends Constraint
79840 {
79841
79842
79843
79844 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
79845 {
79846
79847  if (isset($schema->exclusiveMinimum)) {
79848 if (isset($schema->minimum)) {
79849 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
79850 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
79851 } elseif ($element < $schema->minimum) {
79852 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
79853 }
79854 } else {
79855 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
79856 }
79857 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
79858 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
79859 }
79860
79861
79862  if (isset($schema->exclusiveMaximum)) {
79863 if (isset($schema->maximum)) {
79864 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
79865 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
79866 } elseif ($element > $schema->maximum) {
79867 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
79868 }
79869 } else {
79870 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
79871 }
79872 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
79873 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
79874 }
79875
79876
79877  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
79878 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
79879 }
79880
79881
79882  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
79883 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
79884 }
79885
79886 $this->checkFormat($element, $schema, $path, $i);
79887 }
79888
79889 private function fmod($number1, $number2)
79890 {
79891 $modulus = ($number1 - round($number1 / $number2) * $number2);
79892 $precision = 0.0000000001;
79893
79894 if (-$precision < $modulus && $modulus < $precision) {
79895 return 0.0;
79896 }
79897
79898 return $modulus;
79899 }
79900 }
79901 <?php
79902
79903
79904
79905
79906
79907
79908
79909
79910 namespace JsonSchema\Constraints;
79911
79912 use JsonSchema\Entity\JsonPointer;
79913
79914
79915
79916
79917
79918
79919
79920 class ObjectConstraint extends Constraint
79921 {
79922
79923
79924
79925 protected $appliedDefaults = array();
79926
79927
79928
79929
79930 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
79931 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
79932 {
79933 if ($element instanceof UndefinedConstraint) {
79934 return;
79935 }
79936
79937 $this->appliedDefaults = $appliedDefaults;
79938
79939 $matches = array();
79940 if ($patternProperties) {
79941
79942  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
79943 }
79944
79945 if ($properties) {
79946
79947  $this->validateProperties($element, $properties, $path);
79948 }
79949
79950
79951  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
79952 }
79953
79954 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
79955 {
79956 $try = array('/', '#', '+', '~', '%');
79957 $matches = array();
79958 foreach ($patternProperties as $pregex => $schema) {
79959 $delimiter = '/';
79960
79961  foreach ($try as $delimiter) {
79962 if (strpos($pregex, $delimiter) === false) { 
79963  break;
79964 }
79965 }
79966
79967
79968  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
79969 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
79970 continue;
79971 }
79972 foreach ($element as $i => $value) {
79973 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
79974 $matches[] = $i;
79975 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
79976 }
79977 }
79978 }
79979
79980 return $matches;
79981 }
79982
79983
79984
79985
79986
79987
79988
79989
79990
79991
79992
79993 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
79994 $properties = null, $additionalProp = null)
79995 {
79996 $this->validateMinMaxConstraint($element, $schema, $path);
79997
79998 foreach ($element as $i => $value) {
79999 $definition = $this->getProperty($properties, $i);
80000
80001
80002  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
80003 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
80004 }
80005
80006
80007  if (!in_array($i, $matches) && $additionalProp && !$definition) {
80008 if ($additionalProp === true) {
80009 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
80010 } else {
80011 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
80012 }
80013 }
80014
80015
80016  $require = $this->getProperty($definition, 'requires');
80017 if ($require && !$this->getProperty($element, $require)) {
80018 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
80019 }
80020
80021 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
80022 if (is_object($property)) {
80023 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
80024 }
80025 }
80026 }
80027
80028
80029
80030
80031
80032
80033
80034
80035 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
80036 {
80037 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
80038
80039 foreach ($properties as $i => $value) {
80040 $property = &$this->getProperty($element, $i, $undefinedConstraint);
80041 $definition = $this->getProperty($properties, $i);
80042
80043 if (is_object($definition)) {
80044
80045  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
80046 }
80047 }
80048 }
80049
80050
80051
80052
80053
80054
80055
80056
80057
80058
80059 protected function &getProperty(&$element, $property, $fallback = null)
80060 {
80061 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
80062 return $element[$property];
80063 } elseif (is_object($element) && property_exists($element, $property)) {
80064 return $element->$property;
80065 }
80066
80067 return $fallback;
80068 }
80069
80070
80071
80072
80073
80074
80075
80076
80077 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
80078 {
80079
80080  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
80081 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
80082 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
80083 }
80084 }
80085
80086  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
80087 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
80088 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
80089 }
80090 }
80091 }
80092 }
80093 <?php
80094
80095
80096
80097
80098
80099
80100
80101
80102 namespace JsonSchema\Constraints;
80103
80104 use JsonSchema\Entity\JsonPointer;
80105 use JsonSchema\Exception\InvalidArgumentException;
80106 use JsonSchema\Exception\InvalidSchemaException;
80107 use JsonSchema\Exception\RuntimeException;
80108 use JsonSchema\Validator;
80109
80110
80111
80112
80113
80114
80115
80116 class SchemaConstraint extends Constraint
80117 {
80118 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
80119
80120
80121
80122
80123 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
80124 {
80125 if ($schema !== null) {
80126
80127  $validationSchema = $schema;
80128 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
80129
80130  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
80131 } else {
80132 throw new InvalidArgumentException('no schema found to verify against');
80133 }
80134
80135
80136  if (is_array($validationSchema)) {
80137 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
80138 }
80139
80140
80141  
80142  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
80143 if (!$this->getTypeCheck()->isObject($validationSchema)) {
80144 throw new RuntimeException('Cannot validate the schema of a non-object');
80145 }
80146 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
80147 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
80148 } else {
80149 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
80150 }
80151
80152
80153  $schemaStorage = $this->factory->getSchemaStorage();
80154 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
80155 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
80156 }
80157
80158
80159  $initialErrorCount = $this->numErrors();
80160 $initialConfig = $this->factory->getConfig();
80161 $initialContext = $this->factory->getErrorContext();
80162 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
80163 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
80164 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
80165
80166
80167  try {
80168 $this->check($validationSchema, $schemaSpec);
80169 } catch (\Exception $e) {
80170 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
80171 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
80172 }
80173 }
80174 if ($this->numErrors() > $initialErrorCount) {
80175 $this->addError($path, 'Schema is not valid', 'schema');
80176 }
80177
80178
80179  $this->factory->setConfig($initialConfig);
80180 $this->factory->setErrorContext($initialContext);
80181 }
80182
80183
80184  $this->checkUndefined($element, $validationSchema, $path, $i);
80185 }
80186 }
80187 <?php
80188
80189
80190
80191
80192
80193
80194
80195
80196 namespace JsonSchema\Constraints;
80197
80198 use JsonSchema\Entity\JsonPointer;
80199
80200
80201
80202
80203
80204
80205
80206 class StringConstraint extends Constraint
80207 {
80208
80209
80210
80211 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
80212 {
80213
80214  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
80215 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
80216 'maxLength' => $schema->maxLength,
80217 ));
80218 }
80219
80220
80221  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
80222 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
80223 'minLength' => $schema->minLength,
80224 ));
80225 }
80226
80227
80228  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
80229 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
80230 'pattern' => $schema->pattern,
80231 ));
80232 }
80233
80234 $this->checkFormat($element, $schema, $path, $i);
80235 }
80236
80237 private function strlen($string)
80238 {
80239 if (extension_loaded('mbstring')) {
80240 return mb_strlen($string, mb_detect_encoding($string));
80241 }
80242
80243
80244  return strlen($string); 
80245  }
80246 }
80247 <?php
80248
80249 namespace JsonSchema\Constraints\TypeCheck;
80250
80251 class LooseTypeCheck implements TypeCheckInterface
80252 {
80253 public static function isObject($value)
80254 {
80255 return
80256 is_object($value) ||
80257 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
80258 }
80259
80260 public static function isArray($value)
80261 {
80262 return
80263 is_array($value) &&
80264 (count($value) == 0 || !self::isAssociativeArray($value));
80265 }
80266
80267 public static function propertyGet($value, $property)
80268 {
80269 if (is_object($value)) {
80270 return $value->{$property};
80271 }
80272
80273 return $value[$property];
80274 }
80275
80276 public static function propertySet(&$value, $property, $data)
80277 {
80278 if (is_object($value)) {
80279 $value->{$property} = $data;
80280 } else {
80281 $value[$property] = $data;
80282 }
80283 }
80284
80285 public static function propertyExists($value, $property)
80286 {
80287 if (is_object($value)) {
80288 return property_exists($value, $property);
80289 }
80290
80291 return array_key_exists($property, $value);
80292 }
80293
80294 public static function propertyCount($value)
80295 {
80296 if (is_object($value)) {
80297 return count(get_object_vars($value));
80298 }
80299
80300 return count($value);
80301 }
80302
80303
80304
80305
80306
80307
80308
80309
80310 private static function isAssociativeArray($arr)
80311 {
80312 return array_keys($arr) !== range(0, count($arr) - 1);
80313 }
80314 }
80315 <?php
80316
80317 namespace JsonSchema\Constraints\TypeCheck;
80318
80319 class StrictTypeCheck implements TypeCheckInterface
80320 {
80321 public static function isObject($value)
80322 {
80323 return is_object($value);
80324 }
80325
80326 public static function isArray($value)
80327 {
80328 return is_array($value);
80329 }
80330
80331 public static function propertyGet($value, $property)
80332 {
80333 return $value->{$property};
80334 }
80335
80336 public static function propertySet(&$value, $property, $data)
80337 {
80338 $value->{$property} = $data;
80339 }
80340
80341 public static function propertyExists($value, $property)
80342 {
80343 return property_exists($value, $property);
80344 }
80345
80346 public static function propertyCount($value)
80347 {
80348 if (!is_object($value)) {
80349 return 0;
80350 }
80351
80352 return count(get_object_vars($value));
80353 }
80354 }
80355 <?php
80356
80357 namespace JsonSchema\Constraints\TypeCheck;
80358
80359 interface TypeCheckInterface
80360 {
80361 public static function isObject($value);
80362
80363 public static function isArray($value);
80364
80365 public static function propertyGet($value, $property);
80366
80367 public static function propertySet(&$value, $property, $data);
80368
80369 public static function propertyExists($value, $property);
80370
80371 public static function propertyCount($value);
80372 }
80373 <?php
80374
80375
80376
80377
80378
80379
80380
80381
80382 namespace JsonSchema\Constraints;
80383
80384 use JsonSchema\Entity\JsonPointer;
80385 use JsonSchema\Exception\InvalidArgumentException;
80386 use UnexpectedValueException as StandardUnexpectedValueException;
80387
80388
80389
80390
80391
80392
80393
80394 class TypeConstraint extends Constraint
80395 {
80396
80397
80398
80399 public static $wording = array(
80400 'integer' => 'an integer',
80401 'number' => 'a number',
80402 'boolean' => 'a boolean',
80403 'object' => 'an object',
80404 'array' => 'an array',
80405 'string' => 'a string',
80406 'null' => 'a null',
80407 'any' => null, 
80408  0 => null, 
80409  );
80410
80411
80412
80413
80414 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
80415 {
80416 $type = isset($schema->type) ? $schema->type : null;
80417 $isValid = false;
80418 $wording = array();
80419
80420 if (is_array($type)) {
80421 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
80422 } elseif (is_object($type)) {
80423 $this->checkUndefined($value, $type, $path);
80424
80425 return;
80426 } else {
80427 $isValid = $this->validateType($value, $type);
80428 }
80429
80430 if ($isValid === false) {
80431 if (!is_array($type)) {
80432 $this->validateTypeNameWording($type);
80433 $wording[] = self::$wording[$type];
80434 }
80435 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
80436 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
80437 }
80438 }
80439
80440
80441
80442
80443
80444
80445
80446
80447
80448
80449
80450
80451 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
80452 {
80453 foreach ($type as $tp) {
80454
80455  
80456  if (is_object($tp)) {
80457 if (!$isValid) {
80458 $validator = $this->factory->createInstanceFor('type');
80459 $subSchema = new \stdClass();
80460 $subSchema->type = $tp;
80461 $validator->check($value, $subSchema, $path, null);
80462 $error = $validator->getErrors();
80463 $isValid = !(bool) $error;
80464 $validTypesWording[] = self::$wording['object'];
80465 }
80466 } else {
80467 $this->validateTypeNameWording($tp);
80468 $validTypesWording[] = self::$wording[$tp];
80469 if (!$isValid) {
80470 $isValid = $this->validateType($value, $tp);
80471 }
80472 }
80473 }
80474 }
80475
80476
80477
80478
80479
80480
80481
80482
80483
80484
80485
80486
80487 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
80488 {
80489 if ($listEnd === false || !isset($elements[1])) {
80490 return implode($delimiter, $elements);
80491 }
80492 $lastElement = array_slice($elements, -1);
80493 $firsElements = join($delimiter, array_slice($elements, 0, -1));
80494 $implodedElements = array_merge(array($firsElements), $lastElement);
80495
80496 return join(" $listEnd ", $implodedElements);
80497 }
80498
80499
80500
80501
80502
80503
80504
80505
80506
80507 protected function validateTypeNameWording($type)
80508 {
80509 if (!isset(self::$wording[$type])) {
80510 throw new StandardUnexpectedValueException(
80511 sprintf(
80512 'No wording for %s available, expected wordings are: [%s]',
80513 var_export($type, true),
80514 implode(', ', array_filter(self::$wording)))
80515 );
80516 }
80517 }
80518
80519
80520
80521
80522
80523
80524
80525
80526
80527
80528
80529 protected function validateType(&$value, $type)
80530 {
80531
80532  if (!$type) {
80533 return true;
80534 }
80535
80536 if ('any' === $type) {
80537 return true;
80538 }
80539
80540 if ('object' === $type) {
80541 return $this->getTypeCheck()->isObject($value);
80542 }
80543
80544 if ('array' === $type) {
80545 return $this->getTypeCheck()->isArray($value);
80546 }
80547
80548 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
80549
80550 if ('integer' === $type) {
80551 if ($coerce) {
80552 $value = $this->toInteger($value);
80553 }
80554
80555 return is_int($value);
80556 }
80557
80558 if ('number' === $type) {
80559 if ($coerce) {
80560 $value = $this->toNumber($value);
80561 }
80562
80563 return is_numeric($value) && !is_string($value);
80564 }
80565
80566 if ('boolean' === $type) {
80567 if ($coerce) {
80568 $value = $this->toBoolean($value);
80569 }
80570
80571 return is_bool($value);
80572 }
80573
80574 if ('string' === $type) {
80575 return is_string($value);
80576 }
80577
80578 if ('email' === $type) {
80579 return is_string($value);
80580 }
80581
80582 if ('null' === $type) {
80583 return is_null($value);
80584 }
80585
80586 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
80587 }
80588
80589
80590
80591
80592
80593
80594
80595
80596 protected function toBoolean($value)
80597 {
80598 if ($value === 'true') {
80599 return true;
80600 }
80601
80602 if ($value === 'false') {
80603 return false;
80604 }
80605
80606 return $value;
80607 }
80608
80609
80610
80611
80612
80613
80614
80615
80616 protected function toNumber($value)
80617 {
80618 if (is_numeric($value)) {
80619 return $value + 0; 
80620  }
80621
80622 return $value;
80623 }
80624
80625 protected function toInteger($value)
80626 {
80627 if (is_numeric($value) && (int) $value == $value) {
80628 return (int) $value; 
80629  }
80630
80631 return $value;
80632 }
80633 }
80634 <?php
80635
80636
80637
80638
80639
80640
80641
80642
80643 namespace JsonSchema\Constraints;
80644
80645 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
80646 use JsonSchema\Entity\JsonPointer;
80647 use JsonSchema\Exception\ValidationException;
80648 use JsonSchema\Uri\UriResolver;
80649
80650
80651
80652
80653
80654
80655
80656 class UndefinedConstraint extends Constraint
80657 {
80658
80659
80660
80661 protected $appliedDefaults = array();
80662
80663
80664
80665
80666 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
80667 {
80668 if (is_null($schema) || !is_object($schema)) {
80669 return;
80670 }
80671
80672 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
80673 if ($fromDefault) {
80674 $path->setFromDefault();
80675 }
80676
80677
80678  $this->validateCommonProperties($value, $schema, $path, $i);
80679
80680
80681  $this->validateOfProperties($value, $schema, $path, '');
80682
80683
80684  $this->validateTypes($value, $schema, $path, $i);
80685 }
80686
80687
80688
80689
80690
80691
80692
80693
80694
80695 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
80696 {
80697
80698  if ($this->getTypeCheck()->isArray($value)) {
80699 $this->checkArray($value, $schema, $path, $i);
80700 }
80701
80702
80703  if (LooseTypeCheck::isObject($value)) { 
80704  
80705  
80706  $this->checkObject(
80707 $value,
80708 $schema,
80709 $path,
80710 isset($schema->properties) ? $schema->properties : null,
80711 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
80712 isset($schema->patternProperties) ? $schema->patternProperties : null,
80713 $this->appliedDefaults
80714 );
80715 }
80716
80717
80718  if (is_string($value)) {
80719 $this->checkString($value, $schema, $path, $i);
80720 }
80721
80722
80723  if (is_numeric($value)) {
80724 $this->checkNumber($value, $schema, $path, $i);
80725 }
80726
80727
80728  if (isset($schema->enum)) {
80729 $this->checkEnum($value, $schema, $path, $i);
80730 }
80731 }
80732
80733
80734
80735
80736
80737
80738
80739
80740
80741 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
80742 {
80743
80744  if (isset($schema->extends)) {
80745 if (is_string($schema->extends)) {
80746 $schema->extends = $this->validateUri($schema, $schema->extends);
80747 }
80748 if (is_array($schema->extends)) {
80749 foreach ($schema->extends as $extends) {
80750 $this->checkUndefined($value, $extends, $path, $i);
80751 }
80752 } else {
80753 $this->checkUndefined($value, $schema->extends, $path, $i);
80754 }
80755 }
80756
80757
80758  if (!$path->fromDefault()) {
80759 $this->applyDefaultValues($value, $schema, $path);
80760 }
80761
80762
80763  if ($this->getTypeCheck()->isObject($value)) {
80764 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
80765
80766  foreach ($schema->required as $required) {
80767 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
80768 $this->addError(
80769 $this->incrementPath($path ?: new JsonPointer(''), $required),
80770 'The property ' . $required . ' is required',
80771 'required'
80772 );
80773 }
80774 }
80775 } elseif (isset($schema->required) && !is_array($schema->required)) {
80776
80777  if ($schema->required && $value instanceof self) {
80778 $propertyPaths = $path->getPropertyPaths();
80779 $propertyName = end($propertyPaths);
80780 $this->addError(
80781 $path,
80782 'The property ' . $propertyName . ' is required',
80783 'required'
80784 );
80785 }
80786 } else {
80787
80788  
80789  if ($value instanceof self) {
80790 return;
80791 }
80792 }
80793 }
80794
80795
80796  if (!($value instanceof self)) {
80797 $this->checkType($value, $schema, $path, $i);
80798 }
80799
80800
80801  if (isset($schema->disallow)) {
80802 $initErrors = $this->getErrors();
80803
80804 $typeSchema = new \stdClass();
80805 $typeSchema->type = $schema->disallow;
80806 $this->checkType($value, $typeSchema, $path);
80807
80808
80809  if (count($this->getErrors()) == count($initErrors)) {
80810 $this->addError($path, 'Disallowed value was matched', 'disallow');
80811 } else {
80812 $this->errors = $initErrors;
80813 }
80814 }
80815
80816 if (isset($schema->not)) {
80817 $initErrors = $this->getErrors();
80818 $this->checkUndefined($value, $schema->not, $path, $i);
80819
80820
80821  if (count($this->getErrors()) == count($initErrors)) {
80822 $this->addError($path, 'Matched a schema which it should not', 'not');
80823 } else {
80824 $this->errors = $initErrors;
80825 }
80826 }
80827
80828
80829  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
80830 $this->validateDependencies($value, $schema->dependencies, $path);
80831 }
80832 }
80833
80834
80835
80836
80837
80838
80839
80840
80841
80842
80843 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
80844 {
80845
80846  if (!$requiredOnly) {
80847 return true;
80848 }
80849
80850  if (
80851 $name !== null
80852 && isset($parentSchema->required)
80853 && is_array($parentSchema->required)
80854 && in_array($name, $parentSchema->required)
80855 ) {
80856 return true;
80857 }
80858
80859  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
80860 return true;
80861 }
80862
80863  return false;
80864 }
80865
80866
80867
80868
80869
80870
80871
80872
80873 protected function applyDefaultValues(&$value, $schema, $path)
80874 {
80875
80876  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
80877 return;
80878 }
80879
80880
80881  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
80882 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
80883
80884  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
80885 $propertyDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($propertyDefinition);
80886 if (
80887 !LooseTypeCheck::propertyExists($value, $currentProperty)
80888 && property_exists($propertyDefinition, 'default')
80889 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
80890 ) {
80891
80892  if (is_object($propertyDefinition->default)) {
80893 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
80894 } else {
80895 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
80896 }
80897 $this->appliedDefaults[] = $currentProperty;
80898 }
80899 }
80900 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
80901 $items = array();
80902 if (LooseTypeCheck::isArray($schema->items)) {
80903 $items = $schema->items;
80904 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
80905 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
80906 }
80907
80908  foreach ($items as $currentItem => $itemDefinition) {
80909 $itemDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($itemDefinition);
80910 if (
80911 !array_key_exists($currentItem, $value)
80912 && property_exists($itemDefinition, 'default')
80913 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
80914 if (is_object($itemDefinition->default)) {
80915 $value[$currentItem] = clone $itemDefinition->default;
80916 } else {
80917 $value[$currentItem] = $itemDefinition->default;
80918 }
80919 }
80920 $path->setFromDefault();
80921 }
80922 } elseif (
80923 $value instanceof self
80924 && property_exists($schema, 'default')
80925 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
80926
80927  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
80928 $path->setFromDefault();
80929 }
80930 }
80931
80932
80933
80934
80935
80936
80937
80938
80939
80940 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
80941 {
80942
80943  if ($value instanceof self) {
80944 return;
80945 }
80946
80947 if (isset($schema->allOf)) {
80948 $isValid = true;
80949 foreach ($schema->allOf as $allOf) {
80950 $initErrors = $this->getErrors();
80951 $this->checkUndefined($value, $allOf, $path, $i);
80952 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
80953 }
80954 if (!$isValid) {
80955 $this->addError($path, 'Failed to match all schemas', 'allOf');
80956 }
80957 }
80958
80959 if (isset($schema->anyOf)) {
80960 $isValid = false;
80961 $startErrors = $this->getErrors();
80962 $caughtException = null;
80963 foreach ($schema->anyOf as $anyOf) {
80964 $initErrors = $this->getErrors();
80965 try {
80966 $this->checkUndefined($value, $anyOf, $path, $i);
80967 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
80968 break;
80969 }
80970 } catch (ValidationException $e) {
80971 $isValid = false;
80972 }
80973 }
80974 if (!$isValid) {
80975 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
80976 } else {
80977 $this->errors = $startErrors;
80978 }
80979 }
80980
80981 if (isset($schema->oneOf)) {
80982 $allErrors = array();
80983 $matchedSchemas = 0;
80984 $startErrors = $this->getErrors();
80985 foreach ($schema->oneOf as $oneOf) {
80986 try {
80987 $this->errors = array();
80988 $this->checkUndefined($value, $oneOf, $path, $i);
80989 if (count($this->getErrors()) == 0) {
80990 $matchedSchemas++;
80991 }
80992 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
80993 } catch (ValidationException $e) {
80994
80995  
80996  }
80997 }
80998 if ($matchedSchemas !== 1) {
80999 $this->addErrors(array_merge($allErrors, $startErrors));
81000 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
81001 } else {
81002 $this->errors = $startErrors;
81003 }
81004 }
81005 }
81006
81007
81008
81009
81010
81011
81012
81013
81014
81015 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
81016 {
81017 foreach ($dependencies as $key => $dependency) {
81018 if ($this->getTypeCheck()->propertyExists($value, $key)) {
81019 if (is_string($dependency)) {
81020
81021  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
81022 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
81023 }
81024 } elseif (is_array($dependency)) {
81025
81026  foreach ($dependency as $d) {
81027 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
81028 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
81029 }
81030 }
81031 } elseif (is_object($dependency)) {
81032
81033  $this->checkUndefined($value, $dependency, $path, $i);
81034 }
81035 }
81036 }
81037 }
81038
81039 protected function validateUri($schema, $schemaUri = null)
81040 {
81041 $resolver = new UriResolver();
81042 $retriever = $this->factory->getUriRetriever();
81043
81044 $jsonSchema = null;
81045 if ($resolver->isValid($schemaUri)) {
81046 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
81047 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
81048 }
81049
81050 return $jsonSchema;
81051 }
81052 }
81053 <?php
81054
81055
81056
81057
81058
81059
81060
81061
81062 namespace JsonSchema\Entity;
81063
81064 use JsonSchema\Exception\InvalidArgumentException;
81065
81066
81067
81068
81069
81070
81071 class JsonPointer
81072 {
81073
81074 private $filename;
81075
81076
81077 private $propertyPaths = array();
81078
81079
81080
81081
81082 private $fromDefault = false;
81083
81084
81085
81086
81087
81088
81089 public function __construct($value)
81090 {
81091 if (!is_string($value)) {
81092 throw new InvalidArgumentException('Ref value must be a string');
81093 }
81094
81095 $splitRef = explode('#', $value, 2);
81096 $this->filename = $splitRef[0];
81097 if (array_key_exists(1, $splitRef)) {
81098 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
81099 }
81100 }
81101
81102
81103
81104
81105
81106
81107 private function decodePropertyPaths($propertyPathString)
81108 {
81109 $paths = array();
81110 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
81111 $path = $this->decodePath($path);
81112 if (is_string($path) && '' !== $path) {
81113 $paths[] = $path;
81114 }
81115 }
81116
81117 return $paths;
81118 }
81119
81120
81121
81122
81123 private function encodePropertyPaths()
81124 {
81125 return array_map(
81126 array($this, 'encodePath'),
81127 $this->getPropertyPaths()
81128 );
81129 }
81130
81131
81132
81133
81134
81135
81136 private function decodePath($path)
81137 {
81138 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
81139 }
81140
81141
81142
81143
81144
81145
81146 private function encodePath($path)
81147 {
81148 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
81149 }
81150
81151
81152
81153
81154 public function getFilename()
81155 {
81156 return $this->filename;
81157 }
81158
81159
81160
81161
81162 public function getPropertyPaths()
81163 {
81164 return $this->propertyPaths;
81165 }
81166
81167
81168
81169
81170
81171
81172 public function withPropertyPaths(array $propertyPaths)
81173 {
81174 $new = clone $this;
81175 $new->propertyPaths = $propertyPaths;
81176
81177 return $new;
81178 }
81179
81180
81181
81182
81183 public function getPropertyPathAsString()
81184 {
81185 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
81186 }
81187
81188
81189
81190
81191 public function __toString()
81192 {
81193 return $this->getFilename() . $this->getPropertyPathAsString();
81194 }
81195
81196
81197
81198
81199 public function setFromDefault()
81200 {
81201 $this->fromDefault = true;
81202 }
81203
81204
81205
81206
81207
81208
81209 public function fromDefault()
81210 {
81211 return $this->fromDefault;
81212 }
81213 }
81214 <?php
81215
81216 namespace JsonSchema\Exception;
81217
81218 interface ExceptionInterface
81219 {
81220 }
81221 <?php
81222
81223
81224
81225
81226
81227
81228
81229
81230 namespace JsonSchema\Exception;
81231
81232
81233
81234
81235 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
81236 {
81237 }
81238 <?php
81239
81240
81241
81242
81243
81244
81245
81246
81247 namespace JsonSchema\Exception;
81248
81249
81250
81251
81252 class InvalidConfigException extends RuntimeException
81253 {
81254 }
81255 <?php
81256
81257
81258
81259
81260
81261
81262
81263
81264 namespace JsonSchema\Exception;
81265
81266
81267
81268
81269 class InvalidSchemaException extends RuntimeException
81270 {
81271 }
81272 <?php
81273
81274
81275
81276
81277
81278
81279
81280
81281 namespace JsonSchema\Exception;
81282
81283
81284
81285
81286 class InvalidSchemaMediaTypeException extends RuntimeException
81287 {
81288 }
81289 <?php
81290
81291
81292
81293
81294
81295
81296
81297
81298 namespace JsonSchema\Exception;
81299
81300
81301
81302
81303 class InvalidSourceUriException extends InvalidArgumentException
81304 {
81305 }
81306 <?php
81307
81308
81309
81310
81311
81312
81313
81314
81315 namespace JsonSchema\Exception;
81316
81317
81318
81319
81320 class JsonDecodingException extends RuntimeException
81321 {
81322 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
81323 {
81324 switch ($code) {
81325 case JSON_ERROR_DEPTH:
81326 $message = 'The maximum stack depth has been exceeded';
81327 break;
81328 case JSON_ERROR_STATE_MISMATCH:
81329 $message = 'Invalid or malformed JSON';
81330 break;
81331 case JSON_ERROR_CTRL_CHAR:
81332 $message = 'Control character error, possibly incorrectly encoded';
81333 break;
81334 case JSON_ERROR_UTF8:
81335 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
81336 break;
81337 case JSON_ERROR_SYNTAX:
81338 $message = 'JSON syntax is malformed';
81339 break;
81340 default:
81341 $message = 'Syntax error';
81342 }
81343 parent::__construct($message, $code, $previous);
81344 }
81345 }
81346 <?php
81347
81348
81349
81350
81351
81352
81353
81354
81355 namespace JsonSchema\Exception;
81356
81357
81358
81359
81360 class ResourceNotFoundException extends RuntimeException
81361 {
81362 }
81363 <?php
81364
81365
81366
81367
81368
81369
81370
81371
81372 namespace JsonSchema\Exception;
81373
81374
81375
81376
81377 class RuntimeException extends \RuntimeException implements ExceptionInterface
81378 {
81379 }
81380 <?php
81381
81382
81383
81384
81385
81386
81387
81388
81389 namespace JsonSchema\Exception;
81390
81391
81392
81393
81394
81395
81396 class UnresolvableJsonPointerException extends InvalidArgumentException
81397 {
81398 }
81399 <?php
81400
81401
81402
81403
81404
81405
81406
81407
81408 namespace JsonSchema\Exception;
81409
81410
81411
81412
81413 class UriResolverException extends RuntimeException
81414 {
81415 }
81416 <?php
81417
81418
81419
81420
81421
81422
81423
81424
81425 namespace JsonSchema\Exception;
81426
81427 class ValidationException extends RuntimeException
81428 {
81429 }
81430 <?php
81431
81432
81433
81434
81435
81436
81437
81438
81439 namespace JsonSchema\Iterator;
81440
81441
81442
81443
81444
81445
81446 class ObjectIterator implements \Iterator, \Countable
81447 {
81448
81449 private $object;
81450
81451
81452 private $position = 0;
81453
81454
81455 private $data = array();
81456
81457
81458 private $initialized = false;
81459
81460
81461
81462
81463 public function __construct($object)
81464 {
81465 $this->object = $object;
81466 }
81467
81468
81469
81470
81471 public function current()
81472 {
81473 $this->initialize();
81474
81475 return $this->data[$this->position];
81476 }
81477
81478
81479
81480
81481 public function next()
81482 {
81483 $this->initialize();
81484 $this->position++;
81485 }
81486
81487
81488
81489
81490 public function key()
81491 {
81492 $this->initialize();
81493
81494 return $this->position;
81495 }
81496
81497
81498
81499
81500 public function valid()
81501 {
81502 $this->initialize();
81503
81504 return isset($this->data[$this->position]);
81505 }
81506
81507
81508
81509
81510 public function rewind()
81511 {
81512 $this->initialize();
81513 $this->position = 0;
81514 }
81515
81516
81517
81518
81519 public function count()
81520 {
81521 $this->initialize();
81522
81523 return count($this->data);
81524 }
81525
81526
81527
81528
81529 private function initialize()
81530 {
81531 if (!$this->initialized) {
81532 $this->data = $this->buildDataFromObject($this->object);
81533 $this->initialized = true;
81534 }
81535 }
81536
81537
81538
81539
81540
81541
81542 private function buildDataFromObject($object)
81543 {
81544 $result = array();
81545
81546 $stack = new \SplStack();
81547 $stack->push($object);
81548
81549 while (!$stack->isEmpty()) {
81550 $current = $stack->pop();
81551 if (is_object($current)) {
81552 array_push($result, $current);
81553 }
81554
81555 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
81556 if (is_object($propertyValue) || is_array($propertyValue)) {
81557 $stack->push($propertyValue);
81558 }
81559 }
81560 }
81561
81562 return $result;
81563 }
81564
81565
81566
81567
81568
81569
81570 private function getDataFromItem($item)
81571 {
81572 if (!is_object($item) && !is_array($item)) {
81573 return array();
81574 }
81575
81576 return is_object($item) ? get_object_vars($item) : $item;
81577 }
81578 }
81579 <?php
81580
81581 namespace JsonSchema;
81582
81583 class Rfc3339
81584 {
81585 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
81586
81587
81588
81589
81590
81591
81592
81593
81594 public static function createFromString($string)
81595 {
81596 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
81597 return null;
81598 }
81599
81600 $dateAndTime = $matches[1];
81601 $microseconds = $matches[2] ?: '.000000';
81602 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
81603 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
81604 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
81605
81606 return $dateTime ?: null;
81607 }
81608 }
81609 <?php
81610
81611 namespace JsonSchema;
81612
81613 use JsonSchema\Constraints\BaseConstraint;
81614 use JsonSchema\Entity\JsonPointer;
81615 use JsonSchema\Exception\UnresolvableJsonPointerException;
81616 use JsonSchema\Uri\UriResolver;
81617 use JsonSchema\Uri\UriRetriever;
81618
81619 class SchemaStorage implements SchemaStorageInterface
81620 {
81621 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
81622
81623 protected $uriRetriever;
81624 protected $uriResolver;
81625 protected $schemas = array();
81626
81627 public function __construct(
81628 UriRetrieverInterface $uriRetriever = null,
81629 UriResolverInterface $uriResolver = null
81630 ) {
81631 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
81632 $this->uriResolver = $uriResolver ?: new UriResolver();
81633 }
81634
81635
81636
81637
81638 public function getUriRetriever()
81639 {
81640 return $this->uriRetriever;
81641 }
81642
81643
81644
81645
81646 public function getUriResolver()
81647 {
81648 return $this->uriResolver;
81649 }
81650
81651
81652
81653
81654 public function addSchema($id, $schema = null)
81655 {
81656 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
81657
81658  
81659  
81660  $schema = $this->uriRetriever->retrieve($id);
81661 }
81662
81663
81664  if (is_array($schema)) {
81665 $schema = BaseConstraint::arrayToObjectRecursive($schema);
81666 }
81667
81668
81669  
81670  if (is_object($schema) && property_exists($schema, 'id')) {
81671 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
81672 $schema->properties->id->format = 'uri-reference';
81673 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
81674 $schema->properties->id->format = 'uri-reference';
81675 $schema->properties->{'$ref'}->format = 'uri-reference';
81676 }
81677 }
81678
81679
81680  $this->expandRefs($schema, $id);
81681
81682 $this->schemas[$id] = $schema;
81683 }
81684
81685
81686
81687
81688
81689
81690
81691 private function expandRefs(&$schema, $base = null)
81692 {
81693 if (!is_object($schema)) {
81694 if (is_array($schema)) {
81695 foreach ($schema as &$member) {
81696 $this->expandRefs($member, $base);
81697 }
81698 }
81699
81700 return;
81701 }
81702
81703 if (property_exists($schema, 'id') && is_string($schema->id) && $base != $schema->id) {
81704 $base = $this->uriResolver->resolve($schema->id, $base);
81705 }
81706
81707 if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
81708 $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $base));
81709 $schema->{'$ref'} = (string) $refPointer;
81710 }
81711
81712 foreach ($schema as &$member) {
81713 $this->expandRefs($member, $base);
81714 }
81715 }
81716
81717
81718
81719
81720 public function getSchema($id)
81721 {
81722 if (!array_key_exists($id, $this->schemas)) {
81723 $this->addSchema($id);
81724 }
81725
81726 return $this->schemas[$id];
81727 }
81728
81729
81730
81731
81732 public function resolveRef($ref)
81733 {
81734 $jsonPointer = new JsonPointer($ref);
81735
81736
81737  $fileName = $jsonPointer->getFilename();
81738 if (!strlen($fileName)) {
81739 throw new UnresolvableJsonPointerException(sprintf(
81740 "Could not resolve fragment '%s': no file is defined",
81741 $jsonPointer->getPropertyPathAsString()
81742 ));
81743 }
81744
81745
81746  $refSchema = $this->getSchema($fileName);
81747 foreach ($jsonPointer->getPropertyPaths() as $path) {
81748 if (is_object($refSchema) && property_exists($refSchema, $path)) {
81749 $refSchema = $this->resolveRefSchema($refSchema->{$path});
81750 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
81751 $refSchema = $this->resolveRefSchema($refSchema[$path]);
81752 } else {
81753 throw new UnresolvableJsonPointerException(sprintf(
81754 'File: %s is found, but could not resolve fragment: %s',
81755 $jsonPointer->getFilename(),
81756 $jsonPointer->getPropertyPathAsString()
81757 ));
81758 }
81759 }
81760
81761 return $refSchema;
81762 }
81763
81764
81765
81766
81767 public function resolveRefSchema($refSchema)
81768 {
81769 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
81770 $newSchema = $this->resolveRef($refSchema->{'$ref'});
81771 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
81772 unset($refSchema->{'$ref'});
81773 }
81774
81775 return $refSchema;
81776 }
81777 }
81778 <?php
81779
81780 namespace JsonSchema;
81781
81782 interface SchemaStorageInterface
81783 {
81784
81785
81786
81787
81788
81789
81790 public function addSchema($id, $schema = null);
81791
81792
81793
81794
81795
81796
81797
81798
81799 public function getSchema($id);
81800
81801
81802
81803
81804
81805
81806
81807
81808 public function resolveRef($ref);
81809
81810
81811
81812
81813
81814
81815
81816
81817 public function resolveRefSchema($refSchema);
81818 }
81819 <?php
81820
81821
81822
81823
81824
81825
81826 namespace JsonSchema\Uri\Retrievers;
81827
81828
81829
81830
81831
81832
81833
81834 abstract class AbstractRetriever implements UriRetrieverInterface
81835 {
81836
81837
81838
81839
81840
81841 protected $contentType;
81842
81843
81844
81845
81846
81847
81848 public function getContentType()
81849 {
81850 return $this->contentType;
81851 }
81852 }
81853 <?php
81854
81855
81856
81857
81858
81859
81860
81861
81862 namespace JsonSchema\Uri\Retrievers;
81863
81864 use JsonSchema\Exception\RuntimeException;
81865 use JsonSchema\Validator;
81866
81867
81868
81869
81870
81871
81872 class Curl extends AbstractRetriever
81873 {
81874 protected $messageBody;
81875
81876 public function __construct()
81877 {
81878 if (!function_exists('curl_init')) {
81879
81880  throw new RuntimeException('cURL not installed'); 
81881  }
81882 }
81883
81884
81885
81886
81887
81888
81889 public function retrieve($uri)
81890 {
81891 $ch = curl_init();
81892
81893 curl_setopt($ch, CURLOPT_URL, $uri);
81894 curl_setopt($ch, CURLOPT_HEADER, true);
81895 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
81896 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
81897
81898 $response = curl_exec($ch);
81899 if (false === $response) {
81900 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
81901 }
81902
81903 $this->fetchMessageBody($response);
81904 $this->fetchContentType($response);
81905
81906 curl_close($ch);
81907
81908 return $this->messageBody;
81909 }
81910
81911
81912
81913
81914 private function fetchMessageBody($response)
81915 {
81916 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
81917 $this->messageBody = $match[1];
81918 }
81919
81920
81921
81922
81923
81924
81925 protected function fetchContentType($response)
81926 {
81927 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
81928 $this->contentType = trim($match[1]);
81929
81930 return true;
81931 }
81932
81933 return false;
81934 }
81935 }
81936 <?php
81937
81938
81939
81940
81941
81942
81943
81944
81945 namespace JsonSchema\Uri\Retrievers;
81946
81947 use JsonSchema\Exception\ResourceNotFoundException;
81948
81949
81950
81951
81952
81953
81954 class FileGetContents extends AbstractRetriever
81955 {
81956 protected $messageBody;
81957
81958
81959
81960
81961
81962
81963 public function retrieve($uri)
81964 {
81965 $errorMessage = null;
81966 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
81967 $errorMessage = $errstr;
81968 });
81969 $response = file_get_contents($uri);
81970 restore_error_handler();
81971
81972 if ($errorMessage) {
81973 throw new ResourceNotFoundException($errorMessage);
81974 }
81975
81976 if (false === $response) {
81977 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
81978 }
81979
81980 if ($response == ''
81981 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
81982 ) {
81983 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
81984 }
81985
81986 $this->messageBody = $response;
81987 if (!empty($http_response_header)) {
81988
81989  
81990  $this->fetchContentType($http_response_header); 
81991  } else { 
81992  
81993  $this->contentType = null;
81994 }
81995
81996 return $this->messageBody;
81997 }
81998
81999
82000
82001
82002
82003
82004 private function fetchContentType(array $headers)
82005 {
82006 foreach ($headers as $header) {
82007 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
82008 return true;
82009 }
82010 }
82011
82012 return false;
82013 }
82014
82015
82016
82017
82018
82019
82020 protected static function getContentTypeMatchInHeader($header)
82021 {
82022 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
82023 return trim($match[1]);
82024 }
82025
82026 return null;
82027 }
82028 }
82029 <?php
82030
82031 namespace JsonSchema\Uri\Retrievers;
82032
82033 use JsonSchema\Validator;
82034
82035
82036
82037
82038
82039
82040
82041
82042
82043
82044
82045
82046
82047 class PredefinedArray extends AbstractRetriever
82048 {
82049
82050
82051
82052
82053
82054 private $schemas;
82055
82056
82057
82058
82059
82060
82061
82062 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
82063 {
82064 $this->schemas = $schemas;
82065 $this->contentType = $contentType;
82066 }
82067
82068
82069
82070
82071
82072
82073 public function retrieve($uri)
82074 {
82075 if (!array_key_exists($uri, $this->schemas)) {
82076 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
82077 'The JSON schema "%s" was not found.',
82078 $uri
82079 ));
82080 }
82081
82082 return $this->schemas[$uri];
82083 }
82084 }
82085 <?php
82086
82087
82088
82089
82090
82091
82092
82093
82094 namespace JsonSchema\Uri\Retrievers;
82095
82096
82097
82098
82099
82100
82101 interface UriRetrieverInterface
82102 {
82103
82104
82105
82106
82107
82108
82109
82110
82111
82112 public function retrieve($uri);
82113
82114
82115
82116
82117
82118
82119 public function getContentType();
82120 }
82121 <?php
82122
82123
82124
82125
82126
82127
82128
82129
82130 namespace JsonSchema\Uri;
82131
82132 use JsonSchema\Exception\UriResolverException;
82133 use JsonSchema\UriResolverInterface;
82134
82135
82136
82137
82138
82139
82140 class UriResolver implements UriResolverInterface
82141 {
82142
82143
82144
82145
82146
82147
82148
82149 public function parse($uri)
82150 {
82151 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
82152
82153 $components = array();
82154 if (5 < count($match)) {
82155 $components = array(
82156 'scheme' => $match[2],
82157 'authority' => $match[4],
82158 'path' => $match[5]
82159 );
82160 }
82161 if (7 < count($match)) {
82162 $components['query'] = $match[7];
82163 }
82164 if (9 < count($match)) {
82165 $components['fragment'] = $match[9];
82166 }
82167
82168 return $components;
82169 }
82170
82171
82172
82173
82174
82175
82176
82177
82178 public function generate(array $components)
82179 {
82180 $uri = $components['scheme'] . '://'
82181 . $components['authority']
82182 . $components['path'];
82183
82184 if (array_key_exists('query', $components) && strlen($components['query'])) {
82185 $uri .= '?' . $components['query'];
82186 }
82187 if (array_key_exists('fragment', $components)) {
82188 $uri .= '#' . $components['fragment'];
82189 }
82190
82191 return $uri;
82192 }
82193
82194
82195
82196
82197 public function resolve($uri, $baseUri = null)
82198 {
82199
82200  if (
82201 !is_null($baseUri) &&
82202 !filter_var($baseUri, \FILTER_VALIDATE_URL) &&
82203 !preg_match('|^[^/]+://|u', $baseUri)
82204 ) {
82205 if (is_file($baseUri)) {
82206 $baseUri = 'file://' . realpath($baseUri);
82207 } elseif (is_dir($baseUri)) {
82208 $baseUri = 'file://' . realpath($baseUri) . '/';
82209 } else {
82210 $baseUri = 'file://' . getcwd() . '/' . $baseUri;
82211 }
82212 }
82213
82214 if ($uri == '') {
82215 return $baseUri;
82216 }
82217
82218 $components = $this->parse($uri);
82219 $path = $components['path'];
82220
82221 if (!empty($components['scheme'])) {
82222 return $uri;
82223 }
82224 $baseComponents = $this->parse($baseUri);
82225 $basePath = $baseComponents['path'];
82226
82227 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
82228 if (isset($components['fragment'])) {
82229 $baseComponents['fragment'] = $components['fragment'];
82230 }
82231
82232 return $this->generate($baseComponents);
82233 }
82234
82235
82236
82237
82238
82239
82240
82241
82242
82243
82244
82245 public static function combineRelativePathWithBasePath($relativePath, $basePath)
82246 {
82247 $relativePath = self::normalizePath($relativePath);
82248 if ($relativePath == '') {
82249 return $basePath;
82250 }
82251 if ($relativePath[0] == '/') {
82252 return $relativePath;
82253 }
82254
82255 $basePathSegments = explode('/', $basePath);
82256
82257 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
82258 $numLevelUp = strlen($match[0]) /3 + 1;
82259 if ($numLevelUp >= count($basePathSegments)) {
82260 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
82261 }
82262
82263 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
82264 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
82265
82266 return implode('/', $basePathSegments) . '/' . $path;
82267 }
82268
82269
82270
82271
82272
82273
82274
82275
82276 private static function normalizePath($path)
82277 {
82278 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
82279 $path = preg_replace('|//|', '/', $path);
82280
82281 return $path;
82282 }
82283
82284
82285
82286
82287
82288
82289 public function isValid($uri)
82290 {
82291 $components = $this->parse($uri);
82292
82293 return !empty($components);
82294 }
82295 }
82296 <?php
82297
82298
82299
82300
82301
82302
82303
82304
82305 namespace JsonSchema\Uri;
82306
82307 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
82308 use JsonSchema\Exception\JsonDecodingException;
82309 use JsonSchema\Exception\ResourceNotFoundException;
82310 use JsonSchema\Uri\Retrievers\FileGetContents;
82311 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
82312 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
82313 use JsonSchema\Validator;
82314
82315
82316
82317
82318
82319
82320 class UriRetriever implements BaseUriRetrieverInterface
82321 {
82322
82323
82324
82325 protected $translationMap = array(
82326
82327  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
82328 );
82329
82330
82331
82332
82333 protected $allowedInvalidContentTypeEndpoints = array(
82334 'http://json-schema.org/',
82335 'https://json-schema.org/'
82336 );
82337
82338
82339
82340
82341 protected $uriRetriever = null;
82342
82343
82344
82345
82346
82347
82348 private $schemaCache = array();
82349
82350
82351
82352
82353
82354
82355 public function addInvalidContentTypeEndpoint($endpoint)
82356 {
82357 $this->allowedInvalidContentTypeEndpoints[] = $endpoint;
82358 }
82359
82360
82361
82362
82363
82364
82365
82366
82367
82368 public function confirmMediaType($uriRetriever, $uri)
82369 {
82370 $contentType = $uriRetriever->getContentType();
82371
82372 if (is_null($contentType)) {
82373
82374  return;
82375 }
82376
82377 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
82378 return;
82379 }
82380
82381 foreach ($this->allowedInvalidContentTypeEndpoints as $endpoint) {
82382 if (strpos($uri, $endpoint) === 0) {
82383 return true;
82384 }
82385 }
82386
82387 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
82388 }
82389
82390
82391
82392
82393
82394
82395
82396
82397
82398 public function getUriRetriever()
82399 {
82400 if (is_null($this->uriRetriever)) {
82401 $this->setUriRetriever(new FileGetContents());
82402 }
82403
82404 return $this->uriRetriever;
82405 }
82406
82407
82408
82409
82410
82411
82412
82413
82414
82415
82416
82417
82418
82419
82420
82421 public function resolvePointer($jsonSchema, $uri)
82422 {
82423 $resolver = new UriResolver();
82424 $parsed = $resolver->parse($uri);
82425 if (empty($parsed['fragment'])) {
82426 return $jsonSchema;
82427 }
82428
82429 $path = explode('/', $parsed['fragment']);
82430 while ($path) {
82431 $pathElement = array_shift($path);
82432 if (!empty($pathElement)) {
82433 $pathElement = str_replace('~1', '/', $pathElement);
82434 $pathElement = str_replace('~0', '~', $pathElement);
82435 if (!empty($jsonSchema->$pathElement)) {
82436 $jsonSchema = $jsonSchema->$pathElement;
82437 } else {
82438 throw new ResourceNotFoundException(
82439 'Fragment "' . $parsed['fragment'] . '" not found'
82440 . ' in ' . $uri
82441 );
82442 }
82443
82444 if (!is_object($jsonSchema)) {
82445 throw new ResourceNotFoundException(
82446 'Fragment part "' . $pathElement . '" is no object '
82447 . ' in ' . $uri
82448 );
82449 }
82450 }
82451 }
82452
82453 return $jsonSchema;
82454 }
82455
82456
82457
82458
82459 public function retrieve($uri, $baseUri = null, $translate = true)
82460 {
82461 $resolver = new UriResolver();
82462 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
82463
82464
82465  $arParts = $resolver->parse($resolvedUri);
82466 if (isset($arParts['fragment'])) {
82467 unset($arParts['fragment']);
82468 $fetchUri = $resolver->generate($arParts);
82469 }
82470
82471
82472  if ($translate) {
82473 $fetchUri = $this->translate($fetchUri);
82474 }
82475
82476 $jsonSchema = $this->loadSchema($fetchUri);
82477
82478
82479  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
82480
82481 if ($jsonSchema instanceof \stdClass) {
82482 $jsonSchema->id = $resolvedUri;
82483 }
82484
82485 return $jsonSchema;
82486 }
82487
82488
82489
82490
82491
82492
82493
82494
82495
82496 protected function loadSchema($fetchUri)
82497 {
82498 if (isset($this->schemaCache[$fetchUri])) {
82499 return $this->schemaCache[$fetchUri];
82500 }
82501
82502 $uriRetriever = $this->getUriRetriever();
82503 $contents = $this->uriRetriever->retrieve($fetchUri);
82504 $this->confirmMediaType($uriRetriever, $fetchUri);
82505 $jsonSchema = json_decode($contents);
82506
82507 if (JSON_ERROR_NONE < $error = json_last_error()) {
82508 throw new JsonDecodingException($error);
82509 }
82510
82511 $this->schemaCache[$fetchUri] = $jsonSchema;
82512
82513 return $jsonSchema;
82514 }
82515
82516
82517
82518
82519
82520
82521
82522
82523 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
82524 {
82525 $this->uriRetriever = $uriRetriever;
82526
82527 return $this;
82528 }
82529
82530
82531
82532
82533
82534
82535
82536
82537 public function parse($uri)
82538 {
82539 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
82540
82541 $components = array();
82542 if (5 < count($match)) {
82543 $components = array(
82544 'scheme' => $match[2],
82545 'authority' => $match[4],
82546 'path' => $match[5]
82547 );
82548 }
82549
82550 if (7 < count($match)) {
82551 $components['query'] = $match[7];
82552 }
82553
82554 if (9 < count($match)) {
82555 $components['fragment'] = $match[9];
82556 }
82557
82558 return $components;
82559 }
82560
82561
82562
82563
82564
82565
82566
82567
82568 public function generate(array $components)
82569 {
82570 $uri = $components['scheme'] . '://'
82571 . $components['authority']
82572 . $components['path'];
82573
82574 if (array_key_exists('query', $components)) {
82575 $uri .= $components['query'];
82576 }
82577
82578 if (array_key_exists('fragment', $components)) {
82579 $uri .= $components['fragment'];
82580 }
82581
82582 return $uri;
82583 }
82584
82585
82586
82587
82588
82589
82590
82591
82592
82593 public function resolve($uri, $baseUri = null)
82594 {
82595 $components = $this->parse($uri);
82596 $path = $components['path'];
82597
82598 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
82599 return $uri;
82600 }
82601
82602 $baseComponents = $this->parse($baseUri);
82603 $basePath = $baseComponents['path'];
82604
82605 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
82606
82607 return $this->generate($baseComponents);
82608 }
82609
82610
82611
82612
82613
82614
82615 public function isValid($uri)
82616 {
82617 $components = $this->parse($uri);
82618
82619 return !empty($components);
82620 }
82621
82622
82623
82624
82625 public function setTranslation($from, $to)
82626 {
82627 $this->translationMap[$from] = $to;
82628 }
82629
82630
82631
82632
82633 public function translate($uri)
82634 {
82635 foreach ($this->translationMap as $from => $to) {
82636 $uri = preg_replace($from, $to, $uri);
82637 }
82638
82639
82640  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
82641
82642 return $uri;
82643 }
82644 }
82645 <?php
82646
82647
82648
82649
82650
82651
82652
82653
82654 namespace JsonSchema;
82655
82656
82657
82658
82659 interface UriResolverInterface
82660 {
82661
82662
82663
82664
82665
82666
82667
82668
82669 public function resolve($uri, $baseUri = null);
82670 }
82671 <?php
82672
82673
82674
82675
82676
82677
82678
82679
82680 namespace JsonSchema;
82681
82682
82683
82684
82685 interface UriRetrieverInterface
82686 {
82687
82688
82689
82690
82691
82692
82693
82694
82695 public function retrieve($uri, $baseUri = null);
82696 }
82697 <?php
82698
82699
82700
82701
82702
82703
82704
82705
82706 namespace JsonSchema;
82707
82708 use JsonSchema\Constraints\BaseConstraint;
82709 use JsonSchema\Constraints\Constraint;
82710
82711
82712
82713
82714
82715
82716
82717
82718
82719 class Validator extends BaseConstraint
82720 {
82721 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
82722
82723 const ERROR_NONE = 0x00000000;
82724 const ERROR_ALL = 0xFFFFFFFF;
82725 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
82726 const ERROR_SCHEMA_VALIDATION = 0x00000002;
82727
82728
82729
82730
82731
82732
82733
82734
82735 public function validate(&$value, $schema = null, $checkMode = null)
82736 {
82737
82738  if (is_array($schema)) {
82739 $schema = self::arrayToObjectRecursive($schema);
82740 }
82741
82742
82743  $initialCheckMode = $this->factory->getConfig();
82744 if ($checkMode !== null) {
82745 $this->factory->setConfig($checkMode);
82746 }
82747
82748
82749  if (is_object($schema) && property_exists($schema, 'id')) {
82750 $schemaURI = $schema->id;
82751 } else {
82752 $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
82753 }
82754 $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
82755
82756 $validator = $this->factory->createInstanceFor('schema');
82757 $validator->check(
82758 $value,
82759 $this->factory->getSchemaStorage()->getSchema($schemaURI)
82760 );
82761
82762 $this->factory->setConfig($initialCheckMode);
82763
82764 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
82765
82766 return $validator->getErrorMask();
82767 }
82768
82769
82770
82771
82772 public function check($value, $schema)
82773 {
82774 return $this->validate($value, $schema);
82775 }
82776
82777
82778
82779
82780 public function coerce(&$value, $schema)
82781 {
82782 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
82783 }
82784 }
82785 Copyright (C) 2015 Composer
82786
82787 Permission is hereby granted, free of charge, to any person obtaining a copy of
82788 this software and associated documentation files (the "Software"), to deal in
82789 the Software without restriction, including without limitation the rights to
82790 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
82791 of the Software, and to permit persons to whom the Software is furnished to do
82792 so, subject to the following conditions:
82793
82794 The above copyright notice and this permission notice shall be included in all
82795 copies or substantial portions of the Software.
82796
82797 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82798 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82799 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
82800 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
82801 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82802 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
82803 SOFTWARE.
82804 <?php
82805
82806
82807
82808
82809
82810
82811
82812
82813
82814
82815 namespace Composer\Spdx;
82816
82817 class SpdxLicenses
82818 {
82819
82820 const LICENSES_FILE = 'spdx-licenses.json';
82821
82822
82823 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
82824
82825
82826
82827
82828
82829
82830
82831
82832
82833
82834
82835
82836
82837
82838 private $licenses;
82839
82840
82841
82842
82843 private $licensesExpression;
82844
82845
82846
82847
82848
82849
82850
82851
82852
82853
82854
82855
82856
82857
82858 private $exceptions;
82859
82860
82861
82862
82863 private $exceptionsExpression;
82864
82865 public function __construct()
82866 {
82867 $this->loadLicenses();
82868 $this->loadExceptions();
82869 }
82870
82871
82872
82873
82874
82875
82876
82877
82878
82879
82880
82881
82882
82883 public function getLicenseByIdentifier($identifier)
82884 {
82885 $key = strtolower($identifier);
82886
82887 if (!isset($this->licenses[$key])) {
82888 return;
82889 }
82890
82891 list($identifier, $name, $isOsiApproved, $isDeprecatedLicenseId) = $this->licenses[$key];
82892
82893 return array(
82894 $name,
82895 $isOsiApproved,
82896 'https://spdx.org/licenses/' . $identifier . '.html#licenseText',
82897 $isDeprecatedLicenseId,
82898 );
82899 }
82900
82901
82902
82903
82904
82905
82906 public function getLicenses()
82907 {
82908 return $this->licenses;
82909 }
82910
82911
82912
82913
82914
82915
82916
82917
82918
82919
82920
82921
82922
82923 public function getExceptionByIdentifier($identifier)
82924 {
82925 $key = strtolower($identifier);
82926
82927 if (!isset($this->exceptions[$key])) {
82928 return;
82929 }
82930
82931 list($identifier, $name) = $this->exceptions[$key];
82932
82933 return array(
82934 $name,
82935 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText',
82936 );
82937 }
82938
82939
82940
82941
82942
82943
82944
82945
82946 public function getIdentifierByName($name)
82947 {
82948 foreach ($this->licenses as $licenseData) {
82949 if ($licenseData[1] === $name) {
82950 return $licenseData[0];
82951 }
82952 }
82953
82954 foreach ($this->exceptions as $licenseData) {
82955 if ($licenseData[1] === $name) {
82956 return $licenseData[0];
82957 }
82958 }
82959 }
82960
82961
82962
82963
82964
82965
82966
82967
82968 public function isOsiApprovedByIdentifier($identifier)
82969 {
82970 return $this->licenses[strtolower($identifier)][2];
82971 }
82972
82973
82974
82975
82976
82977
82978
82979
82980 public function isDeprecatedByIdentifier($identifier)
82981 {
82982 return $this->licenses[strtolower($identifier)][3];
82983 }
82984
82985
82986
82987
82988
82989
82990
82991
82992 public function validate($license)
82993 {
82994 if (is_array($license)) {
82995 $count = count($license);
82996 if ($count !== count(array_filter($license, 'is_string'))) {
82997 throw new \InvalidArgumentException('Array of strings expected.');
82998 }
82999 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
83000 }
83001
83002 if (!is_string($license)) {
83003 throw new \InvalidArgumentException(sprintf(
83004 'Array or String expected, %s given.',
83005 gettype($license)
83006 ));
83007 }
83008
83009 return $this->isValidLicenseString($license);
83010 }
83011
83012
83013
83014
83015 public static function getResourcesDir()
83016 {
83017 return dirname(__DIR__) . '/res';
83018 }
83019
83020 private function loadLicenses()
83021 {
83022 if (null !== $this->licenses) {
83023 return;
83024 }
83025
83026 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
83027 $this->licenses = array();
83028
83029 foreach (json_decode($json, true) as $identifier => $license) {
83030 $this->licenses[strtolower($identifier)] = array($identifier, $license[0], $license[1], $license[2]);
83031 }
83032 }
83033
83034 private function loadExceptions()
83035 {
83036 if (null !== $this->exceptions) {
83037 return;
83038 }
83039
83040 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
83041 $this->exceptions = array();
83042
83043 foreach (json_decode($json, true) as $identifier => $exception) {
83044 $this->exceptions[strtolower($identifier)] = array($identifier, $exception[0]);
83045 }
83046 }
83047
83048
83049
83050
83051 private function getLicensesExpression()
83052 {
83053 if (null === $this->licensesExpression) {
83054 $licenses = array_map('preg_quote', array_keys($this->licenses));
83055 rsort($licenses);
83056 $licenses = implode('|', $licenses);
83057 $this->licensesExpression = $licenses;
83058 }
83059
83060 return $this->licensesExpression;
83061 }
83062
83063
83064
83065
83066 private function getExceptionsExpression()
83067 {
83068 if (null === $this->exceptionsExpression) {
83069 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
83070 rsort($exceptions);
83071 $exceptions = implode('|', $exceptions);
83072 $this->exceptionsExpression = $exceptions;
83073 }
83074
83075 return $this->exceptionsExpression;
83076 }
83077
83078
83079
83080
83081
83082
83083
83084
83085 private function isValidLicenseString($license)
83086 {
83087 if (isset($this->licenses[strtolower($license)])) {
83088 return true;
83089 }
83090
83091 $licenses = $this->getLicensesExpression();
83092 $exceptions = $this->getExceptionsExpression();
83093
83094 $regex = <<<REGEX
83095 {
83096 (?(DEFINE)
83097     # idstring: 1*( ALPHA / DIGIT / - / . )
83098     (?<idstring>[\pL\pN.-]{1,})
83099
83100     # license-id: taken from list
83101     (?<licenseid>${licenses})
83102
83103     # license-exception-id: taken from list
83104     (?<licenseexceptionid>${exceptions})
83105
83106     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
83107     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
83108
83109     # simple-expresssion: license-id / license-id+ / license-ref
83110     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
83111
83112     # compound-expression: 1*(
83113     #   simple-expression /
83114     #   simple-expression WITH license-exception-id /
83115     #   compound-expression AND compound-expression /
83116     #   compound-expression OR compound-expression
83117     # ) / ( compound-expression ) )
83118     (?<compound_head>
83119         (?&simple_expression) ( \s+ WITH \s+ (?&licenseexceptionid))?
83120             | \( \s* (?&compound_expression) \s* \)
83121     )
83122     (?<compound_expression>
83123         (?&compound_head) (?: \s+ (?:AND|OR) \s+ (?&compound_expression))?
83124     )
83125
83126     # license-expression: 1*1(simple-expression / compound-expression)
83127     (?<license_expression>(?&compound_expression) | (?&simple_expression))
83128 ) # end of define
83129
83130 ^(NONE | NOASSERTION | (?&license_expression))$
83131 }xi
83132 REGEX;
83133
83134 $match = preg_match($regex, $license);
83135
83136 if (0 === $match) {
83137 return false;
83138 }
83139
83140 if (false === $match) {
83141 throw new \RuntimeException('Regex failed to compile/run.');
83142 }
83143
83144 return true;
83145 }
83146 }
83147 Copyright (C) 2015 Composer
83148
83149 Permission is hereby granted, free of charge, to any person obtaining a copy of
83150 this software and associated documentation files (the "Software"), to deal in
83151 the Software without restriction, including without limitation the rights to
83152 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
83153 of the Software, and to permit persons to whom the Software is furnished to do
83154 so, subject to the following conditions:
83155
83156 The above copyright notice and this permission notice shall be included in all
83157 copies or substantial portions of the Software.
83158
83159 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
83160 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
83161 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
83162 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
83163 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
83164 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
83165 SOFTWARE.
83166 <?php
83167
83168
83169
83170
83171
83172
83173
83174
83175
83176
83177 namespace Composer\Semver;
83178
83179 use Composer\Semver\Constraint\Constraint;
83180
83181 class Comparator
83182 {
83183
83184
83185
83186
83187
83188
83189
83190
83191 public static function greaterThan($version1, $version2)
83192 {
83193 return self::compare($version1, '>', $version2);
83194 }
83195
83196
83197
83198
83199
83200
83201
83202
83203
83204 public static function greaterThanOrEqualTo($version1, $version2)
83205 {
83206 return self::compare($version1, '>=', $version2);
83207 }
83208
83209
83210
83211
83212
83213
83214
83215
83216
83217 public static function lessThan($version1, $version2)
83218 {
83219 return self::compare($version1, '<', $version2);
83220 }
83221
83222
83223
83224
83225
83226
83227
83228
83229
83230 public static function lessThanOrEqualTo($version1, $version2)
83231 {
83232 return self::compare($version1, '<=', $version2);
83233 }
83234
83235
83236
83237
83238
83239
83240
83241
83242
83243 public static function equalTo($version1, $version2)
83244 {
83245 return self::compare($version1, '==', $version2);
83246 }
83247
83248
83249
83250
83251
83252
83253
83254
83255
83256 public static function notEqualTo($version1, $version2)
83257 {
83258 return self::compare($version1, '!=', $version2);
83259 }
83260
83261
83262
83263
83264
83265
83266
83267
83268
83269
83270 public static function compare($version1, $operator, $version2)
83271 {
83272 $constraint = new Constraint($operator, $version2);
83273
83274 return $constraint->matches(new Constraint('==', $version1));
83275 }
83276 }
83277 <?php
83278
83279
83280
83281
83282
83283
83284
83285
83286
83287
83288 namespace Composer\Semver\Constraint;
83289
83290 trigger_error('The ' . __NAMESPACE__ . '\AbstractConstraint abstract class is deprecated, there is no replacement for it, it will be removed in the next major version.', E_USER_DEPRECATED);
83291
83292
83293
83294
83295 abstract class AbstractConstraint implements ConstraintInterface
83296 {
83297
83298 protected $prettyString;
83299
83300
83301
83302
83303
83304
83305 public function matches(ConstraintInterface $provider)
83306 {
83307 if ($provider instanceof $this) {
83308
83309  return $this->matchSpecific($provider);
83310 }
83311
83312
83313  return $provider->matches($this);
83314 }
83315
83316
83317
83318
83319 public function setPrettyString($prettyString)
83320 {
83321 $this->prettyString = $prettyString;
83322 }
83323
83324
83325
83326
83327 public function getPrettyString()
83328 {
83329 if ($this->prettyString) {
83330 return $this->prettyString;
83331 }
83332
83333 return $this->__toString();
83334 }
83335
83336
83337  
83338  
83339 }
83340 <?php
83341
83342
83343
83344
83345
83346
83347
83348
83349
83350
83351 namespace Composer\Semver\Constraint;
83352
83353
83354
83355
83356 class Constraint implements ConstraintInterface
83357 {
83358
83359 const OP_EQ = 0;
83360 const OP_LT = 1;
83361 const OP_LE = 2;
83362 const OP_GT = 3;
83363 const OP_GE = 4;
83364 const OP_NE = 5;
83365
83366
83367
83368
83369
83370
83371 private static $transOpStr = array(
83372 '=' => self::OP_EQ,
83373 '==' => self::OP_EQ,
83374 '<' => self::OP_LT,
83375 '<=' => self::OP_LE,
83376 '>' => self::OP_GT,
83377 '>=' => self::OP_GE,
83378 '<>' => self::OP_NE,
83379 '!=' => self::OP_NE,
83380 );
83381
83382
83383
83384
83385
83386
83387 private static $transOpInt = array(
83388 self::OP_EQ => '==',
83389 self::OP_LT => '<',
83390 self::OP_LE => '<=',
83391 self::OP_GT => '>',
83392 self::OP_GE => '>=',
83393 self::OP_NE => '!=',
83394 );
83395
83396
83397 protected $operator;
83398
83399
83400 protected $version;
83401
83402
83403 protected $prettyString;
83404
83405
83406
83407
83408
83409
83410 public function matches(ConstraintInterface $provider)
83411 {
83412 if ($provider instanceof $this) {
83413 return $this->matchSpecific($provider);
83414 }
83415
83416
83417  return $provider->matches($this);
83418 }
83419
83420
83421
83422
83423 public function setPrettyString($prettyString)
83424 {
83425 $this->prettyString = $prettyString;
83426 }
83427
83428
83429
83430
83431 public function getPrettyString()
83432 {
83433 if ($this->prettyString) {
83434 return $this->prettyString;
83435 }
83436
83437 return $this->__toString();
83438 }
83439
83440
83441
83442
83443
83444
83445 public static function getSupportedOperators()
83446 {
83447 return array_keys(self::$transOpStr);
83448 }
83449
83450
83451
83452
83453
83454
83455
83456
83457
83458 public function __construct($operator, $version)
83459 {
83460 if (!isset(self::$transOpStr[$operator])) {
83461 throw new \InvalidArgumentException(sprintf(
83462 'Invalid operator "%s" given, expected one of: %s',
83463 $operator,
83464 implode(', ', self::getSupportedOperators())
83465 ));
83466 }
83467
83468 $this->operator = self::$transOpStr[$operator];
83469 $this->version = $version;
83470 }
83471
83472
83473
83474
83475
83476
83477
83478
83479
83480
83481
83482 public function versionCompare($a, $b, $operator, $compareBranches = false)
83483 {
83484 if (!isset(self::$transOpStr[$operator])) {
83485 throw new \InvalidArgumentException(sprintf(
83486 'Invalid operator "%s" given, expected one of: %s',
83487 $operator,
83488 implode(', ', self::getSupportedOperators())
83489 ));
83490 }
83491
83492 $aIsBranch = 'dev-' === substr($a, 0, 4);
83493 $bIsBranch = 'dev-' === substr($b, 0, 4);
83494
83495 if ($aIsBranch && $bIsBranch) {
83496 return $operator === '==' && $a === $b;
83497 }
83498
83499
83500  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
83501 return false;
83502 }
83503
83504 return version_compare($a, $b, $operator);
83505 }
83506
83507
83508
83509
83510
83511
83512
83513 public function matchSpecific(Constraint $provider, $compareBranches = false)
83514 {
83515 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
83516 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
83517
83518 $isEqualOp = self::OP_EQ === $this->operator;
83519 $isNonEqualOp = self::OP_NE === $this->operator;
83520 $isProviderEqualOp = self::OP_EQ === $provider->operator;
83521 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
83522
83523
83524  
83525  if ($isNonEqualOp || $isProviderNonEqualOp) {
83526 return (!$isEqualOp && !$isProviderEqualOp)
83527 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
83528 }
83529
83530
83531  
83532  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
83533 return true;
83534 }
83535
83536 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
83537
83538  
83539  return !($provider->version === $this->version
83540 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
83541 && self::$transOpInt[$this->operator] !== $noEqualOp);
83542 }
83543
83544 return false;
83545 }
83546
83547
83548
83549
83550 public function __toString()
83551 {
83552 return self::$transOpInt[$this->operator] . ' ' . $this->version;
83553 }
83554 }
83555 <?php
83556
83557
83558
83559
83560
83561
83562
83563
83564
83565
83566 namespace Composer\Semver\Constraint;
83567
83568 interface ConstraintInterface
83569 {
83570
83571
83572
83573
83574
83575 public function matches(ConstraintInterface $provider);
83576
83577
83578
83579
83580 public function getPrettyString();
83581
83582
83583
83584
83585 public function __toString();
83586 }
83587 <?php
83588
83589
83590
83591
83592
83593
83594
83595
83596
83597
83598 namespace Composer\Semver\Constraint;
83599
83600
83601
83602
83603 class EmptyConstraint implements ConstraintInterface
83604 {
83605
83606 protected $prettyString;
83607
83608
83609
83610
83611
83612
83613 public function matches(ConstraintInterface $provider)
83614 {
83615 return true;
83616 }
83617
83618
83619
83620
83621 public function setPrettyString($prettyString)
83622 {
83623 $this->prettyString = $prettyString;
83624 }
83625
83626
83627
83628
83629 public function getPrettyString()
83630 {
83631 if ($this->prettyString) {
83632 return $this->prettyString;
83633 }
83634
83635 return (string) $this;
83636 }
83637
83638
83639
83640
83641 public function __toString()
83642 {
83643 return '[]';
83644 }
83645 }
83646 <?php
83647
83648
83649
83650
83651
83652
83653
83654
83655
83656
83657 namespace Composer\Semver\Constraint;
83658
83659
83660
83661
83662 class MultiConstraint implements ConstraintInterface
83663 {
83664
83665 protected $constraints;
83666
83667
83668 protected $prettyString;
83669
83670
83671 protected $conjunctive;
83672
83673
83674
83675
83676
83677 public function __construct(array $constraints, $conjunctive = true)
83678 {
83679 $this->constraints = $constraints;
83680 $this->conjunctive = $conjunctive;
83681 }
83682
83683
83684
83685
83686 public function getConstraints()
83687 {
83688 return $this->constraints;
83689 }
83690
83691
83692
83693
83694 public function isConjunctive()
83695 {
83696 return $this->conjunctive;
83697 }
83698
83699
83700
83701
83702 public function isDisjunctive()
83703 {
83704 return !$this->conjunctive;
83705 }
83706
83707
83708
83709
83710
83711
83712 public function matches(ConstraintInterface $provider)
83713 {
83714 if (false === $this->conjunctive) {
83715 foreach ($this->constraints as $constraint) {
83716 if ($constraint->matches($provider)) {
83717 return true;
83718 }
83719 }
83720
83721 return false;
83722 }
83723
83724 foreach ($this->constraints as $constraint) {
83725 if (!$constraint->matches($provider)) {
83726 return false;
83727 }
83728 }
83729
83730 return true;
83731 }
83732
83733
83734
83735
83736 public function setPrettyString($prettyString)
83737 {
83738 $this->prettyString = $prettyString;
83739 }
83740
83741
83742
83743
83744 public function getPrettyString()
83745 {
83746 if ($this->prettyString) {
83747 return $this->prettyString;
83748 }
83749
83750 return (string) $this;
83751 }
83752
83753
83754
83755
83756 public function __toString()
83757 {
83758 $constraints = array();
83759 foreach ($this->constraints as $constraint) {
83760 $constraints[] = (string) $constraint;
83761 }
83762
83763 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
83764 }
83765 }
83766 <?php
83767
83768
83769
83770
83771
83772
83773
83774
83775
83776
83777 namespace Composer\Semver;
83778
83779 use Composer\Semver\Constraint\Constraint;
83780
83781 class Semver
83782 {
83783 const SORT_ASC = 1;
83784 const SORT_DESC = -1;
83785
83786
83787 private static $versionParser;
83788
83789
83790
83791
83792
83793
83794
83795
83796
83797 public static function satisfies($version, $constraints)
83798 {
83799 if (null === self::$versionParser) {
83800 self::$versionParser = new VersionParser();
83801 }
83802
83803 $versionParser = self::$versionParser;
83804 $provider = new Constraint('==', $versionParser->normalize($version));
83805 $parsedConstraints = $versionParser->parseConstraints($constraints);
83806
83807 return $parsedConstraints->matches($provider);
83808 }
83809
83810
83811
83812
83813
83814
83815
83816
83817
83818 public static function satisfiedBy(array $versions, $constraints)
83819 {
83820 $versions = array_filter($versions, function ($version) use ($constraints) {
83821 return Semver::satisfies($version, $constraints);
83822 });
83823
83824 return array_values($versions);
83825 }
83826
83827
83828
83829
83830
83831
83832
83833
83834 public static function sort(array $versions)
83835 {
83836 return self::usort($versions, self::SORT_ASC);
83837 }
83838
83839
83840
83841
83842
83843
83844
83845
83846 public static function rsort(array $versions)
83847 {
83848 return self::usort($versions, self::SORT_DESC);
83849 }
83850
83851
83852
83853
83854
83855
83856
83857 private static function usort(array $versions, $direction)
83858 {
83859 if (null === self::$versionParser) {
83860 self::$versionParser = new VersionParser();
83861 }
83862
83863 $versionParser = self::$versionParser;
83864 $normalized = array();
83865
83866
83867  
83868  foreach ($versions as $key => $version) {
83869 $normalized[] = array($versionParser->normalize($version), $key);
83870 }
83871
83872 usort($normalized, function (array $left, array $right) use ($direction) {
83873 if ($left[0] === $right[0]) {
83874 return 0;
83875 }
83876
83877 if (Comparator::lessThan($left[0], $right[0])) {
83878 return -$direction;
83879 }
83880
83881 return $direction;
83882 });
83883
83884
83885  $sorted = array();
83886 foreach ($normalized as $item) {
83887 $sorted[] = $versions[$item[1]];
83888 }
83889
83890 return $sorted;
83891 }
83892 }
83893 <?php
83894
83895
83896
83897
83898
83899
83900
83901
83902
83903
83904 namespace Composer\Semver;
83905
83906 use Composer\Semver\Constraint\ConstraintInterface;
83907 use Composer\Semver\Constraint\EmptyConstraint;
83908 use Composer\Semver\Constraint\MultiConstraint;
83909 use Composer\Semver\Constraint\Constraint;
83910
83911
83912
83913
83914
83915
83916 class VersionParser
83917 {
83918
83919
83920
83921
83922
83923
83924
83925
83926
83927
83928
83929
83930
83931 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
83932
83933
83934 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
83935
83936
83937
83938
83939
83940
83941
83942
83943 public static function parseStability($version)
83944 {
83945 $version = preg_replace('{#.+$}i', '', $version);
83946
83947 if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) {
83948 return 'dev';
83949 }
83950
83951 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
83952
83953 if (!empty($match[3])) {
83954 return 'dev';
83955 }
83956
83957 if (!empty($match[1])) {
83958 if ('beta' === $match[1] || 'b' === $match[1]) {
83959 return 'beta';
83960 }
83961 if ('alpha' === $match[1] || 'a' === $match[1]) {
83962 return 'alpha';
83963 }
83964 if ('rc' === $match[1]) {
83965 return 'RC';
83966 }
83967 }
83968
83969 return 'stable';
83970 }
83971
83972
83973
83974
83975
83976
83977 public static function normalizeStability($stability)
83978 {
83979 $stability = strtolower($stability);
83980
83981 return $stability === 'rc' ? 'RC' : $stability;
83982 }
83983
83984
83985
83986
83987
83988
83989
83990
83991
83992
83993
83994 public function normalize($version, $fullVersion = null)
83995 {
83996 $version = trim($version);
83997 if (null === $fullVersion) {
83998 $fullVersion = $version;
83999 }
84000
84001
84002  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
84003
84004  $this->normalize($match[2]);
84005
84006 $version = $match[1];
84007 }
84008
84009
84010  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
84011 return '9999999-dev';
84012 }
84013
84014
84015  if (stripos($version, 'dev-') === 0) {
84016 return 'dev-' . substr($version, 4);
84017 }
84018
84019
84020  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
84021 $version = $match[1];
84022 }
84023
84024
84025  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
84026 $version = $matches[1]
84027 . (!empty($matches[2]) ? $matches[2] : '.0')
84028 . (!empty($matches[3]) ? $matches[3] : '.0')
84029 . (!empty($matches[4]) ? $matches[4] : '.0');
84030 $index = 5;
84031
84032  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
84033 $version = preg_replace('{\D}', '.', $matches[1]);
84034 $index = 2;
84035 }
84036
84037
84038  if (isset($index)) {
84039 if (!empty($matches[$index])) {
84040 if ('stable' === $matches[$index]) {
84041 return $version;
84042 }
84043 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
84044 }
84045
84046 if (!empty($matches[$index + 2])) {
84047 $version .= '-dev';
84048 }
84049
84050 return $version;
84051 }
84052
84053
84054  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
84055 try {
84056 return $this->normalizeBranch($match[1]);
84057 } catch (\Exception $e) {
84058 }
84059 }
84060
84061 $extraMessage = '';
84062 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
84063 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
84064 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
84065 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
84066 }
84067
84068 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
84069 }
84070
84071
84072
84073
84074
84075
84076
84077
84078 public function parseNumericAliasPrefix($branch)
84079 {
84080 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
84081 return $matches['version'] . '.';
84082 }
84083
84084 return false;
84085 }
84086
84087
84088
84089
84090
84091
84092
84093
84094 public function normalizeBranch($name)
84095 {
84096 $name = trim($name);
84097
84098 if (in_array($name, array('master', 'trunk', 'default'))) {
84099 return $this->normalize($name);
84100 }
84101
84102 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
84103 $version = '';
84104 for ($i = 1; $i < 5; ++$i) {
84105 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
84106 }
84107
84108 return str_replace('x', '9999999', $version) . '-dev';
84109 }
84110
84111 return 'dev-' . $name;
84112 }
84113
84114
84115
84116
84117
84118
84119
84120
84121 public function parseConstraints($constraints)
84122 {
84123 $prettyConstraint = $constraints;
84124
84125 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
84126 $constraints = empty($match[1]) ? '*' : $match[1];
84127 }
84128
84129 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
84130 $constraints = $match[1];
84131 }
84132
84133 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
84134 $orGroups = array();
84135
84136 foreach ($orConstraints as $constraints) {
84137 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
84138 if (count($andConstraints) > 1) {
84139 $constraintObjects = array();
84140 foreach ($andConstraints as $constraint) {
84141 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
84142 $constraintObjects[] = $parsedConstraint;
84143 }
84144 }
84145 } else {
84146 $constraintObjects = $this->parseConstraint($andConstraints[0]);
84147 }
84148
84149 if (1 === count($constraintObjects)) {
84150 $constraint = $constraintObjects[0];
84151 } else {
84152 $constraint = new MultiConstraint($constraintObjects);
84153 }
84154
84155 $orGroups[] = $constraint;
84156 }
84157
84158 if (1 === count($orGroups)) {
84159 $constraint = $orGroups[0];
84160 } elseif (2 === count($orGroups)
84161
84162  
84163  && $orGroups[0] instanceof MultiConstraint
84164 && $orGroups[1] instanceof MultiConstraint
84165 && 2 === count($orGroups[0]->getConstraints())
84166 && 2 === count($orGroups[1]->getConstraints())
84167 && ($a = (string) $orGroups[0])
84168 && strpos($a, '[>=') === 0 && (false !== ($posA = strpos($a, '<', 4)))
84169 && ($b = (string) $orGroups[1])
84170 && strpos($b, '[>=') === 0 && (false !== ($posB = strpos($b, '<', 4)))
84171 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
84172 ) {
84173 $constraint = new MultiConstraint(array(
84174 new Constraint('>=', substr($a, 4, $posA - 5)),
84175 new Constraint('<', substr($b, $posB + 2, -1)),
84176 ));
84177 } else {
84178 $constraint = new MultiConstraint($orGroups, false);
84179 }
84180
84181 $constraint->setPrettyString($prettyConstraint);
84182
84183 return $constraint;
84184 }
84185
84186
84187
84188
84189
84190
84191
84192
84193 private function parseConstraint($constraint)
84194 {
84195 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
84196 $constraint = $match[1];
84197 if ($match[2] !== 'stable') {
84198 $stabilityModifier = $match[2];
84199 }
84200 }
84201
84202 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
84203 return array(new EmptyConstraint());
84204 }
84205
84206 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
84207
84208
84209  
84210  
84211  
84212  
84213  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
84214 if (strpos($constraint, '~>') === 0) {
84215 throw new \UnexpectedValueException(
84216 'Could not parse version constraint ' . $constraint . ': ' .
84217 'Invalid operator "~>", you probably meant to use the "~" operator'
84218 );
84219 }
84220
84221
84222  if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
84223 $position = 4;
84224 } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
84225 $position = 3;
84226 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
84227 $position = 2;
84228 } else {
84229 $position = 1;
84230 }
84231
84232
84233  $stabilitySuffix = '';
84234 if (empty($matches[5]) && empty($matches[7])) {
84235 $stabilitySuffix .= '-dev';
84236 }
84237
84238 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
84239 $lowerBound = new Constraint('>=', $lowVersion);
84240
84241
84242  
84243  $highPosition = max(1, $position - 1);
84244 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
84245 $upperBound = new Constraint('<', $highVersion);
84246
84247 return array(
84248 $lowerBound,
84249 $upperBound,
84250 );
84251 }
84252
84253
84254  
84255  
84256  
84257  
84258  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
84259
84260  if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
84261 $position = 1;
84262 } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
84263 $position = 2;
84264 } else {
84265 $position = 3;
84266 }
84267
84268
84269  $stabilitySuffix = '';
84270 if (empty($matches[5]) && empty($matches[7])) {
84271 $stabilitySuffix .= '-dev';
84272 }
84273
84274 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
84275 $lowerBound = new Constraint('>=', $lowVersion);
84276
84277
84278  
84279  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
84280 $upperBound = new Constraint('<', $highVersion);
84281
84282 return array(
84283 $lowerBound,
84284 $upperBound,
84285 );
84286 }
84287
84288
84289  
84290  
84291  
84292  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
84293 if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
84294 $position = 3;
84295 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
84296 $position = 2;
84297 } else {
84298 $position = 1;
84299 }
84300
84301 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
84302 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
84303
84304 if ($lowVersion === '0.0.0.0-dev') {
84305 return array(new Constraint('<', $highVersion));
84306 }
84307
84308 return array(
84309 new Constraint('>=', $lowVersion),
84310 new Constraint('<', $highVersion),
84311 );
84312 }
84313
84314
84315  
84316  
84317  
84318  
84319  
84320  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
84321
84322  $lowStabilitySuffix = '';
84323 if (empty($matches[6]) && empty($matches[8])) {
84324 $lowStabilitySuffix = '-dev';
84325 }
84326
84327 $lowVersion = $this->normalize($matches['from']);
84328 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
84329
84330 $empty = function ($x) {
84331 return ($x === 0 || $x === '0') ? false : empty($x);
84332 };
84333
84334 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
84335 $highVersion = $this->normalize($matches['to']);
84336 $upperBound = new Constraint('<=', $highVersion);
84337 } else {
84338 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
84339 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
84340 $upperBound = new Constraint('<', $highVersion);
84341 }
84342
84343 return array(
84344 $lowerBound,
84345 $upperBound,
84346 );
84347 }
84348
84349
84350  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
84351 try {
84352 $version = $this->normalize($matches[2]);
84353
84354 if (!empty($stabilityModifier) && self::parseStability($version) === 'stable') {
84355 $version .= '-' . $stabilityModifier;
84356 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
84357 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
84358 if (strpos($matches[2], 'dev-') !== 0) {
84359 $version .= '-dev';
84360 }
84361 }
84362 }
84363
84364 return array(new Constraint($matches[1] ?: '=', $version));
84365 } catch (\Exception $e) {
84366 }
84367 }
84368
84369 $message = 'Could not parse version constraint ' . $constraint;
84370 if (isset($e)) {
84371 $message .= ': ' . $e->getMessage();
84372 }
84373
84374 throw new \UnexpectedValueException($message);
84375 }
84376
84377
84378
84379
84380
84381
84382
84383
84384
84385
84386
84387
84388
84389 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
84390 {
84391 for ($i = 4; $i > 0; --$i) {
84392 if ($i > $position) {
84393 $matches[$i] = $pad;
84394 } elseif ($i === $position && $increment) {
84395 $matches[$i] += $increment;
84396
84397  if ($matches[$i] < 0) {
84398 $matches[$i] = $pad;
84399 --$position;
84400
84401
84402  if ($i === 1) {
84403 return null;
84404 }
84405 }
84406 }
84407 }
84408
84409 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
84410 }
84411
84412
84413
84414
84415
84416
84417
84418
84419 private function expandStability($stability)
84420 {
84421 $stability = strtolower($stability);
84422
84423 switch ($stability) {
84424 case 'a':
84425 return 'alpha';
84426 case 'b':
84427 return 'beta';
84428 case 'p':
84429 case 'pl':
84430 return 'patch';
84431 case 'rc':
84432 return 'RC';
84433 default:
84434 return $stability;
84435 }
84436 }
84437 }
84438 Copyright (C) 2016 Composer
84439
84440 Permission is hereby granted, free of charge, to any person obtaining a copy of
84441 this software and associated documentation files (the "Software"), to deal in
84442 the Software without restriction, including without limitation the rights to
84443 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
84444 of the Software, and to permit persons to whom the Software is furnished to do
84445 so, subject to the following conditions:
84446
84447 The above copyright notice and this permission notice shall be included in all
84448 copies or substantial portions of the Software.
84449
84450 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84451 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84452 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84453 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84454 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84455 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
84456 SOFTWARE.
84457 <?php
84458
84459
84460
84461
84462
84463
84464
84465
84466
84467
84468 namespace Composer\CaBundle;
84469
84470 use Psr\Log\LoggerInterface;
84471 use Symfony\Component\Process\PhpProcess;
84472
84473
84474
84475
84476
84477 class CaBundle
84478 {
84479 private static $caPath;
84480 private static $caFileValidity = array();
84481 private static $useOpensslParse;
84482
84483
84484
84485
84486
84487
84488
84489
84490
84491
84492
84493
84494
84495
84496
84497
84498
84499
84500
84501
84502
84503
84504
84505
84506
84507
84508
84509
84510
84511
84512
84513
84514
84515
84516
84517
84518
84519
84520 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
84521 {
84522 if (self::$caPath !== null) {
84523 return self::$caPath;
84524 }
84525 $caBundlePaths = array();
84526
84527
84528
84529  
84530  $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
84531
84532
84533  
84534  $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
84535
84536 $caBundlePaths[] = ini_get('openssl.cafile');
84537 $caBundlePaths[] = ini_get('openssl.capath');
84538
84539 $otherLocations = array(
84540 '/etc/pki/tls/certs/ca-bundle.crt', 
84541  '/etc/ssl/certs/ca-certificates.crt', 
84542  '/etc/ssl/ca-bundle.pem', 
84543  '/usr/local/share/certs/ca-root-nss.crt', 
84544  '/usr/ssl/certs/ca-bundle.crt', 
84545  '/opt/local/share/curl/curl-ca-bundle.crt', 
84546  '/usr/local/share/curl/curl-ca-bundle.crt', 
84547  '/usr/share/ssl/certs/ca-bundle.crt', 
84548  '/etc/ssl/cert.pem', 
84549  '/usr/local/etc/ssl/cert.pem', 
84550  '/usr/local/etc/openssl/cert.pem', 
84551  '/usr/local/etc/openssl@1.1/cert.pem', 
84552  );
84553
84554 foreach($otherLocations as $location) {
84555 $otherLocations[] = dirname($location);
84556 }
84557
84558 $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
84559
84560 foreach ($caBundlePaths as $caBundle) {
84561 if (self::caFileUsable($caBundle, $logger)) {
84562 return self::$caPath = $caBundle;
84563 }
84564
84565 if (self::caDirUsable($caBundle)) {
84566 return self::$caPath = $caBundle;
84567 }
84568 }
84569
84570 return self::$caPath = static::getBundledCaBundlePath(); 
84571  }
84572
84573
84574
84575
84576
84577
84578
84579
84580 public static function getBundledCaBundlePath()
84581 {
84582 $caBundleFile = __DIR__.'/../res/cacert.pem';
84583
84584
84585  
84586  if (0 === strpos($caBundleFile, 'phar://')) {
84587 file_put_contents(
84588 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
84589 file_get_contents($caBundleFile)
84590 );
84591
84592 register_shutdown_function(function() use ($tempCaBundleFile) {
84593 @unlink($tempCaBundleFile);
84594 });
84595
84596 $caBundleFile = $tempCaBundleFile;
84597 }
84598
84599 return $caBundleFile;
84600 }
84601
84602
84603
84604
84605
84606
84607
84608
84609
84610 public static function validateCaFile($filename, LoggerInterface $logger = null)
84611 {
84612 static $warned = false;
84613
84614 if (isset(self::$caFileValidity[$filename])) {
84615 return self::$caFileValidity[$filename];
84616 }
84617
84618 $contents = file_get_contents($filename);
84619
84620
84621  
84622  if (!static::isOpensslParseSafe()) {
84623 if (!$warned && $logger) {
84624 $logger->warning(sprintf(
84625 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
84626 PHP_VERSION
84627 ));
84628 $warned = true;
84629 }
84630
84631 $isValid = !empty($contents);
84632 } else {
84633 $isValid = (bool) openssl_x509_parse($contents);
84634 }
84635
84636 if ($logger) {
84637 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
84638 }
84639
84640 return self::$caFileValidity[$filename] = $isValid;
84641 }
84642
84643
84644
84645
84646
84647
84648
84649
84650
84651 public static function isOpensslParseSafe()
84652 {
84653 if (null !== self::$useOpensslParse) {
84654 return self::$useOpensslParse;
84655 }
84656
84657 if (PHP_VERSION_ID >= 50600) {
84658 return self::$useOpensslParse = true;
84659 }
84660
84661
84662  
84663  
84664  
84665  if (
84666 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
84667 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
84668 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
84669 ) {
84670
84671  return self::$useOpensslParse = true;
84672 }
84673
84674 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
84675
84676  return self::$useOpensslParse = false;
84677 }
84678
84679 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
84680 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
84681
84682 if (preg_match($regex, PHP_VERSION, $m)) {
84683 return ((int) $m[1]) >= $fixedVersion;
84684 }
84685
84686 return false;
84687 };
84688
84689
84690  if (
84691 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
84692  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
84693  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
84694  ) {
84695 return self::$useOpensslParse = true;
84696 }
84697
84698
84699  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
84700 return self::$useOpensslParse = false;
84701 }
84702
84703
84704  
84705  
84706  
84707  
84708  
84709
84710
84711  
84712  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
84713 $script = <<<'EOT'
84714
84715 error_reporting(-1);
84716 $info = openssl_x509_parse(base64_decode('%s'));
84717 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
84718
84719 EOT;
84720 $script = '<'."?php\n".sprintf($script, $cert);
84721
84722 try {
84723 $process = new PhpProcess($script);
84724 $process->mustRun();
84725 } catch (\Exception $e) {
84726
84727  
84728  return self::$useOpensslParse = false;
84729 }
84730
84731 $output = preg_split('{\r?\n}', trim($process->getOutput()));
84732 $errorOutput = trim($process->getErrorOutput());
84733
84734 if (
84735 count($output) === 3
84736 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
84737 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
84738 && $output[2] === 'int(-1)'
84739 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
84740 ) {
84741
84742  return self::$useOpensslParse = true;
84743 }
84744
84745 return self::$useOpensslParse = false;
84746 }
84747
84748
84749
84750
84751 public static function reset()
84752 {
84753 self::$caFileValidity = array();
84754 self::$caPath = null;
84755 self::$useOpensslParse = null;
84756 }
84757
84758 private static function getEnvVariable($name)
84759 {
84760 if (isset($_SERVER[$name])) {
84761 return (string) $_SERVER[$name];
84762 }
84763
84764 if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
84765 return (string) $value;
84766 }
84767
84768 return false;
84769 }
84770
84771 private static function caFileUsable($certFile, LoggerInterface $logger = null)
84772 {
84773 return $certFile && @is_file($certFile) && @is_readable($certFile) && static::validateCaFile($certFile, $logger);
84774 }
84775
84776 private static function caDirUsable($certDir)
84777 {
84778 return $certDir && @is_dir($certDir) && @is_readable($certDir) && glob($certDir . '/*');
84779 }
84780 }
84781 MIT License
84782
84783 Copyright (c) 2017 Composer
84784
84785 Permission is hereby granted, free of charge, to any person obtaining a copy
84786 of this software and associated documentation files (the "Software"), to deal
84787 in the Software without restriction, including without limitation the rights
84788 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
84789 copies of the Software, and to permit persons to whom the Software is
84790 furnished to do so, subject to the following conditions:
84791
84792 The above copyright notice and this permission notice shall be included in all
84793 copies or substantial portions of the Software.
84794
84795 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84796 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84797 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84798 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84799 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84800 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
84801 SOFTWARE.
84802 <?php
84803
84804
84805
84806
84807
84808
84809
84810
84811
84812
84813 namespace Composer\XdebugHandler;
84814
84815
84816
84817
84818 class PhpConfig
84819 {
84820
84821
84822
84823
84824
84825 public function useOriginal()
84826 {
84827 $this->getDataAndReset();
84828 return array();
84829 }
84830
84831
84832
84833
84834
84835
84836 public function useStandard()
84837 {
84838 if ($data = $this->getDataAndReset()) {
84839 return array('-n', '-c', $data['tmpIni']);
84840 }
84841
84842 return array();
84843 }
84844
84845
84846
84847
84848
84849
84850 public function usePersistent()
84851 {
84852 if ($data = $this->getDataAndReset()) {
84853 Process::setEnv('PHPRC', $data['tmpIni']);
84854 Process::setEnv('PHP_INI_SCAN_DIR', '');
84855 }
84856
84857 return array();
84858 }
84859
84860
84861
84862
84863
84864
84865 private function getDataAndReset()
84866 {
84867 if ($data = XdebugHandler::getRestartSettings()) {
84868 Process::setEnv('PHPRC', $data['phprc']);
84869 Process::setEnv('PHP_INI_SCAN_DIR', $data['scanDir']);
84870 }
84871
84872 return $data;
84873 }
84874 }
84875 <?php
84876
84877
84878
84879
84880
84881
84882
84883
84884
84885
84886 namespace Composer\XdebugHandler;
84887
84888
84889
84890
84891
84892
84893
84894
84895 class Process
84896 {
84897
84898
84899
84900
84901
84902
84903
84904
84905
84906
84907 public static function addColorOption(array $args, $colorOption)
84908 {
84909 if (!$colorOption
84910 || in_array($colorOption, $args)
84911 || !preg_match('/^--([a-z]+$)|(^--[a-z]+=)/', $colorOption, $matches)) {
84912 return $args;
84913 }
84914
84915 if (isset($matches[2])) {
84916
84917  if (false !== ($index = array_search($matches[2].'auto', $args))) {
84918 $args[$index] = $colorOption;
84919 return $args;
84920 } elseif (preg_grep('/^'.$matches[2].'/', $args)) {
84921 return $args;
84922 }
84923 } elseif (in_array('--no-'.$matches[1], $args)) {
84924 return $args;
84925 }
84926
84927
84928  if (false !== getenv('NO_COLOR')) {
84929 return $args;
84930 }
84931
84932 if (false !== ($index = array_search('--', $args))) {
84933
84934  array_splice($args, $index, 0, $colorOption);
84935 } else {
84936 $args[] = $colorOption;
84937 }
84938
84939 return $args;
84940 }
84941
84942
84943
84944
84945
84946
84947
84948
84949
84950
84951
84952
84953
84954 public static function escape($arg, $meta = true, $module = false)
84955 {
84956 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
84957 return "'".str_replace("'", "'\\''", $arg)."'";
84958 }
84959
84960 $quote = strpbrk($arg, " \t") !== false || $arg === '';
84961
84962 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
84963
84964 if ($meta) {
84965 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
84966
84967 if (!$meta) {
84968 $quote = $quote || strpbrk($arg, '^&|<>()') !== false;
84969 } elseif ($module && !$dquotes && $quote) {
84970 $meta = false;
84971 }
84972 }
84973
84974 if ($quote) {
84975 $arg = '"'.preg_replace('/(\\\\*)$/', '$1$1', $arg).'"';
84976 }
84977
84978 if ($meta) {
84979 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
84980 }
84981
84982 return $arg;
84983 }
84984
84985
84986
84987
84988
84989
84990
84991
84992
84993
84994
84995 public static function supportsColor($output)
84996 {
84997 if ('Hyper' === getenv('TERM_PROGRAM')) {
84998 return true;
84999 }
85000
85001 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
85002 return (function_exists('sapi_windows_vt100_support')
85003 && sapi_windows_vt100_support($output))
85004 || false !== getenv('ANSICON')
85005 || 'ON' === getenv('ConEmuANSI')
85006 || 'xterm' === getenv('TERM');
85007 }
85008
85009 if (function_exists('stream_isatty')) {
85010 return stream_isatty($output);
85011 }
85012
85013 if (function_exists('posix_isatty')) {
85014 return posix_isatty($output);
85015 }
85016
85017 $stat = fstat($output);
85018
85019  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
85020 }
85021
85022
85023
85024
85025
85026
85027
85028
85029
85030 public static function setEnv($name, $value = false)
85031 {
85032 $unset = false === $value;
85033
85034 if (!putenv($unset ? $name : $name.'='.$value)) {
85035 return false;
85036 }
85037
85038 if ($unset) {
85039 unset($_SERVER[$name]);
85040 } else {
85041 $_SERVER[$name] = $value;
85042 }
85043
85044
85045  if (false !== stripos((string) ini_get('variables_order'), 'E')) {
85046 if ($unset) {
85047 unset($_ENV[$name]);
85048 } else {
85049 $_ENV[$name] = $value;
85050 }
85051 }
85052
85053 return true;
85054 }
85055 }
85056 <?php
85057
85058
85059
85060
85061
85062
85063
85064
85065
85066
85067 namespace Composer\XdebugHandler;
85068
85069 use Psr\Log\LoggerInterface;
85070 use Psr\Log\LogLevel;
85071
85072
85073
85074
85075
85076 class Status
85077 {
85078 const ENV_RESTART = 'XDEBUG_HANDLER_RESTART';
85079 const CHECK = 'Check';
85080 const ERROR = 'Error';
85081 const INFO = 'Info';
85082 const NORESTART = 'NoRestart';
85083 const RESTART = 'Restart';
85084 const RESTARTING = 'Restarting';
85085 const RESTARTED = 'Restarted';
85086
85087 private $debug;
85088 private $envAllowXdebug;
85089 private $loaded;
85090 private $logger;
85091 private $time;
85092
85093
85094
85095
85096
85097
85098
85099 public function __construct($envAllowXdebug, $debug)
85100 {
85101 $start = getenv(self::ENV_RESTART);
85102 Process::setEnv(self::ENV_RESTART);
85103 $this->time = $start ? round((microtime(true) - $start) * 1000) : 0;
85104
85105 $this->envAllowXdebug = $envAllowXdebug;
85106 $this->debug = $debug && defined('STDERR');
85107 }
85108
85109
85110
85111
85112 public function setLogger(LoggerInterface $logger)
85113 {
85114 $this->logger = $logger;
85115 }
85116
85117
85118
85119
85120
85121
85122
85123 public function report($op, $data)
85124 {
85125 if ($this->logger || $this->debug) {
85126 call_user_func(array($this, 'report'.$op), $data);
85127 }
85128 }
85129
85130
85131
85132
85133
85134
85135
85136 private function output($text, $level = null)
85137 {
85138 if ($this->logger) {
85139 $this->logger->log($level ?: LogLevel::DEBUG, $text);
85140 }
85141
85142 if ($this->debug) {
85143 fwrite(STDERR, sprintf('xdebug-handler[%d] %s', getmypid(), $text.PHP_EOL));
85144 }
85145 }
85146
85147 private function reportCheck($loaded)
85148 {
85149 $this->loaded = $loaded;
85150 $this->output('Checking '.$this->envAllowXdebug);
85151 }
85152
85153 private function reportError($error)
85154 {
85155 $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
85156 }
85157
85158 private function reportInfo($info)
85159 {
85160 $this->output($info);
85161 }
85162
85163 private function reportNoRestart()
85164 {
85165 $this->output($this->getLoadedMessage());
85166
85167 if ($this->loaded) {
85168 $text = sprintf('No restart (%s)', $this->getEnvAllow());
85169 if (!getenv($this->envAllowXdebug)) {
85170 $text .= ' Allowed by application';
85171 }
85172 $this->output($text);
85173 }
85174 }
85175
85176 private function reportRestart()
85177 {
85178 $this->output($this->getLoadedMessage());
85179 Process::setEnv(self::ENV_RESTART, (string) microtime(true));
85180 }
85181
85182 private function reportRestarted()
85183 {
85184 $loaded = $this->getLoadedMessage();
85185 $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded);
85186 $level = $this->loaded ? LogLevel::WARNING : null;
85187 $this->output($text, $level);
85188 }
85189
85190 private function reportRestarting($command)
85191 {
85192 $text = sprintf('Process restarting (%s)', $this->getEnvAllow());
85193 $this->output($text);
85194 $text = 'Running '.$command;
85195 $this->output($text);
85196 }
85197
85198
85199
85200
85201
85202
85203 private function getEnvAllow()
85204 {
85205 return $this->envAllowXdebug.'='.getenv($this->envAllowXdebug);
85206 }
85207
85208
85209
85210
85211
85212
85213 private function getLoadedMessage()
85214 {
85215 $loaded = $this->loaded ? sprintf('loaded (%s)', $this->loaded) : 'not loaded';
85216 return 'The Xdebug extension is '.$loaded;
85217 }
85218 }
85219 <?php
85220
85221
85222
85223
85224
85225
85226
85227
85228
85229
85230 namespace Composer\XdebugHandler;
85231
85232 use Psr\Log\LoggerInterface;
85233
85234
85235
85236
85237 class XdebugHandler
85238 {
85239 const SUFFIX_ALLOW = '_ALLOW_XDEBUG';
85240 const SUFFIX_INIS = '_ORIGINAL_INIS';
85241 const RESTART_ID = 'internal';
85242 const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS';
85243 const DEBUG = 'XDEBUG_HANDLER_DEBUG';
85244
85245
85246 protected $tmpIni;
85247
85248 private static $inRestart;
85249 private static $name;
85250 private static $skipped;
85251
85252 private $cli;
85253 private $colorOption;
85254 private $debug;
85255 private $envAllowXdebug;
85256 private $envOriginalInis;
85257 private $loaded;
85258 private $persistent;
85259 private $script;
85260
85261 private $statusWriter;
85262
85263
85264
85265
85266
85267
85268
85269
85270
85271
85272
85273
85274 public function __construct($envPrefix, $colorOption = '')
85275 {
85276 if (!is_string($envPrefix) || empty($envPrefix) || !is_string($colorOption)) {
85277 throw new \RuntimeException('Invalid constructor parameter');
85278 }
85279
85280 self::$name = strtoupper($envPrefix);
85281 $this->envAllowXdebug = self::$name.self::SUFFIX_ALLOW;
85282 $this->envOriginalInis = self::$name.self::SUFFIX_INIS;
85283
85284 $this->colorOption = $colorOption;
85285
85286 if (extension_loaded('xdebug')) {
85287 $ext = new \ReflectionExtension('xdebug');
85288 $this->loaded = $ext->getVersion() ?: 'unknown';
85289 }
85290
85291 if ($this->cli = PHP_SAPI === 'cli') {
85292 $this->debug = getenv(self::DEBUG);
85293 }
85294
85295 $this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug);
85296 }
85297
85298
85299
85300
85301
85302
85303
85304
85305 public function setLogger(LoggerInterface $logger)
85306 {
85307 $this->statusWriter->setLogger($logger);
85308 return $this;
85309 }
85310
85311
85312
85313
85314
85315
85316
85317
85318 public function setMainScript($script)
85319 {
85320 $this->script = $script;
85321 return $this;
85322 }
85323
85324
85325
85326
85327
85328
85329 public function setPersistent()
85330 {
85331 $this->persistent = true;
85332 return $this;
85333 }
85334
85335
85336
85337
85338
85339
85340
85341
85342 public function check()
85343 {
85344 $this->notify(Status::CHECK, $this->loaded);
85345 $envArgs = explode('|', (string) getenv($this->envAllowXdebug));
85346
85347 if (empty($envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) {
85348
85349  $this->notify(Status::RESTART);
85350
85351 if ($this->prepareRestart()) {
85352 $command = $this->getCommand();
85353 $this->notify(Status::RESTARTING, $command);
85354 $this->restart($command);
85355 }
85356 return;
85357 }
85358
85359 if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
85360
85361  $this->notify(Status::RESTARTED);
85362
85363 Process::setEnv($this->envAllowXdebug);
85364 self::$inRestart = true;
85365
85366 if (!$this->loaded) {
85367
85368  self::$skipped = $envArgs[1];
85369 }
85370
85371
85372  $this->setEnvRestartSettings($envArgs);
85373 return;
85374 }
85375
85376 $this->notify(Status::NORESTART);
85377
85378 if ($settings = self::getRestartSettings()) {
85379
85380  $this->syncSettings($settings);
85381 }
85382 }
85383
85384
85385
85386
85387
85388
85389
85390
85391
85392 public static function getAllIniFiles()
85393 {
85394 if (!empty(self::$name)) {
85395 $env = getenv(self::$name.self::SUFFIX_INIS);
85396
85397 if (false !== $env) {
85398 return explode(PATH_SEPARATOR, $env);
85399 }
85400 }
85401
85402 $paths = array((string) php_ini_loaded_file());
85403
85404 if ($scanned = php_ini_scanned_files()) {
85405 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
85406 }
85407
85408 return $paths;
85409 }
85410
85411
85412
85413
85414
85415
85416
85417
85418
85419 public static function getRestartSettings()
85420 {
85421 $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS));
85422
85423 if (count($envArgs) !== 6
85424 || (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) {
85425 return;
85426 }
85427
85428 return array(
85429 'tmpIni' => $envArgs[0],
85430 'scannedInis' => (bool) $envArgs[1],
85431 'scanDir' => '*' === $envArgs[2] ? false : $envArgs[2],
85432 'phprc' => '*' === $envArgs[3] ? false : $envArgs[3],
85433 'inis' => explode(PATH_SEPARATOR, $envArgs[4]),
85434 'skipped' => $envArgs[5],
85435 );
85436 }
85437
85438
85439
85440
85441
85442
85443 public static function getSkippedVersion()
85444 {
85445 return (string) self::$skipped;
85446 }
85447
85448
85449
85450
85451
85452
85453
85454
85455 protected function requiresRestart($isLoaded)
85456 {
85457 return $isLoaded;
85458 }
85459
85460
85461
85462
85463
85464
85465 protected function restart($command)
85466 {
85467 $this->doRestart($command);
85468 }
85469
85470
85471
85472
85473
85474
85475 private function doRestart($command)
85476 {
85477 passthru($command, $exitCode);
85478 $this->notify(Status::INFO, 'Restarted process exited '.$exitCode);
85479
85480 if ($this->debug === '2') {
85481 $this->notify(Status::INFO, 'Temp ini saved: '.$this->tmpIni);
85482 } else {
85483 @unlink($this->tmpIni);
85484 }
85485
85486 exit($exitCode);
85487 }
85488
85489
85490
85491
85492
85493
85494
85495
85496
85497
85498
85499 private function prepareRestart()
85500 {
85501 $error = '';
85502 $iniFiles = self::getAllIniFiles();
85503 $scannedInis = count($iniFiles) > 1;
85504 $tmpDir = sys_get_temp_dir();
85505
85506 if (!$this->cli) {
85507 $error = 'Unsupported SAPI: '.PHP_SAPI;
85508 } elseif (!defined('PHP_BINARY')) {
85509 $error = 'PHP version is too old: '.PHP_VERSION;
85510 } elseif (!$this->checkConfiguration($info)) {
85511 $error = $info;
85512 } elseif (!$this->checkScanDirConfig()) {
85513 $error = 'PHP version does not report scanned inis: '.PHP_VERSION;
85514 } elseif (!$this->checkMainScript()) {
85515 $error = 'Unable to access main script: '.$this->script;
85516 } elseif (!$this->writeTmpIni($iniFiles, $tmpDir, $error)) {
85517 $error = $error ?: 'Unable to create temp ini file at: '.$tmpDir;
85518 } elseif (!$this->setEnvironment($scannedInis, $iniFiles)) {
85519 $error = 'Unable to set environment variables';
85520 }
85521
85522 if ($error) {
85523 $this->notify(Status::ERROR, $error);
85524 }
85525
85526 return empty($error);
85527 }
85528
85529
85530
85531
85532
85533
85534
85535
85536
85537
85538 private function writeTmpIni(array $iniFiles, $tmpDir, &$error)
85539 {
85540 if (!$this->tmpIni = @tempnam($tmpDir, '')) {
85541 return false;
85542 }
85543
85544
85545  if (empty($iniFiles[0])) {
85546 array_shift($iniFiles);
85547 }
85548
85549 $content = '';
85550 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
85551
85552 foreach ($iniFiles as $file) {
85553
85554  if (!$data = @file_get_contents($file)) {
85555 $error = 'Unable to read ini: '.$file;
85556 return false;
85557 }
85558 $content .= preg_replace($regex, ';$1', $data).PHP_EOL;
85559 }
85560
85561
85562  if ($config = parse_ini_string($content)) {
85563 $loaded = ini_get_all(null, false);
85564 $content .= $this->mergeLoadedConfig($loaded, $config);
85565 }
85566
85567
85568  $content .= 'opcache.enable_cli=0'.PHP_EOL;
85569
85570 return @file_put_contents($this->tmpIni, $content);
85571 }
85572
85573
85574
85575
85576
85577
85578 private function getCommand()
85579 {
85580 $php = array(PHP_BINARY);
85581 $args = array_slice($_SERVER['argv'], 1);
85582
85583 if (!$this->persistent) {
85584
85585  array_push($php, '-n', '-c', $this->tmpIni);
85586 }
85587
85588 if (defined('STDOUT') && Process::supportsColor(STDOUT)) {
85589 $args = Process::addColorOption($args, $this->colorOption);
85590 }
85591
85592 $args = array_merge($php, array($this->script), $args);
85593
85594 $cmd = Process::escape(array_shift($args), true, true);
85595 foreach ($args as $arg) {
85596 $cmd .= ' '.Process::escape($arg);
85597 }
85598
85599 return $cmd;
85600 }
85601
85602
85603
85604
85605
85606
85607
85608
85609
85610
85611
85612 private function setEnvironment($scannedInis, array $iniFiles)
85613 {
85614 $scanDir = getenv('PHP_INI_SCAN_DIR');
85615 $phprc = getenv('PHPRC');
85616
85617
85618  if (!putenv($this->envOriginalInis.'='.implode(PATH_SEPARATOR, $iniFiles))) {
85619 return false;
85620 }
85621
85622 if ($this->persistent) {
85623
85624  if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC='.$this->tmpIni)) {
85625 return false;
85626 }
85627 }
85628
85629
85630  $envArgs = array(
85631 self::RESTART_ID,
85632 $this->loaded,
85633 (int) $scannedInis,
85634 false === $scanDir ? '*' : $scanDir,
85635 false === $phprc ? '*' : $phprc,
85636 );
85637
85638 return putenv($this->envAllowXdebug.'='.implode('|', $envArgs));
85639 }
85640
85641
85642
85643
85644
85645
85646
85647 private function notify($op, $data = null)
85648 {
85649 $this->statusWriter->report($op, $data);
85650 }
85651
85652
85653
85654
85655
85656
85657
85658
85659
85660 private function mergeLoadedConfig(array $loadedConfig, array $iniConfig)
85661 {
85662 $content = '';
85663
85664 foreach ($loadedConfig as $name => $value) {
85665
85666  if (!is_string($value)
85667 || strpos($name, 'xdebug') === 0
85668 || $name === 'apc.mmap_file_mask') {
85669 continue;
85670 }
85671
85672 if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
85673
85674  $content .= $name.'="'.addcslashes($value, '\\"').'"'.PHP_EOL;
85675 }
85676 }
85677
85678 return $content;
85679 }
85680
85681
85682
85683
85684
85685
85686 private function checkMainScript()
85687 {
85688 if (null !== $this->script) {
85689
85690  return file_exists($this->script) || '--' === $this->script;
85691 }
85692
85693 if (file_exists($this->script = $_SERVER['argv'][0])) {
85694 return true;
85695 }
85696
85697
85698  $options = PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false;
85699 $trace = debug_backtrace($options);
85700
85701 if (($main = end($trace)) && isset($main['file'])) {
85702 return file_exists($this->script = $main['file']);
85703 }
85704
85705 return false;
85706 }
85707
85708
85709
85710
85711
85712
85713 private function setEnvRestartSettings($envArgs)
85714 {
85715 $settings = array(
85716 php_ini_loaded_file(),
85717 $envArgs[2],
85718 $envArgs[3],
85719 $envArgs[4],
85720 getenv($this->envOriginalInis),
85721 self::$skipped,
85722 );
85723
85724 Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings));
85725 }
85726
85727
85728
85729
85730
85731
85732 private function syncSettings(array $settings)
85733 {
85734 if (false === getenv($this->envOriginalInis)) {
85735
85736  Process::setEnv($this->envOriginalInis, implode(PATH_SEPARATOR, $settings['inis']));
85737 }
85738
85739 self::$skipped = $settings['skipped'];
85740 $this->notify(Status::INFO, 'Process called with existing restart settings');
85741 }
85742
85743
85744
85745
85746
85747
85748
85749
85750
85751 private function checkScanDirConfig()
85752 {
85753 return !(getenv('PHP_INI_SCAN_DIR')
85754 && !PHP_CONFIG_FILE_SCAN_DIR
85755 && (PHP_VERSION_ID < 70113
85756 || PHP_VERSION_ID === 70200));
85757 }
85758
85759
85760
85761
85762
85763
85764 private function checkConfiguration(&$info)
85765 {
85766 if (false !== strpos(ini_get('disable_functions'), 'passthru')) {
85767 $info = 'passthru function is disabled';
85768 return false;
85769 }
85770
85771 if (extension_loaded('uopz') && !ini_get('uopz.disable')) {
85772
85773  if (function_exists('uopz_allow_exit')) {
85774 @uopz_allow_exit(true);
85775 } else {
85776 $info = 'uopz extension is not compatible';
85777 return false;
85778 }
85779 }
85780
85781 return true;
85782 }
85783 }
85784 Copyright (c) 2012 PHP Framework Interoperability Group
85785
85786 Permission is hereby granted, free of charge, to any person obtaining a copy 
85787 of this software and associated documentation files (the "Software"), to deal
85788 in the Software without restriction, including without limitation the rights 
85789 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
85790 copies of the Software, and to permit persons to whom the Software is 
85791 furnished to do so, subject to the following conditions:
85792
85793 The above copyright notice and this permission notice shall be included in 
85794 all copies or substantial portions of the Software.
85795
85796 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
85797 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85798 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
85799 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
85800 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
85801 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
85802 THE SOFTWARE.
85803 <?php
85804
85805 namespace Psr\Log;
85806
85807
85808
85809
85810
85811
85812
85813
85814 abstract class AbstractLogger implements LoggerInterface
85815 {
85816
85817
85818
85819
85820
85821
85822
85823
85824 public function emergency($message, array $context = array())
85825 {
85826 $this->log(LogLevel::EMERGENCY, $message, $context);
85827 }
85828
85829
85830
85831
85832
85833
85834
85835
85836
85837
85838
85839
85840 public function alert($message, array $context = array())
85841 {
85842 $this->log(LogLevel::ALERT, $message, $context);
85843 }
85844
85845
85846
85847
85848
85849
85850
85851
85852
85853
85854
85855 public function critical($message, array $context = array())
85856 {
85857 $this->log(LogLevel::CRITICAL, $message, $context);
85858 }
85859
85860
85861
85862
85863
85864
85865
85866
85867
85868
85869 public function error($message, array $context = array())
85870 {
85871 $this->log(LogLevel::ERROR, $message, $context);
85872 }
85873
85874
85875
85876
85877
85878
85879
85880
85881
85882
85883
85884
85885 public function warning($message, array $context = array())
85886 {
85887 $this->log(LogLevel::WARNING, $message, $context);
85888 }
85889
85890
85891
85892
85893
85894
85895
85896
85897
85898 public function notice($message, array $context = array())
85899 {
85900 $this->log(LogLevel::NOTICE, $message, $context);
85901 }
85902
85903
85904
85905
85906
85907
85908
85909
85910
85911
85912
85913 public function info($message, array $context = array())
85914 {
85915 $this->log(LogLevel::INFO, $message, $context);
85916 }
85917
85918
85919
85920
85921
85922
85923
85924
85925
85926 public function debug($message, array $context = array())
85927 {
85928 $this->log(LogLevel::DEBUG, $message, $context);
85929 }
85930 }
85931 <?php
85932
85933 namespace Psr\Log;
85934
85935 class InvalidArgumentException extends \InvalidArgumentException
85936 {
85937 }
85938 <?php
85939
85940 namespace Psr\Log;
85941
85942
85943
85944
85945 class LogLevel
85946 {
85947 const EMERGENCY = 'emergency';
85948 const ALERT = 'alert';
85949 const CRITICAL = 'critical';
85950 const ERROR = 'error';
85951 const WARNING = 'warning';
85952 const NOTICE = 'notice';
85953 const INFO = 'info';
85954 const DEBUG = 'debug';
85955 }
85956 <?php
85957
85958 namespace Psr\Log;
85959
85960
85961
85962
85963 interface LoggerAwareInterface
85964 {
85965
85966
85967
85968
85969
85970
85971
85972 public function setLogger(LoggerInterface $logger);
85973 }
85974 <?php
85975
85976 namespace Psr\Log;
85977
85978
85979
85980
85981 trait LoggerAwareTrait
85982 {
85983
85984
85985
85986
85987
85988 protected $logger;
85989
85990
85991
85992
85993
85994
85995 public function setLogger(LoggerInterface $logger)
85996 {
85997 $this->logger = $logger;
85998 }
85999 }
86000 <?php
86001
86002 namespace Psr\Log;
86003
86004
86005
86006
86007
86008
86009
86010
86011
86012
86013
86014
86015
86016
86017
86018
86019 interface LoggerInterface
86020 {
86021
86022
86023
86024
86025
86026
86027
86028
86029 public function emergency($message, array $context = array());
86030
86031
86032
86033
86034
86035
86036
86037
86038
86039
86040
86041
86042 public function alert($message, array $context = array());
86043
86044
86045
86046
86047
86048
86049
86050
86051
86052
86053
86054 public function critical($message, array $context = array());
86055
86056
86057
86058
86059
86060
86061
86062
86063
86064
86065 public function error($message, array $context = array());
86066
86067
86068
86069
86070
86071
86072
86073
86074
86075
86076
86077
86078 public function warning($message, array $context = array());
86079
86080
86081
86082
86083
86084
86085
86086
86087
86088 public function notice($message, array $context = array());
86089
86090
86091
86092
86093
86094
86095
86096
86097
86098
86099
86100 public function info($message, array $context = array());
86101
86102
86103
86104
86105
86106
86107
86108
86109
86110 public function debug($message, array $context = array());
86111
86112
86113
86114
86115
86116
86117
86118
86119
86120
86121
86122
86123 public function log($level, $message, array $context = array());
86124 }
86125 <?php
86126
86127 namespace Psr\Log;
86128
86129
86130
86131
86132
86133
86134
86135
86136
86137 trait LoggerTrait
86138 {
86139
86140
86141
86142
86143
86144
86145
86146
86147 public function emergency($message, array $context = array())
86148 {
86149 $this->log(LogLevel::EMERGENCY, $message, $context);
86150 }
86151
86152
86153
86154
86155
86156
86157
86158
86159
86160
86161
86162
86163 public function alert($message, array $context = array())
86164 {
86165 $this->log(LogLevel::ALERT, $message, $context);
86166 }
86167
86168
86169
86170
86171
86172
86173
86174
86175
86176
86177
86178 public function critical($message, array $context = array())
86179 {
86180 $this->log(LogLevel::CRITICAL, $message, $context);
86181 }
86182
86183
86184
86185
86186
86187
86188
86189
86190
86191
86192 public function error($message, array $context = array())
86193 {
86194 $this->log(LogLevel::ERROR, $message, $context);
86195 }
86196
86197
86198
86199
86200
86201
86202
86203
86204
86205
86206
86207
86208 public function warning($message, array $context = array())
86209 {
86210 $this->log(LogLevel::WARNING, $message, $context);
86211 }
86212
86213
86214
86215
86216
86217
86218
86219
86220
86221 public function notice($message, array $context = array())
86222 {
86223 $this->log(LogLevel::NOTICE, $message, $context);
86224 }
86225
86226
86227
86228
86229
86230
86231
86232
86233
86234
86235
86236 public function info($message, array $context = array())
86237 {
86238 $this->log(LogLevel::INFO, $message, $context);
86239 }
86240
86241
86242
86243
86244
86245
86246
86247
86248
86249 public function debug($message, array $context = array())
86250 {
86251 $this->log(LogLevel::DEBUG, $message, $context);
86252 }
86253
86254
86255
86256
86257
86258
86259
86260
86261
86262
86263
86264
86265 abstract public function log($level, $message, array $context = array());
86266 }
86267 <?php
86268
86269 namespace Psr\Log;
86270
86271
86272
86273
86274
86275
86276
86277
86278
86279 class NullLogger extends AbstractLogger
86280 {
86281
86282
86283
86284
86285
86286
86287
86288
86289
86290
86291
86292 public function log($level, $message, array $context = array())
86293 {
86294
86295  }
86296 }
86297 <?php
86298
86299 namespace Psr\Log\Test;
86300
86301 use Psr\Log\LoggerInterface;
86302 use Psr\Log\LogLevel;
86303 use PHPUnit\Framework\TestCase;
86304
86305
86306
86307
86308
86309
86310
86311 abstract class LoggerInterfaceTest extends TestCase
86312 {
86313
86314
86315
86316 abstract public function getLogger();
86317
86318
86319
86320
86321
86322
86323
86324
86325
86326
86327 abstract public function getLogs();
86328
86329 public function testImplements()
86330 {
86331 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
86332 }
86333
86334
86335
86336
86337 public function testLogsAtAllLevels($level, $message)
86338 {
86339 $logger = $this->getLogger();
86340 $logger->{$level}($message, array('user' => 'Bob'));
86341 $logger->log($level, $message, array('user' => 'Bob'));
86342
86343 $expected = array(
86344 $level.' message of level '.$level.' with context: Bob',
86345 $level.' message of level '.$level.' with context: Bob',
86346 );
86347 $this->assertEquals($expected, $this->getLogs());
86348 }
86349
86350 public function provideLevelsAndMessages()
86351 {
86352 return array(
86353 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
86354 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
86355 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
86356 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
86357 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
86358 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
86359 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
86360 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
86361 );
86362 }
86363
86364
86365
86366
86367 public function testThrowsOnInvalidLevel()
86368 {
86369 $logger = $this->getLogger();
86370 $logger->log('invalid level', 'Foo');
86371 }
86372
86373 public function testContextReplacement()
86374 {
86375 $logger = $this->getLogger();
86376 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
86377
86378 $expected = array('info {Message {nothing} Bob Bar a}');
86379 $this->assertEquals($expected, $this->getLogs());
86380 }
86381
86382 public function testObjectCastToString()
86383 {
86384 if (method_exists($this, 'createPartialMock')) {
86385 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
86386 } else {
86387 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
86388 }
86389 $dummy->expects($this->once())
86390 ->method('__toString')
86391 ->will($this->returnValue('DUMMY'));
86392
86393 $this->getLogger()->warning($dummy);
86394
86395 $expected = array('warning DUMMY');
86396 $this->assertEquals($expected, $this->getLogs());
86397 }
86398
86399 public function testContextCanContainAnything()
86400 {
86401 $closed = fopen('php://memory', 'r');
86402 fclose($closed);
86403
86404 $context = array(
86405 'bool' => true,
86406 'null' => null,
86407 'string' => 'Foo',
86408 'int' => 0,
86409 'float' => 0.5,
86410 'nested' => array('with object' => new DummyTest),
86411 'object' => new \DateTime,
86412 'resource' => fopen('php://memory', 'r'),
86413 'closed' => $closed,
86414 );
86415
86416 $this->getLogger()->warning('Crazy context data', $context);
86417
86418 $expected = array('warning Crazy context data');
86419 $this->assertEquals($expected, $this->getLogs());
86420 }
86421
86422 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
86423 {
86424 $logger = $this->getLogger();
86425 $logger->warning('Random message', array('exception' => 'oops'));
86426 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
86427
86428 $expected = array(
86429 'warning Random message',
86430 'critical Uncaught Exception!'
86431 );
86432 $this->assertEquals($expected, $this->getLogs());
86433 }
86434 }
86435
86436 class DummyTest
86437 {
86438 public function __toString()
86439 {
86440 return 'DummyTest';
86441 }
86442 }
86443 <?php
86444
86445 namespace Psr\Log\Test;
86446
86447 use Psr\Log\AbstractLogger;
86448
86449
86450
86451
86452
86453
86454
86455
86456
86457
86458
86459
86460
86461
86462
86463
86464
86465
86466
86467
86468
86469
86470
86471
86472
86473
86474
86475
86476
86477
86478
86479
86480
86481
86482
86483
86484
86485
86486
86487
86488
86489
86490
86491
86492
86493
86494
86495
86496
86497
86498
86499 class TestLogger extends AbstractLogger
86500 {
86501
86502
86503
86504 public $records = [];
86505
86506 public $recordsByLevel = [];
86507
86508
86509
86510
86511 public function log($level, $message, array $context = [])
86512 {
86513 $record = [
86514 'level' => $level,
86515 'message' => $message,
86516 'context' => $context,
86517 ];
86518
86519 $this->recordsByLevel[$record['level']][] = $record;
86520 $this->records[] = $record;
86521 }
86522
86523 public function hasRecords($level)
86524 {
86525 return isset($this->recordsByLevel[$level]);
86526 }
86527
86528 public function hasRecord($record, $level)
86529 {
86530 if (is_string($record)) {
86531 $record = ['message' => $record];
86532 }
86533 return $this->hasRecordThatPasses(function ($rec) use ($record) {
86534 if ($rec['message'] !== $record['message']) {
86535 return false;
86536 }
86537 if (isset($record['context']) && $rec['context'] !== $record['context']) {
86538 return false;
86539 }
86540 return true;
86541 }, $level);
86542 }
86543
86544 public function hasRecordThatContains($message, $level)
86545 {
86546 return $this->hasRecordThatPasses(function ($rec) use ($message) {
86547 return strpos($rec['message'], $message) !== false;
86548 }, $level);
86549 }
86550
86551 public function hasRecordThatMatches($regex, $level)
86552 {
86553 return $this->hasRecordThatPasses(function ($rec) use ($regex) {
86554 return preg_match($regex, $rec['message']) > 0;
86555 }, $level);
86556 }
86557
86558 public function hasRecordThatPasses(callable $predicate, $level)
86559 {
86560 if (!isset($this->recordsByLevel[$level])) {
86561 return false;
86562 }
86563 foreach ($this->recordsByLevel[$level] as $i => $rec) {
86564 if (call_user_func($predicate, $rec, $i)) {
86565 return true;
86566 }
86567 }
86568 return false;
86569 }
86570
86571 public function __call($method, $args)
86572 {
86573 if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
86574 $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
86575 $level = strtolower($matches[2]);
86576 if (method_exists($this, $genericMethod)) {
86577 $args[] = $level;
86578 return call_user_func_array([$this, $genericMethod], $args);
86579 }
86580 }
86581 throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
86582 }
86583
86584 public function reset()
86585 {
86586 $this->records = [];
86587 $this->recordsByLevel = [];
86588 }
86589 }
86590 <?php
86591
86592
86593
86594 require_once __DIR__ . '/composer/autoload_real.php';
86595
86596 return ComposerAutoloaderInitComposerPhar1579015832::getLoader();
86597 <?php
86598
86599
86600
86601 $vendorDir = dirname(dirname(__FILE__));
86602 $baseDir = dirname($vendorDir);
86603
86604 return array(
86605 );
86606 <?php
86607
86608
86609
86610 $vendorDir = dirname(dirname(__FILE__));
86611 $baseDir = dirname($vendorDir);
86612
86613 return array(
86614 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
86615 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
86616 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
86617 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
86618 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
86619 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
86620 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
86621 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
86622 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
86623 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
86624 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
86625 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
86626 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
86627 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
86628 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
86629 'Composer\\' => array($baseDir . '/src/Composer'),
86630 );
86631 <?php
86632
86633
86634
86635 $vendorDir = dirname(dirname(__FILE__));
86636 $baseDir = dirname($vendorDir);
86637
86638 return array(
86639 );
86640 <?php
86641
86642
86643
86644 $vendorDir = dirname(dirname(__FILE__));
86645 $baseDir = dirname($vendorDir);
86646
86647 return array(
86648 '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
86649 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
86650 );
86651 <?php
86652
86653
86654
86655 class ComposerAutoloaderInitComposerPhar1579015832
86656 {
86657 private static $loader;
86658
86659 public static function loadClassLoader($class)
86660 {
86661 if ('Composer\Autoload\ClassLoader' === $class) {
86662 require __DIR__ . '/ClassLoader.php';
86663 }
86664 }
86665
86666 public static function getLoader()
86667 {
86668 if (null !== self::$loader) {
86669 return self::$loader;
86670 }
86671
86672 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1579015832', 'loadClassLoader'), true, true);
86673 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
86674 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1579015832', 'loadClassLoader'));
86675
86676 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
86677 if ($useStaticLoader) {
86678 require_once __DIR__ . '/autoload_static.php';
86679
86680 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1579015832::getInitializer($loader));
86681 } else {
86682 $map = require __DIR__ . '/autoload_namespaces.php';
86683 foreach ($map as $namespace => $path) {
86684 $loader->set($namespace, $path);
86685 }
86686
86687 $map = require __DIR__ . '/autoload_psr4.php';
86688 foreach ($map as $namespace => $path) {
86689 $loader->setPsr4($namespace, $path);
86690 }
86691
86692 $classMap = require __DIR__ . '/autoload_classmap.php';
86693 if ($classMap) {
86694 $loader->addClassMap($classMap);
86695 }
86696 }
86697
86698 $loader->register(true);
86699
86700 if ($useStaticLoader) {
86701 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1579015832::$files;
86702 } else {
86703 $includeFiles = require __DIR__ . '/autoload_files.php';
86704 }
86705 foreach ($includeFiles as $fileIdentifier => $file) {
86706 composerRequireComposerPhar1579015832($fileIdentifier, $file);
86707 }
86708
86709 return $loader;
86710 }
86711 }
86712
86713 function composerRequireComposerPhar1579015832($fileIdentifier, $file)
86714 {
86715 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
86716 require $file;
86717
86718 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
86719 }
86720 }
86721 <?php
86722
86723
86724
86725 namespace Composer\Autoload;
86726
86727 class ComposerStaticInitComposerPhar1579015832
86728 {
86729 public static $files = array (
86730 '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
86731 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
86732 );
86733
86734 public static $prefixLengthsPsr4 = array (
86735 'S' => 
86736 array (
86737 'Symfony\\Polyfill\\Mbstring\\' => 26,
86738 'Symfony\\Polyfill\\Ctype\\' => 23,
86739 'Symfony\\Component\\Process\\' => 26,
86740 'Symfony\\Component\\Finder\\' => 25,
86741 'Symfony\\Component\\Filesystem\\' => 29,
86742 'Symfony\\Component\\Debug\\' => 24,
86743 'Symfony\\Component\\Console\\' => 26,
86744 'Seld\\PharUtils\\' => 15,
86745 'Seld\\JsonLint\\' => 14,
86746 ),
86747 'P' => 
86748 array (
86749 'Psr\\Log\\' => 8,
86750 ),
86751 'J' => 
86752 array (
86753 'JsonSchema\\' => 11,
86754 ),
86755 'C' => 
86756 array (
86757 'Composer\\XdebugHandler\\' => 23,
86758 'Composer\\Spdx\\' => 14,
86759 'Composer\\Semver\\' => 16,
86760 'Composer\\CaBundle\\' => 18,
86761 'Composer\\' => 9,
86762 ),
86763 );
86764
86765 public static $prefixDirsPsr4 = array (
86766 'Symfony\\Polyfill\\Mbstring\\' => 
86767 array (
86768 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
86769 ),
86770 'Symfony\\Polyfill\\Ctype\\' => 
86771 array (
86772 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
86773 ),
86774 'Symfony\\Component\\Process\\' => 
86775 array (
86776 0 => __DIR__ . '/..' . '/symfony/process',
86777 ),
86778 'Symfony\\Component\\Finder\\' => 
86779 array (
86780 0 => __DIR__ . '/..' . '/symfony/finder',
86781 ),
86782 'Symfony\\Component\\Filesystem\\' => 
86783 array (
86784 0 => __DIR__ . '/..' . '/symfony/filesystem',
86785 ),
86786 'Symfony\\Component\\Debug\\' => 
86787 array (
86788 0 => __DIR__ . '/..' . '/symfony/debug',
86789 ),
86790 'Symfony\\Component\\Console\\' => 
86791 array (
86792 0 => __DIR__ . '/..' . '/symfony/console',
86793 ),
86794 'Seld\\PharUtils\\' => 
86795 array (
86796 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
86797 ),
86798 'Seld\\JsonLint\\' => 
86799 array (
86800 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
86801 ),
86802 'Psr\\Log\\' => 
86803 array (
86804 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
86805 ),
86806 'JsonSchema\\' => 
86807 array (
86808 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
86809 ),
86810 'Composer\\XdebugHandler\\' => 
86811 array (
86812 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
86813 ),
86814 'Composer\\Spdx\\' => 
86815 array (
86816 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
86817 ),
86818 'Composer\\Semver\\' => 
86819 array (
86820 0 => __DIR__ . '/..' . '/composer/semver/src',
86821 ),
86822 'Composer\\CaBundle\\' => 
86823 array (
86824 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
86825 ),
86826 'Composer\\' => 
86827 array (
86828 0 => __DIR__ . '/../..' . '/src/Composer',
86829 ),
86830 );
86831
86832 public static function getInitializer(ClassLoader $loader)
86833 {
86834 return \Closure::bind(function () use ($loader) {
86835 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1579015832::$prefixLengthsPsr4;
86836 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1579015832::$prefixDirsPsr4;
86837
86838 }, null, ClassLoader::class);
86839 }
86840 }
86841 <?php
86842
86843
86844
86845
86846
86847
86848
86849
86850
86851
86852
86853 namespace Composer\Autoload;
86854
86855
86856
86857
86858
86859
86860
86861
86862
86863
86864
86865
86866
86867
86868
86869
86870
86871
86872
86873
86874
86875
86876
86877
86878
86879
86880
86881
86882
86883 class ClassLoader
86884 {
86885
86886  private $prefixLengthsPsr4 = array();
86887 private $prefixDirsPsr4 = array();
86888 private $fallbackDirsPsr4 = array();
86889
86890
86891  private $prefixesPsr0 = array();
86892 private $fallbackDirsPsr0 = array();
86893
86894 private $useIncludePath = false;
86895 private $classMap = array();
86896 private $classMapAuthoritative = false;
86897 private $missingClasses = array();
86898 private $apcuPrefix;
86899
86900 public function getPrefixes()
86901 {
86902 if (!empty($this->prefixesPsr0)) {
86903 return call_user_func_array('array_merge', $this->prefixesPsr0);
86904 }
86905
86906 return array();
86907 }
86908
86909 public function getPrefixesPsr4()
86910 {
86911 return $this->prefixDirsPsr4;
86912 }
86913
86914 public function getFallbackDirs()
86915 {
86916 return $this->fallbackDirsPsr0;
86917 }
86918
86919 public function getFallbackDirsPsr4()
86920 {
86921 return $this->fallbackDirsPsr4;
86922 }
86923
86924 public function getClassMap()
86925 {
86926 return $this->classMap;
86927 }
86928
86929
86930
86931
86932 public function addClassMap(array $classMap)
86933 {
86934 if ($this->classMap) {
86935 $this->classMap = array_merge($this->classMap, $classMap);
86936 } else {
86937 $this->classMap = $classMap;
86938 }
86939 }
86940
86941
86942
86943
86944
86945
86946
86947
86948
86949 public function add($prefix, $paths, $prepend = false)
86950 {
86951 if (!$prefix) {
86952 if ($prepend) {
86953 $this->fallbackDirsPsr0 = array_merge(
86954 (array) $paths,
86955 $this->fallbackDirsPsr0
86956 );
86957 } else {
86958 $this->fallbackDirsPsr0 = array_merge(
86959 $this->fallbackDirsPsr0,
86960 (array) $paths
86961 );
86962 }
86963
86964 return;
86965 }
86966
86967 $first = $prefix[0];
86968 if (!isset($this->prefixesPsr0[$first][$prefix])) {
86969 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
86970
86971 return;
86972 }
86973 if ($prepend) {
86974 $this->prefixesPsr0[$first][$prefix] = array_merge(
86975 (array) $paths,
86976 $this->prefixesPsr0[$first][$prefix]
86977 );
86978 } else {
86979 $this->prefixesPsr0[$first][$prefix] = array_merge(
86980 $this->prefixesPsr0[$first][$prefix],
86981 (array) $paths
86982 );
86983 }
86984 }
86985
86986
86987
86988
86989
86990
86991
86992
86993
86994
86995
86996 public function addPsr4($prefix, $paths, $prepend = false)
86997 {
86998 if (!$prefix) {
86999
87000  if ($prepend) {
87001 $this->fallbackDirsPsr4 = array_merge(
87002 (array) $paths,
87003 $this->fallbackDirsPsr4
87004 );
87005 } else {
87006 $this->fallbackDirsPsr4 = array_merge(
87007 $this->fallbackDirsPsr4,
87008 (array) $paths
87009 );
87010 }
87011 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
87012
87013  $length = strlen($prefix);
87014 if ('\\' !== $prefix[$length - 1]) {
87015 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
87016 }
87017 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
87018 $this->prefixDirsPsr4[$prefix] = (array) $paths;
87019 } elseif ($prepend) {
87020
87021  $this->prefixDirsPsr4[$prefix] = array_merge(
87022 (array) $paths,
87023 $this->prefixDirsPsr4[$prefix]
87024 );
87025 } else {
87026
87027  $this->prefixDirsPsr4[$prefix] = array_merge(
87028 $this->prefixDirsPsr4[$prefix],
87029 (array) $paths
87030 );
87031 }
87032 }
87033
87034
87035
87036
87037
87038
87039
87040
87041 public function set($prefix, $paths)
87042 {
87043 if (!$prefix) {
87044 $this->fallbackDirsPsr0 = (array) $paths;
87045 } else {
87046 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
87047 }
87048 }
87049
87050
87051
87052
87053
87054
87055
87056
87057
87058
87059 public function setPsr4($prefix, $paths)
87060 {
87061 if (!$prefix) {
87062 $this->fallbackDirsPsr4 = (array) $paths;
87063 } else {
87064 $length = strlen($prefix);
87065 if ('\\' !== $prefix[$length - 1]) {
87066 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
87067 }
87068 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
87069 $this->prefixDirsPsr4[$prefix] = (array) $paths;
87070 }
87071 }
87072
87073
87074
87075
87076
87077
87078 public function setUseIncludePath($useIncludePath)
87079 {
87080 $this->useIncludePath = $useIncludePath;
87081 }
87082
87083
87084
87085
87086
87087
87088
87089 public function getUseIncludePath()
87090 {
87091 return $this->useIncludePath;
87092 }
87093
87094
87095
87096
87097
87098
87099
87100 public function setClassMapAuthoritative($classMapAuthoritative)
87101 {
87102 $this->classMapAuthoritative = $classMapAuthoritative;
87103 }
87104
87105
87106
87107
87108
87109
87110 public function isClassMapAuthoritative()
87111 {
87112 return $this->classMapAuthoritative;
87113 }
87114
87115
87116
87117
87118
87119
87120 public function setApcuPrefix($apcuPrefix)
87121 {
87122 $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
87123 }
87124
87125
87126
87127
87128
87129
87130 public function getApcuPrefix()
87131 {
87132 return $this->apcuPrefix;
87133 }
87134
87135
87136
87137
87138
87139
87140 public function register($prepend = false)
87141 {
87142 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
87143 }
87144
87145
87146
87147
87148 public function unregister()
87149 {
87150 spl_autoload_unregister(array($this, 'loadClass'));
87151 }
87152
87153
87154
87155
87156
87157
87158
87159 public function loadClass($class)
87160 {
87161 if ($file = $this->findFile($class)) {
87162 includeFile($file);
87163
87164 return true;
87165 }
87166 }
87167
87168
87169
87170
87171
87172
87173
87174
87175 public function findFile($class)
87176 {
87177
87178  if (isset($this->classMap[$class])) {
87179 return $this->classMap[$class];
87180 }
87181 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
87182 return false;
87183 }
87184 if (null !== $this->apcuPrefix) {
87185 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
87186 if ($hit) {
87187 return $file;
87188 }
87189 }
87190
87191 $file = $this->findFileWithExtension($class, '.php');
87192
87193
87194  if (false === $file && defined('HHVM_VERSION')) {
87195 $file = $this->findFileWithExtension($class, '.hh');
87196 }
87197
87198 if (null !== $this->apcuPrefix) {
87199 apcu_add($this->apcuPrefix.$class, $file);
87200 }
87201
87202 if (false === $file) {
87203
87204  $this->missingClasses[$class] = true;
87205 }
87206
87207 return $file;
87208 }
87209
87210 private function findFileWithExtension($class, $ext)
87211 {
87212
87213  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
87214
87215 $first = $class[0];
87216 if (isset($this->prefixLengthsPsr4[$first])) {
87217 $subPath = $class;
87218 while (false !== $lastPos = strrpos($subPath, '\\')) {
87219 $subPath = substr($subPath, 0, $lastPos);
87220 $search = $subPath . '\\';
87221 if (isset($this->prefixDirsPsr4[$search])) {
87222 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
87223 foreach ($this->prefixDirsPsr4[$search] as $dir) {
87224 if (file_exists($file = $dir . $pathEnd)) {
87225 return $file;
87226 }
87227 }
87228 }
87229 }
87230 }
87231
87232
87233  foreach ($this->fallbackDirsPsr4 as $dir) {
87234 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
87235 return $file;
87236 }
87237 }
87238
87239
87240  if (false !== $pos = strrpos($class, '\\')) {
87241
87242  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
87243 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
87244 } else {
87245
87246  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
87247 }
87248
87249 if (isset($this->prefixesPsr0[$first])) {
87250 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
87251 if (0 === strpos($class, $prefix)) {
87252 foreach ($dirs as $dir) {
87253 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
87254 return $file;
87255 }
87256 }
87257 }
87258 }
87259 }
87260
87261
87262  foreach ($this->fallbackDirsPsr0 as $dir) {
87263 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
87264 return $file;
87265 }
87266 }
87267
87268
87269  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
87270 return $file;
87271 }
87272
87273 return false;
87274 }
87275 }
87276
87277
87278
87279
87280
87281
87282 function includeFile($file)
87283 {
87284 include $file;
87285 }
87286 ##
87287 ## Bundle of CA Root Certificates
87288 ##
87289 ## Certificate data from Mozilla as of: Wed Jan  1 04:12:10 2020 GMT
87290 ##
87291 ## This is a bundle of X.509 certificates of public Certificate Authorities
87292 ## (CA). These were automatically extracted from Mozilla's root certificates
87293 ## file (certdata.txt).  This file can be found in the mozilla source tree:
87294 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
87295 ##
87296 ## It contains the certificates in PEM format and therefore
87297 ## can be directly used with curl / libcurl / php_curl, or with
87298 ## an Apache+mod_ssl webserver for SSL client authentication.
87299 ## Just configure this file as the SSLCACertificateFile.
87300 ##
87301 ## Conversion done with mk-ca-bundle.pl version 1.27.
87302 ## SHA256: f3bdcd74612952da8476a9d4147f50b29ad0710b7dd95b4c8690500209986d70
87303 ##
87304
87305
87306 GlobalSign Root CA
87307 ==================
87308 -----BEGIN CERTIFICATE-----
87309 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
87310 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
87311 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
87312 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
87313 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
87314 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
87315 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
87316 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
87317 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
87318 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
87319 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
87320 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
87321 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
87322 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
87323 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
87324 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
87325 -----END CERTIFICATE-----
87326
87327 GlobalSign Root CA - R2
87328 =======================
87329 -----BEGIN CERTIFICATE-----
87330 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
87331 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
87332 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
87333 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
87334 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
87335 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
87336 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
87337 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
87338 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
87339 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
87340 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
87341 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
87342 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
87343 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
87344 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
87345 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
87346 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
87347 -----END CERTIFICATE-----
87348
87349 Verisign Class 3 Public Primary Certification Authority - G3
87350 ============================================================
87351 -----BEGIN CERTIFICATE-----
87352 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
87353 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
87354 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
87355 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
87356 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
87357 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
87358 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
87359 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
87360 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
87361 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
87362 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
87363 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
87364 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
87365 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
87366 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
87367 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
87368 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
87369 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
87370 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
87371 -----END CERTIFICATE-----
87372
87373 Entrust.net Premium 2048 Secure Server CA
87374 =========================================
87375 -----BEGIN CERTIFICATE-----
87376 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
87377 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
87378 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
87379 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
87380 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
87381 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
87382 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
87383 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
87384 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
87385 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
87386 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
87387 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
87388 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
87389 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
87390 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
87391 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
87392 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
87393 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
87394 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
87395 -----END CERTIFICATE-----
87396
87397 Baltimore CyberTrust Root
87398 =========================
87399 -----BEGIN CERTIFICATE-----
87400 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
87401 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
87402 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
87403 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
87404 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
87405 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
87406 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
87407 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
87408 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
87409 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
87410 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
87411 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
87412 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
87413 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
87414 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
87415 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
87416 -----END CERTIFICATE-----
87417
87418 AddTrust External Root
87419 ======================
87420 -----BEGIN CERTIFICATE-----
87421 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
87422 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
87423 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
87424 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
87425 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
87426 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
87427 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
87428 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
87429 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
87430 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
87431 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
87432 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
87433 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
87434 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
87435 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
87436 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
87437 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
87438 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
87439 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
87440 -----END CERTIFICATE-----
87441
87442 Entrust Root Certification Authority
87443 ====================================
87444 -----BEGIN CERTIFICATE-----
87445 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
87446 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
87447 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
87448 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
87449 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
87450 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
87451 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
87452 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
87453 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
87454 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
87455 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
87456 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
87457 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
87458 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
87459 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
87460 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
87461 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
87462 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
87463 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
87464 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
87465 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
87466 -----END CERTIFICATE-----
87467
87468 GeoTrust Global CA
87469 ==================
87470 -----BEGIN CERTIFICATE-----
87471 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
87472 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
87473 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
87474 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
87475 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
87476 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
87477 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
87478 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
87479 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
87480 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
87481 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
87482 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
87483 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
87484 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
87485 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
87486 Mw==
87487 -----END CERTIFICATE-----
87488
87489 GeoTrust Universal CA
87490 =====================
87491 -----BEGIN CERTIFICATE-----
87492 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
87493 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
87494 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
87495 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
87496 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
87497 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
87498 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
87499 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
87500 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
87501 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
87502 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
87503 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
87504 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
87505 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
87506 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
87507 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
87508 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
87509 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
87510 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
87511 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
87512 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
87513 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
87514 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
87515 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
87516 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
87517 -----END CERTIFICATE-----
87518
87519 GeoTrust Universal CA 2
87520 =======================
87521 -----BEGIN CERTIFICATE-----
87522 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
87523 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
87524 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
87525 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
87526 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
87527 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
87528 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
87529 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
87530 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
87531 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
87532 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
87533 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
87534 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
87535 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
87536 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
87537 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
87538 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
87539 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
87540 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
87541 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
87542 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
87543 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
87544 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
87545 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
87546 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
87547 -----END CERTIFICATE-----
87548
87549 Comodo AAA Services root
87550 ========================
87551 -----BEGIN CERTIFICATE-----
87552 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
87553 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
87554 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
87555 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
87556 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
87557 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
87558 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
87559 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
87560 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
87561 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
87562 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
87563 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
87564 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
87565 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
87566 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
87567 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
87568 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
87569 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
87570 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
87571 -----END CERTIFICATE-----
87572
87573 QuoVadis Root CA
87574 ================
87575 -----BEGIN CERTIFICATE-----
87576 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
87577 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
87578 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
87579 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
87580 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
87581 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
87582 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
87583 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
87584 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
87585 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
87586 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
87587 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
87588 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
87589 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
87590 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
87591 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
87592 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
87593 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
87594 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
87595 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
87596 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
87597 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
87598 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
87599 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
87600 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
87601 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
87602 5nrQNiOKSnQ2+Q==
87603 -----END CERTIFICATE-----
87604
87605 QuoVadis Root CA 2
87606 ==================
87607 -----BEGIN CERTIFICATE-----
87608 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
87609 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
87610 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
87611 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
87612 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
87613 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
87614 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
87615 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
87616 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
87617 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
87618 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
87619 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
87620 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
87621 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
87622 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
87623 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
87624 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
87625 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
87626 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
87627 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
87628 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
87629 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
87630 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
87631 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
87632 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
87633 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
87634 -----END CERTIFICATE-----
87635
87636 QuoVadis Root CA 3
87637 ==================
87638 -----BEGIN CERTIFICATE-----
87639 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
87640 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
87641 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
87642 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
87643 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
87644 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
87645 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
87646 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
87647 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
87648 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
87649 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
87650 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
87651 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
87652 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
87653 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
87654 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
87655 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
87656 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
87657 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
87658 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
87659 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
87660 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
87661 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
87662 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
87663 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
87664 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
87665 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
87666 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
87667 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
87668 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
87669 -----END CERTIFICATE-----
87670
87671 Security Communication Root CA
87672 ==============================
87673 -----BEGIN CERTIFICATE-----
87674 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
87675 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
87676 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
87677 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
87678 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
87679 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
87680 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
87681 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
87682 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
87683 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
87684 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
87685 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
87686 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
87687 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
87688 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
87689 FL39vmwLAw==
87690 -----END CERTIFICATE-----
87691
87692 Sonera Class 2 Root CA
87693 ======================
87694 -----BEGIN CERTIFICATE-----
87695 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
87696 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
87697 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
87698 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
87699 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
87700 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
87701 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
87702 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
87703 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
87704 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
87705 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
87706 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
87707 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
87708 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
87709 llpwrN9M
87710 -----END CERTIFICATE-----
87711
87712 XRamp Global CA Root
87713 ====================
87714 -----BEGIN CERTIFICATE-----
87715 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
87716 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
87717 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
87718 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
87719 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
87720 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
87721 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
87722 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
87723 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
87724 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
87725 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
87726 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
87727 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
87728 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
87729 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
87730 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
87731 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
87732 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
87733 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
87734 -----END CERTIFICATE-----
87735
87736 Go Daddy Class 2 CA
87737 ===================
87738 -----BEGIN CERTIFICATE-----
87739 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
87740 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
87741 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
87742 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
87743 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
87744 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
87745 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
87746 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
87747 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
87748 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
87749 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
87750 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
87751 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
87752 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
87753 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
87754 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
87755 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
87756 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
87757 vZ8=
87758 -----END CERTIFICATE-----
87759
87760 Starfield Class 2 CA
87761 ====================
87762 -----BEGIN CERTIFICATE-----
87763 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
87764 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
87765 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
87766 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
87767 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
87768 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
87769 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
87770 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
87771 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
87772 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
87773 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
87774 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
87775 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
87776 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
87777 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
87778 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
87779 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
87780 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
87781 QBFGmh95DmK/D5fs4C8fF5Q=
87782 -----END CERTIFICATE-----
87783
87784 Taiwan GRCA
87785 ===========
87786 -----BEGIN CERTIFICATE-----
87787 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
87788 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
87789 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
87790 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
87791 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
87792 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
87793 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
87794 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
87795 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
87796 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
87797 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
87798 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
87799 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
87800 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
87801 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
87802 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
87803 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
87804 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
87805 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
87806 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
87807 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
87808 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
87809 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
87810 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
87811 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
87812 -----END CERTIFICATE-----
87813
87814 DigiCert Assured ID Root CA
87815 ===========================
87816 -----BEGIN CERTIFICATE-----
87817 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
87818 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
87819 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
87820 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
87821 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
87822 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
87823 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
87824 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
87825 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
87826 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
87827 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
87828 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
87829 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
87830 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
87831 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
87832 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
87833 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
87834 -----END CERTIFICATE-----
87835
87836 DigiCert Global Root CA
87837 =======================
87838 -----BEGIN CERTIFICATE-----
87839 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
87840 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
87841 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
87842 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
87843 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
87844 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
87845 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
87846 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
87847 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
87848 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
87849 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
87850 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
87851 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
87852 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
87853 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
87854 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
87855 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
87856 -----END CERTIFICATE-----
87857
87858 DigiCert High Assurance EV Root CA
87859 ==================================
87860 -----BEGIN CERTIFICATE-----
87861 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
87862 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
87863 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
87864 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
87865 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
87866 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
87867 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
87868 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
87869 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
87870 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
87871 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
87872 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
87873 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
87874 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
87875 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
87876 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
87877 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
87878 -----END CERTIFICATE-----
87879
87880 DST Root CA X3
87881 ==============
87882 -----BEGIN CERTIFICATE-----
87883 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
87884 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
87885 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
87886 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
87887 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
87888 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
87889 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
87890 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
87891 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
87892 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
87893 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
87894 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
87895 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
87896 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
87897 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
87898 -----END CERTIFICATE-----
87899
87900 SwissSign Gold CA - G2
87901 ======================
87902 -----BEGIN CERTIFICATE-----
87903 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
87904 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
87905 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
87906 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
87907 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
87908 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
87909 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
87910 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
87911 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
87912 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
87913 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
87914 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
87915 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
87916 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
87917 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
87918 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
87919 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
87920 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
87921 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
87922 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
87923 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
87924 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
87925 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
87926 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
87927 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
87928 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
87929 -----END CERTIFICATE-----
87930
87931 SwissSign Silver CA - G2
87932 ========================
87933 -----BEGIN CERTIFICATE-----
87934 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
87935 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
87936 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
87937 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
87938 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
87939 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
87940 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
87941 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
87942 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
87943 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
87944 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
87945 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
87946 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
87947 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
87948 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
87949 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
87950 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
87951 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
87952 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
87953 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
87954 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
87955 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
87956 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
87957 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
87958 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
87959 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
87960 -----END CERTIFICATE-----
87961
87962 GeoTrust Primary Certification Authority
87963 ========================================
87964 -----BEGIN CERTIFICATE-----
87965 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
87966 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
87967 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
87968 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
87969 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
87970 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
87971 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
87972 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
87973 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
87974 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
87975 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
87976 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
87977 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
87978 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
87979 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
87980 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
87981 -----END CERTIFICATE-----
87982
87983 thawte Primary Root CA
87984 ======================
87985 -----BEGIN CERTIFICATE-----
87986 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
87987 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
87988 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
87989 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
87990 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
87991 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
87992 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
87993 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
87994 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
87995 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
87996 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
87997 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
87998 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
87999 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
88000 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
88001 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
88002 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
88003 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
88004 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
88005 -----END CERTIFICATE-----
88006
88007 VeriSign Class 3 Public Primary Certification Authority - G5
88008 ============================================================
88009 -----BEGIN CERTIFICATE-----
88010 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
88011 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
88012 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
88013 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
88014 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
88015 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
88016 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
88017 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
88018 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
88019 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
88020 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
88021 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
88022 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
88023 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
88024 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
88025 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
88026 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
88027 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
88028 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
88029 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
88030 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
88031 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
88032 -----END CERTIFICATE-----
88033
88034 SecureTrust CA
88035 ==============
88036 -----BEGIN CERTIFICATE-----
88037 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
88038 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
88039 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
88040 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
88041 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
88042 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
88043 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
88044 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
88045 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
88046 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
88047 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
88048 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
88049 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
88050 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
88051 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
88052 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
88053 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
88054 -----END CERTIFICATE-----
88055
88056 Secure Global CA
88057 ================
88058 -----BEGIN CERTIFICATE-----
88059 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
88060 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
88061 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
88062 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
88063 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
88064 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
88065 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
88066 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
88067 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
88068 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
88069 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
88070 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
88071 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
88072 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
88073 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
88074 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
88075 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
88076 -----END CERTIFICATE-----
88077
88078 COMODO Certification Authority
88079 ==============================
88080 -----BEGIN CERTIFICATE-----
88081 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
88082 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
88083 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
88084 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
88085 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
88086 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
88087 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
88088 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
88089 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
88090 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
88091 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
88092 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
88093 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
88094 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
88095 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
88096 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
88097 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
88098 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
88099 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
88100 -----END CERTIFICATE-----
88101
88102 Network Solutions Certificate Authority
88103 =======================================
88104 -----BEGIN CERTIFICATE-----
88105 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
88106 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
88107 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
88108 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
88109 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
88110 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
88111 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
88112 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
88113 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
88114 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
88115 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
88116 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
88117 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
88118 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
88119 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
88120 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
88121 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
88122 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
88123 -----END CERTIFICATE-----
88124
88125 COMODO ECC Certification Authority
88126 ==================================
88127 -----BEGIN CERTIFICATE-----
88128 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
88129 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
88130 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
88131 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
88132 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
88133 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
88134 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
88135 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
88136 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
88137 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
88138 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
88139 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
88140 -----END CERTIFICATE-----
88141
88142 OISTE WISeKey Global Root GA CA
88143 ===============================
88144 -----BEGIN CERTIFICATE-----
88145 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
88146 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
88147 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
88148 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
88149 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
88150 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
88151 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
88152 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
88153 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
88154 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
88155 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
88156 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
88157 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
88158 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
88159 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
88160 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
88161 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
88162 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
88163 -----END CERTIFICATE-----
88164
88165 Certigna
88166 ========
88167 -----BEGIN CERTIFICATE-----
88168 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
88169 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
88170 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
88171 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
88172 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
88173 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
88174 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
88175 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
88176 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
88177 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
88178 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
88179 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
88180 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
88181 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
88182 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
88183 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
88184 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
88185 -----END CERTIFICATE-----
88186
88187 Cybertrust Global Root
88188 ======================
88189 -----BEGIN CERTIFICATE-----
88190 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
88191 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
88192 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
88193 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
88194 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
88195 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
88196 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
88197 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
88198 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
88199 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
88200 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
88201 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
88202 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
88203 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
88204 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
88205 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
88206 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
88207 -----END CERTIFICATE-----
88208
88209 ePKI Root Certification Authority
88210 =================================
88211 -----BEGIN CERTIFICATE-----
88212 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
88213 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
88214 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
88215 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
88216 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
88217 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
88218 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
88219 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
88220 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
88221 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
88222 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
88223 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
88224 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
88225 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
88226 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
88227 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
88228 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
88229 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
88230 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
88231 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
88232 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
88233 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
88234 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
88235 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
88236 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
88237 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
88238 -----END CERTIFICATE-----
88239
88240 certSIGN ROOT CA
88241 ================
88242 -----BEGIN CERTIFICATE-----
88243 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
88244 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
88245 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
88246 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
88247 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
88248 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
88249 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
88250 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
88251 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
88252 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
88253 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
88254 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
88255 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
88256 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
88257 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
88258 -----END CERTIFICATE-----
88259
88260 GeoTrust Primary Certification Authority - G3
88261 =============================================
88262 -----BEGIN CERTIFICATE-----
88263 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
88264 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
88265 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
88266 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
88267 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
88268 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
88269 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
88270 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
88271 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
88272 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
88273 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
88274 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
88275 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
88276 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
88277 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
88278 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
88279 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
88280 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
88281 -----END CERTIFICATE-----
88282
88283 thawte Primary Root CA - G2
88284 ===========================
88285 -----BEGIN CERTIFICATE-----
88286 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
88287 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
88288 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
88289 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
88290 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
88291 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
88292 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
88293 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
88294 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
88295 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
88296 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
88297 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
88298 -----END CERTIFICATE-----
88299
88300 thawte Primary Root CA - G3
88301 ===========================
88302 -----BEGIN CERTIFICATE-----
88303 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
88304 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
88305 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
88306 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
88307 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
88308 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
88309 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
88310 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
88311 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
88312 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
88313 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
88314 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
88315 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
88316 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
88317 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
88318 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
88319 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
88320 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
88321 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
88322 -----END CERTIFICATE-----
88323
88324 GeoTrust Primary Certification Authority - G2
88325 =============================================
88326 -----BEGIN CERTIFICATE-----
88327 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
88328 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
88329 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
88330 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
88331 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
88332 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
88333 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
88334 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
88335 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
88336 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
88337 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
88338 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
88339 npaqBA+K
88340 -----END CERTIFICATE-----
88341
88342 VeriSign Universal Root Certification Authority
88343 ===============================================
88344 -----BEGIN CERTIFICATE-----
88345 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
88346 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
88347 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
88348 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
88349 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
88350 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
88351 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
88352 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
88353 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
88354 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
88355 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
88356 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
88357 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
88358 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
88359 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
88360 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
88361 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
88362 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
88363 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
88364 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
88365 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
88366 mJO37M2CYfE45k+XmCpajQ==
88367 -----END CERTIFICATE-----
88368
88369 VeriSign Class 3 Public Primary Certification Authority - G4
88370 ============================================================
88371 -----BEGIN CERTIFICATE-----
88372 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
88373 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
88374 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
88375 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
88376 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
88377 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
88378 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
88379 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
88380 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
88381 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
88382 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
88383 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
88384 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
88385 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
88386 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
88387 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
88388 -----END CERTIFICATE-----
88389
88390 NetLock Arany (Class Gold) Főtanúsítvány
88391 ========================================
88392 -----BEGIN CERTIFICATE-----
88393 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
88394 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
88395 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
88396 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
88397 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
88398 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
88399 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
88400 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
88401 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
88402 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
88403 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
88404 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
88405 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
88406 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
88407 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
88408 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
88409 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
88410 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
88411 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
88412 -----END CERTIFICATE-----
88413
88414 Staat der Nederlanden Root CA - G2
88415 ==================================
88416 -----BEGIN CERTIFICATE-----
88417 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
88418 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
88419 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
88420 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
88421 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
88422 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
88423 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
88424 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
88425 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
88426 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
88427 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
88428 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
88429 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
88430 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
88431 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
88432 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
88433 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
88434 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
88435 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
88436 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
88437 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
88438 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
88439 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
88440 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
88441 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
88442 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
88443 66+KAQ==
88444 -----END CERTIFICATE-----
88445
88446 Hongkong Post Root CA 1
88447 =======================
88448 -----BEGIN CERTIFICATE-----
88449 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
88450 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
88451 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
88452 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
88453 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
88454 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
88455 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
88456 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
88457 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
88458 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
88459 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
88460 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
88461 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
88462 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
88463 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
88464 -----END CERTIFICATE-----
88465
88466 SecureSign RootCA11
88467 ===================
88468 -----BEGIN CERTIFICATE-----
88469 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
88470 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
88471 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
88472 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
88473 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
88474 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
88475 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
88476 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
88477 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
88478 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
88479 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
88480 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
88481 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
88482 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
88483 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
88484 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
88485 -----END CERTIFICATE-----
88486
88487 Microsec e-Szigno Root CA 2009
88488 ==============================
88489 -----BEGIN CERTIFICATE-----
88490 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
88491 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
88492 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
88493 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
88494 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
88495 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
88496 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
88497 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
88498 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
88499 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
88500 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
88501 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
88502 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
88503 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
88504 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
88505 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
88506 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
88507 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
88508 LXpUq3DDfSJlgnCW
88509 -----END CERTIFICATE-----
88510
88511 GlobalSign Root CA - R3
88512 =======================
88513 -----BEGIN CERTIFICATE-----
88514 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
88515 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
88516 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
88517 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
88518 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
88519 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
88520 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
88521 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
88522 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
88523 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
88524 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
88525 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
88526 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
88527 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
88528 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
88529 kpeDMdmztcpHWD9f
88530 -----END CERTIFICATE-----
88531
88532 Autoridad de Certificacion Firmaprofesional CIF A62634068
88533 =========================================================
88534 -----BEGIN CERTIFICATE-----
88535 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
88536 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
88537 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
88538 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
88539 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
88540 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
88541 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
88542 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
88543 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
88544 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
88545 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
88546 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
88547 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
88548 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
88549 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
88550 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
88551 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
88552 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
88553 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
88554 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
88555 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
88556 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
88557 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
88558 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
88559 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
88560 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
88561 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
88562 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
88563 -----END CERTIFICATE-----
88564
88565 Izenpe.com
88566 ==========
88567 -----BEGIN CERTIFICATE-----
88568 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
88569 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
88570 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
88571 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
88572 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
88573 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
88574 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
88575 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
88576 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
88577 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
88578 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
88579 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
88580 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
88581 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
88582 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
88583 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
88584 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
88585 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
88586 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
88587 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
88588 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
88589 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
88590 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
88591 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
88592 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
88593 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
88594 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
88595 -----END CERTIFICATE-----
88596
88597 Chambers of Commerce Root - 2008
88598 ================================
88599 -----BEGIN CERTIFICATE-----
88600 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
88601 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
88602 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
88603 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
88604 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
88605 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
88606 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
88607 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
88608 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
88609 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
88610 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
88611 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
88612 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
88613 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
88614 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
88615 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
88616 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
88617 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
88618 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
88619 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
88620 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
88621 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
88622 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
88623 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
88624 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
88625 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
88626 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
88627 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
88628 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
88629 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
88630 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
88631 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
88632 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
88633 -----END CERTIFICATE-----
88634
88635 Global Chambersign Root - 2008
88636 ==============================
88637 -----BEGIN CERTIFICATE-----
88638 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
88639 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
88640 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
88641 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
88642 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
88643 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
88644 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
88645 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
88646 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
88647 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
88648 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
88649 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
88650 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
88651 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
88652 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
88653 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
88654 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
88655 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
88656 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
88657 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
88658 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
88659 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
88660 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
88661 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
88662 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
88663 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
88664 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
88665 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
88666 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
88667 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
88668 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
88669 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
88670 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
88671 -----END CERTIFICATE-----
88672
88673 Go Daddy Root Certificate Authority - G2
88674 ========================================
88675 -----BEGIN CERTIFICATE-----
88676 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
88677 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
88678 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
88679 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
88680 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
88681 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
88682 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
88683 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
88684 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
88685 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
88686 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
88687 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
88688 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
88689 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
88690 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
88691 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
88692 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
88693 -----END CERTIFICATE-----
88694
88695 Starfield Root Certificate Authority - G2
88696 =========================================
88697 -----BEGIN CERTIFICATE-----
88698 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
88699 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
88700 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
88701 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
88702 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
88703 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
88704 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
88705 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
88706 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
88707 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
88708 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
88709 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
88710 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
88711 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
88712 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
88713 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
88714 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
88715 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
88716 -----END CERTIFICATE-----
88717
88718 Starfield Services Root Certificate Authority - G2
88719 ==================================================
88720 -----BEGIN CERTIFICATE-----
88721 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
88722 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
88723 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
88724 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
88725 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
88726 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
88727 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
88728 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
88729 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
88730 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
88731 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
88732 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
88733 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
88734 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
88735 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
88736 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
88737 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
88738 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
88739 -----END CERTIFICATE-----
88740
88741 AffirmTrust Commercial
88742 ======================
88743 -----BEGIN CERTIFICATE-----
88744 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
88745 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
88746 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
88747 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
88748 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
88749 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
88750 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
88751 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
88752 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
88753 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
88754 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
88755 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
88756 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
88757 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
88758 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
88759 -----END CERTIFICATE-----
88760
88761 AffirmTrust Networking
88762 ======================
88763 -----BEGIN CERTIFICATE-----
88764 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
88765 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
88766 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
88767 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
88768 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
88769 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
88770 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
88771 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
88772 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
88773 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
88774 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
88775 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
88776 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
88777 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
88778 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
88779 -----END CERTIFICATE-----
88780
88781 AffirmTrust Premium
88782 ===================
88783 -----BEGIN CERTIFICATE-----
88784 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
88785 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
88786 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
88787 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
88788 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
88789 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
88790 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
88791 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
88792 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
88793 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
88794 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
88795 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
88796 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
88797 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
88798 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
88799 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
88800 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
88801 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
88802 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
88803 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
88804 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
88805 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
88806 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
88807 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
88808 -----END CERTIFICATE-----
88809
88810 AffirmTrust Premium ECC
88811 =======================
88812 -----BEGIN CERTIFICATE-----
88813 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
88814 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
88815 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
88816 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
88817 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
88818 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
88819 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
88820 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
88821 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
88822 eQ==
88823 -----END CERTIFICATE-----
88824
88825 Certum Trusted Network CA
88826 =========================
88827 -----BEGIN CERTIFICATE-----
88828 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
88829 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
88830 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
88831 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
88832 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
88833 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
88834 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
88835 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
88836 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
88837 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
88838 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
88839 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
88840 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
88841 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
88842 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
88843 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
88844 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
88845 -----END CERTIFICATE-----
88846
88847 TWCA Root Certification Authority
88848 =================================
88849 -----BEGIN CERTIFICATE-----
88850 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
88851 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
88852 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
88853 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
88854 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
88855 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
88856 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
88857 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
88858 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
88859 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
88860 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
88861 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
88862 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
88863 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
88864 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
88865 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
88866 -----END CERTIFICATE-----
88867
88868 Security Communication RootCA2
88869 ==============================
88870 -----BEGIN CERTIFICATE-----
88871 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
88872 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
88873 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
88874 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
88875 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
88876 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
88877 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
88878 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
88879 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
88880 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
88881 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
88882 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
88883 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
88884 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
88885 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
88886 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
88887 -----END CERTIFICATE-----
88888
88889 EC-ACC
88890 ======
88891 -----BEGIN CERTIFICATE-----
88892 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
88893 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
88894 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
88895 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
88896 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
88897 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
88898 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
88899 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
88900 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
88901 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
88902 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
88903 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
88904 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
88905 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
88906 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
88907 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
88908 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
88909 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
88910 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
88911 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
88912 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
88913 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
88914 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
88915 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
88916 5EI=
88917 -----END CERTIFICATE-----
88918
88919 Hellenic Academic and Research Institutions RootCA 2011
88920 =======================================================
88921 -----BEGIN CERTIFICATE-----
88922 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
88923 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
88924 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
88925 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
88926 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
88927 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
88928 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
88929 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
88930 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
88931 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
88932 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
88933 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
88934 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
88935 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
88936 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
88937 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
88938 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
88939 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
88940 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
88941 -----END CERTIFICATE-----
88942
88943 Actalis Authentication Root CA
88944 ==============================
88945 -----BEGIN CERTIFICATE-----
88946 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
88947 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
88948 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
88949 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
88950 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
88951 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
88952 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
88953 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
88954 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
88955 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
88956 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
88957 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
88958 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
88959 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
88960 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
88961 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
88962 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
88963 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
88964 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
88965 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
88966 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
88967 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
88968 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
88969 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
88970 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
88971 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
88972 -----END CERTIFICATE-----
88973
88974 Trustis FPS Root CA
88975 ===================
88976 -----BEGIN CERTIFICATE-----
88977 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
88978 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
88979 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
88980 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
88981 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
88982 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
88983 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
88984 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
88985 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
88986 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
88987 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
88988 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
88989 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
88990 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
88991 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
88992 iB6XzCGcKQENZetX2fNXlrtIzYE=
88993 -----END CERTIFICATE-----
88994
88995 Buypass Class 2 Root CA
88996 =======================
88997 -----BEGIN CERTIFICATE-----
88998 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
88999 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
89000 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
89001 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
89002 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
89003 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
89004 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
89005 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
89006 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
89007 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
89008 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
89009 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
89010 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
89011 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
89012 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
89013 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
89014 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
89015 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
89016 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
89017 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
89018 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
89019 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
89020 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
89021 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
89022 rJgWVqA=
89023 -----END CERTIFICATE-----
89024
89025 Buypass Class 3 Root CA
89026 =======================
89027 -----BEGIN CERTIFICATE-----
89028 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
89029 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
89030 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
89031 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
89032 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
89033 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
89034 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
89035 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
89036 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
89037 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
89038 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
89039 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
89040 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
89041 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
89042 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
89043 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
89044 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
89045 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
89046 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
89047 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
89048 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
89049 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
89050 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
89051 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
89052 Cp/HuZc=
89053 -----END CERTIFICATE-----
89054
89055 T-TeleSec GlobalRoot Class 3
89056 ============================
89057 -----BEGIN CERTIFICATE-----
89058 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
89059 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
89060 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
89061 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
89062 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
89063 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
89064 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
89065 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
89066 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
89067 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
89068 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
89069 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
89070 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
89071 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
89072 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
89073 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
89074 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
89075 -----END CERTIFICATE-----
89076
89077 EE Certification Centre Root CA
89078 ===============================
89079 -----BEGIN CERTIFICATE-----
89080 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
89081 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
89082 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
89083 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
89084 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
89085 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
89086 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
89087 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
89088 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
89089 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
89090 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
89091 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
89092 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
89093 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
89094 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
89095 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
89096 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
89097 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
89098 dcGWxZ0=
89099 -----END CERTIFICATE-----
89100
89101 D-TRUST Root Class 3 CA 2 2009
89102 ==============================
89103 -----BEGIN CERTIFICATE-----
89104 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
89105 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
89106 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
89107 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
89108 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
89109 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
89110 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
89111 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
89112 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
89113 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
89114 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
89115 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
89116 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
89117 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
89118 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
89119 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
89120 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
89121 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
89122 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
89123 -----END CERTIFICATE-----
89124
89125 D-TRUST Root Class 3 CA 2 EV 2009
89126 =================================
89127 -----BEGIN CERTIFICATE-----
89128 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
89129 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
89130 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
89131 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
89132 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
89133 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
89134 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
89135 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
89136 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
89137 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
89138 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
89139 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
89140 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
89141 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
89142 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
89143 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
89144 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
89145 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
89146 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
89147 w9y4AyHqnxbxLFS1
89148 -----END CERTIFICATE-----
89149
89150 CA Disig Root R2
89151 ================
89152 -----BEGIN CERTIFICATE-----
89153 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
89154 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
89155 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
89156 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
89157 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
89158 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
89159 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
89160 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
89161 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
89162 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
89163 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
89164 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
89165 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
89166 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
89167 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
89168 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
89169 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
89170 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
89171 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
89172 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
89173 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
89174 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
89175 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
89176 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
89177 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
89178 -----END CERTIFICATE-----
89179
89180 ACCVRAIZ1
89181 =========
89182 -----BEGIN CERTIFICATE-----
89183 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
89184 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
89185 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
89186 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
89187 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
89188 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
89189 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
89190 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
89191 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
89192 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
89193 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
89194 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
89195 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
89196 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
89197 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
89198 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
89199 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
89200 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
89201 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
89202 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
89203 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
89204 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
89205 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
89206 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
89207 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
89208 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
89209 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
89210 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
89211 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
89212 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
89213 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
89214 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
89215 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
89216 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
89217 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
89218 EfbRD0tVNEYqi4Y7
89219 -----END CERTIFICATE-----
89220
89221 TWCA Global Root CA
89222 ===================
89223 -----BEGIN CERTIFICATE-----
89224 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
89225 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
89226 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
89227 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
89228 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
89229 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
89230 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
89231 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
89232 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
89233 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
89234 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
89235 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
89236 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
89237 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
89238 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
89239 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
89240 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
89241 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
89242 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
89243 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
89244 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
89245 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
89246 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
89247 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
89248 -----END CERTIFICATE-----
89249
89250 TeliaSonera Root CA v1
89251 ======================
89252 -----BEGIN CERTIFICATE-----
89253 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
89254 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
89255 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
89256 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
89257 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
89258 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
89259 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
89260 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
89261 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
89262 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
89263 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
89264 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
89265 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
89266 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
89267 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
89268 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
89269 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
89270 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
89271 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
89272 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
89273 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
89274 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
89275 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
89276 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
89277 -----END CERTIFICATE-----
89278
89279 E-Tugra Certification Authority
89280 ===============================
89281 -----BEGIN CERTIFICATE-----
89282 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
89283 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
89284 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
89285 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
89286 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
89287 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
89288 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
89289 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
89290 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
89291 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
89292 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
89293 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
89294 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
89295 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
89296 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
89297 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
89298 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
89299 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
89300 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
89301 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
89302 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
89303 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
89304 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
89305 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
89306 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
89307 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
89308 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
89309 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
89310 C7TbO6Orb1wdtn7os4I07QZcJA==
89311 -----END CERTIFICATE-----
89312
89313 T-TeleSec GlobalRoot Class 2
89314 ============================
89315 -----BEGIN CERTIFICATE-----
89316 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
89317 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
89318 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
89319 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
89320 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
89321 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
89322 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
89323 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
89324 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
89325 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
89326 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
89327 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
89328 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
89329 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
89330 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
89331 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
89332 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
89333 -----END CERTIFICATE-----
89334
89335 Atos TrustedRoot 2011
89336 =====================
89337 -----BEGIN CERTIFICATE-----
89338 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
89339 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
89340 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
89341 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
89342 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
89343 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
89344 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
89345 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
89346 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
89347 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
89348 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
89349 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
89350 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
89351 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
89352 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
89353 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
89354 -----END CERTIFICATE-----
89355
89356 QuoVadis Root CA 1 G3
89357 =====================
89358 -----BEGIN CERTIFICATE-----
89359 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
89360 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
89361 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
89362 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
89363 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
89364 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
89365 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
89366 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
89367 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
89368 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
89369 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
89370 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
89371 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
89372 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89373 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
89374 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
89375 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
89376 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
89377 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
89378 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
89379 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
89380 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
89381 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
89382 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
89383 hMJKzRwuJIczYOXD
89384 -----END CERTIFICATE-----
89385
89386 QuoVadis Root CA 2 G3
89387 =====================
89388 -----BEGIN CERTIFICATE-----
89389 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
89390 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
89391 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
89392 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
89393 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
89394 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
89395 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
89396 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
89397 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
89398 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
89399 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
89400 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
89401 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
89402 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89403 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
89404 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
89405 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
89406 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
89407 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
89408 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
89409 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
89410 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
89411 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
89412 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
89413 O3jtZsSOeWmD3n+M
89414 -----END CERTIFICATE-----
89415
89416 QuoVadis Root CA 3 G3
89417 =====================
89418 -----BEGIN CERTIFICATE-----
89419 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
89420 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
89421 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
89422 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
89423 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
89424 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
89425 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
89426 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
89427 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
89428 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
89429 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
89430 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
89431 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
89432 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89433 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
89434 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
89435 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
89436 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
89437 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
89438 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
89439 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
89440 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
89441 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
89442 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
89443 PpxxVJkES/1Y+Zj0
89444 -----END CERTIFICATE-----
89445
89446 DigiCert Assured ID Root G2
89447 ===========================
89448 -----BEGIN CERTIFICATE-----
89449 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
89450 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
89451 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
89452 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
89453 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
89454 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
89455 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
89456 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
89457 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
89458 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
89459 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
89460 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
89461 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
89462 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
89463 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
89464 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
89465 IhNzbM8m9Yop5w==
89466 -----END CERTIFICATE-----
89467
89468 DigiCert Assured ID Root G3
89469 ===========================
89470 -----BEGIN CERTIFICATE-----
89471 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
89472 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
89473 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
89474 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
89475 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
89476 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
89477 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
89478 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
89479 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
89480 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
89481 1vUhZscv6pZjamVFkpUBtA==
89482 -----END CERTIFICATE-----
89483
89484 DigiCert Global Root G2
89485 =======================
89486 -----BEGIN CERTIFICATE-----
89487 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
89488 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
89489 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
89490 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
89491 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
89492 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
89493 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
89494 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
89495 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
89496 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
89497 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
89498 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
89499 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
89500 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
89501 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
89502 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
89503 MrY=
89504 -----END CERTIFICATE-----
89505
89506 DigiCert Global Root G3
89507 =======================
89508 -----BEGIN CERTIFICATE-----
89509 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
89510 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
89511 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
89512 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
89513 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
89514 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
89515 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
89516 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
89517 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
89518 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
89519 VOKa5Vt8sycX
89520 -----END CERTIFICATE-----
89521
89522 DigiCert Trusted Root G4
89523 ========================
89524 -----BEGIN CERTIFICATE-----
89525 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
89526 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
89527 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
89528 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
89529 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
89530 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
89531 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
89532 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
89533 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
89534 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
89535 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
89536 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
89537 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
89538 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
89539 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
89540 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
89541 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
89542 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
89543 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
89544 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
89545 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
89546 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
89547 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
89548 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
89549 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
89550 82Z+
89551 -----END CERTIFICATE-----
89552
89553 COMODO RSA Certification Authority
89554 ==================================
89555 -----BEGIN CERTIFICATE-----
89556 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
89557 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
89558 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
89559 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
89560 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
89561 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
89562 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
89563 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
89564 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
89565 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
89566 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
89567 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
89568 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
89569 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
89570 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
89571 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
89572 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
89573 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
89574 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
89575 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
89576 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
89577 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
89578 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
89579 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
89580 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
89581 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
89582 LaZRfyHBNVOFBkpdn627G190
89583 -----END CERTIFICATE-----
89584
89585 USERTrust RSA Certification Authority
89586 =====================================
89587 -----BEGIN CERTIFICATE-----
89588 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
89589 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
89590 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
89591 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
89592 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
89593 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
89594 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
89595 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
89596 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
89597 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
89598 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
89599 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
89600 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
89601 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
89602 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
89603 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
89604 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
89605 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
89606 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
89607 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
89608 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
89609 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
89610 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
89611 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
89612 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
89613 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
89614 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
89615 -----END CERTIFICATE-----
89616
89617 USERTrust ECC Certification Authority
89618 =====================================
89619 -----BEGIN CERTIFICATE-----
89620 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
89621 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
89622 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
89623 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
89624 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
89625 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
89626 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
89627 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
89628 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
89629 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
89630 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
89631 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
89632 -----END CERTIFICATE-----
89633
89634 GlobalSign ECC Root CA - R4
89635 ===========================
89636 -----BEGIN CERTIFICATE-----
89637 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
89638 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89639 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
89640 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89641 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
89642 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
89643 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
89644 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
89645 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
89646 -----END CERTIFICATE-----
89647
89648 GlobalSign ECC Root CA - R5
89649 ===========================
89650 -----BEGIN CERTIFICATE-----
89651 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
89652 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89653 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
89654 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89655 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
89656 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
89657 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
89658 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
89659 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
89660 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
89661 -----END CERTIFICATE-----
89662
89663 Staat der Nederlanden Root CA - G3
89664 ==================================
89665 -----BEGIN CERTIFICATE-----
89666 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
89667 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
89668 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
89669 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
89670 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
89671 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
89672 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
89673 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
89674 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
89675 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
89676 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
89677 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
89678 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
89679 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
89680 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
89681 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
89682 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
89683 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
89684 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
89685 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
89686 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
89687 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
89688 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
89689 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
89690 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
89691 -----END CERTIFICATE-----
89692
89693 Staat der Nederlanden EV Root CA
89694 ================================
89695 -----BEGIN CERTIFICATE-----
89696 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
89697 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
89698 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
89699 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
89700 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
89701 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
89702 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
89703 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
89704 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
89705 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
89706 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
89707 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
89708 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
89709 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
89710 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
89711 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
89712 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
89713 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
89714 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
89715 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
89716 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
89717 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
89718 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
89719 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
89720 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
89721 -----END CERTIFICATE-----
89722
89723 IdenTrust Commercial Root CA 1
89724 ==============================
89725 -----BEGIN CERTIFICATE-----
89726 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
89727 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
89728 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
89729 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
89730 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
89731 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
89732 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
89733 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
89734 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
89735 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
89736 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
89737 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
89738 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
89739 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
89740 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
89741 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
89742 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
89743 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
89744 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
89745 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
89746 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
89747 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
89748 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
89749 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
89750 cGzM7vRX+Bi6hG6H
89751 -----END CERTIFICATE-----
89752
89753 IdenTrust Public Sector Root CA 1
89754 =================================
89755 -----BEGIN CERTIFICATE-----
89756 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
89757 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
89758 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
89759 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
89760 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
89761 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
89762 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
89763 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
89764 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
89765 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
89766 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
89767 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
89768 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
89769 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
89770 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
89771 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
89772 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
89773 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
89774 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
89775 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
89776 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
89777 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
89778 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
89779 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
89780 3Wl9af0AVqW3rLatt8o+Ae+c
89781 -----END CERTIFICATE-----
89782
89783 Entrust Root Certification Authority - G2
89784 =========================================
89785 -----BEGIN CERTIFICATE-----
89786 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
89787 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
89788 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
89789 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
89790 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
89791 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
89792 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
89793 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
89794 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
89795 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
89796 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
89797 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
89798 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
89799 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
89800 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
89801 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
89802 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
89803 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
89804 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
89805 e4pIb4tF9g==
89806 -----END CERTIFICATE-----
89807
89808 Entrust Root Certification Authority - EC1
89809 ==========================================
89810 -----BEGIN CERTIFICATE-----
89811 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
89812 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
89813 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
89814 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
89815 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
89816 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
89817 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
89818 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
89819 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
89820 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
89821 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
89822 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
89823 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
89824 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
89825 -----END CERTIFICATE-----
89826
89827 CFCA EV ROOT
89828 ============
89829 -----BEGIN CERTIFICATE-----
89830 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
89831 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
89832 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
89833 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
89834 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
89835 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
89836 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
89837 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
89838 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
89839 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
89840 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
89841 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
89842 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
89843 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
89844 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
89845 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
89846 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
89847 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
89848 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
89849 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
89850 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
89851 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
89852 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
89853 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
89854 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
89855 -----END CERTIFICATE-----
89856
89857 OISTE WISeKey Global Root GB CA
89858 ===============================
89859 -----BEGIN CERTIFICATE-----
89860 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
89861 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
89862 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
89863 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
89864 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
89865 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
89866 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
89867 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
89868 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
89869 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
89870 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
89871 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
89872 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
89873 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
89874 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
89875 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
89876 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
89877 -----END CERTIFICATE-----
89878
89879 SZAFIR ROOT CA2
89880 ===============
89881 -----BEGIN CERTIFICATE-----
89882 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
89883 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
89884 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
89885 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
89886 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
89887 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
89888 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
89889 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
89890 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
89891 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
89892 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
89893 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
89894 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
89895 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
89896 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
89897 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
89898 -----END CERTIFICATE-----
89899
89900 Certum Trusted Network CA 2
89901 ===========================
89902 -----BEGIN CERTIFICATE-----
89903 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
89904 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
89905 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
89906 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
89907 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
89908 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
89909 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
89910 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
89911 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
89912 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
89913 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
89914 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
89915 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
89916 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
89917 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
89918 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89919 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
89920 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
89921 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
89922 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
89923 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
89924 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
89925 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
89926 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
89927 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
89928 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
89929 zAYspsbiDrW5viSP
89930 -----END CERTIFICATE-----
89931
89932 Hellenic Academic and Research Institutions RootCA 2015
89933 =======================================================
89934 -----BEGIN CERTIFICATE-----
89935 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
89936 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
89937 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
89938 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
89939 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
89940 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
89941 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
89942 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
89943 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
89944 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
89945 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
89946 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
89947 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
89948 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
89949 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
89950 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
89951 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89952 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
89953 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
89954 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
89955 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
89956 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
89957 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
89958 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
89959 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
89960 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
89961 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
89962 p/UsQu0yrbYhnr68
89963 -----END CERTIFICATE-----
89964
89965 Hellenic Academic and Research Institutions ECC RootCA 2015
89966 ===========================================================
89967 -----BEGIN CERTIFICATE-----
89968 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
89969 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
89970 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
89971 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
89972 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
89973 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
89974 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
89975 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
89976 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
89977 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
89978 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
89979 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
89980 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
89981 -----END CERTIFICATE-----
89982
89983 ISRG Root X1
89984 ============
89985 -----BEGIN CERTIFICATE-----
89986 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
89987 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
89988 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
89989 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
89990 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
89991 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
89992 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
89993 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
89994 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
89995 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
89996 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
89997 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
89998 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
89999 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
90000 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
90001 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
90002 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
90003 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
90004 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
90005 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
90006 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
90007 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
90008 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
90009 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
90010 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
90011 -----END CERTIFICATE-----
90012
90013 AC RAIZ FNMT-RCM
90014 ================
90015 -----BEGIN CERTIFICATE-----
90016 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
90017 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
90018 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
90019 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
90020 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
90021 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
90022 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
90023 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
90024 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
90025 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
90026 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
90027 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
90028 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
90029 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
90030 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
90031 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
90032 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
90033 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
90034 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
90035 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
90036 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
90037 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
90038 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
90039 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
90040 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
90041 -----END CERTIFICATE-----
90042
90043 Amazon Root CA 1
90044 ================
90045 -----BEGIN CERTIFICATE-----
90046 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
90047 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
90048 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
90049 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
90050 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
90051 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
90052 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
90053 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
90054 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
90055 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
90056 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
90057 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
90058 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
90059 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
90060 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
90061 -----END CERTIFICATE-----
90062
90063 Amazon Root CA 2
90064 ================
90065 -----BEGIN CERTIFICATE-----
90066 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
90067 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
90068 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
90069 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
90070 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
90071 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
90072 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
90073 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
90074 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
90075 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
90076 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
90077 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
90078 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
90079 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
90080 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
90081 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
90082 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
90083 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
90084 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
90085 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
90086 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
90087 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
90088 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
90089 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
90090 -----END CERTIFICATE-----
90091
90092 Amazon Root CA 3
90093 ================
90094 -----BEGIN CERTIFICATE-----
90095 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
90096 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
90097 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
90098 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
90099 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
90100 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
90101 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
90102 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
90103 -----END CERTIFICATE-----
90104
90105 Amazon Root CA 4
90106 ================
90107 -----BEGIN CERTIFICATE-----
90108 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
90109 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
90110 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
90111 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
90112 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
90113 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
90114 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
90115 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
90116 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
90117 -----END CERTIFICATE-----
90118
90119 LuxTrust Global Root 2
90120 ======================
90121 -----BEGIN CERTIFICATE-----
90122 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
90123 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
90124 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
90125 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
90126 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
90127 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
90128 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
90129 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
90130 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
90131 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
90132 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
90133 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
90134 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
90135 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
90136 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
90137 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
90138 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
90139 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
90140 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
90141 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
90142 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
90143 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
90144 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
90145 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
90146 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
90147 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
90148 -----END CERTIFICATE-----
90149
90150 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
90151 =============================================
90152 -----BEGIN CERTIFICATE-----
90153 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
90154 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
90155 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
90156 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
90157 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
90158 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
90159 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
90160 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
90161 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
90162 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
90163 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
90164 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
90165 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
90166 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
90167 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
90168 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
90169 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
90170 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
90171 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
90172 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
90173 -----END CERTIFICATE-----
90174
90175 GDCA TrustAUTH R5 ROOT
90176 ======================
90177 -----BEGIN CERTIFICATE-----
90178 MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
90179 BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
90180 DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
90181 YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
90182 IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
90183 AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
90184 AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
90185 OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
90186 pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
90187 9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
90188 xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
90189 R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
90190 D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
90191 oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
90192 9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
90193 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
90194 p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
90195 H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
90196 6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
90197 +PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
90198 HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
90199 F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
90200 8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
90201 /EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
90202 aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
90203 -----END CERTIFICATE-----
90204
90205 TrustCor RootCert CA-1
90206 ======================
90207 -----BEGIN CERTIFICATE-----
90208 MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP
90209 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
90210 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
90211 dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx
90212 MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu
90213 YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe
90214 VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy
90215 dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq
90216 jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4
90217 pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0
90218 JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h
90219 gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw
90220 /Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j
90221 BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
90222 AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5
90223 mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
90224 ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C
90225 qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P
90226 3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk=
90227 -----END CERTIFICATE-----
90228
90229 TrustCor RootCert CA-2
90230 ======================
90231 -----BEGIN CERTIFICATE-----
90232 MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w
90233 DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT
90234 eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0
90235 eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy
90236 MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h
90237 bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
90238 cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0
90239 IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb
90240 ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk
90241 RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1
90242 oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb
90243 XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1
90244 /p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q
90245 jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP
90246 eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg
90247 rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
90248 8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU
90249 2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD
90250 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h
90251 Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp
90252 kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv
90253 2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3
90254 S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw
90255 PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv
90256 DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU
90257 RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE
90258 xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX
90259 RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ
90260 -----END CERTIFICATE-----
90261
90262 TrustCor ECA-1
90263 ==============
90264 -----BEGIN CERTIFICATE-----
90265 MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP
90266 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
90267 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
90268 dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw
90269 N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5
90270 MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y
90271 IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG
90272 SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR
90273 MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23
90274 xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc
90275 p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+
90276 fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj
90277 YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL
90278 f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
90279 AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u
90280 /ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
90281 hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs
90282 J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC
90283 jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g==
90284 -----END CERTIFICATE-----
90285
90286 SSL.com Root Certification Authority RSA
90287 ========================================
90288 -----BEGIN CERTIFICATE-----
90289 MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
90290 BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
90291 MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
90292 MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
90293 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
90294 LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
90295 ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
90296 Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
90297 P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
90298 oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
90299 k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
90300 fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
90301 gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
90302 UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
90303 1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
90304 bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
90305 HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
90306 AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
90307 dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
90308 ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
90309 u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
90310 erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
90311 MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
90312 vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
90313 Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
90314 wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
90315 WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
90316 -----END CERTIFICATE-----
90317
90318 SSL.com Root Certification Authority ECC
90319 ========================================
90320 -----BEGIN CERTIFICATE-----
90321 MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
90322 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
90323 BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
90324 MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
90325 BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
90326 bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
90327 BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
90328 8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
90329 hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
90330 jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
90331 e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
90332 5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
90333 -----END CERTIFICATE-----
90334
90335 SSL.com EV Root Certification Authority RSA R2
90336 ==============================================
90337 -----BEGIN CERTIFICATE-----
90338 MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
90339 DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
90340 MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
90341 MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
90342 DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
90343 VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
90344 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
90345 hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
90346 cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
90347 Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
90348 B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
90349 CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
90350 9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
90351 RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
90352 JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
90353 +qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
90354 HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
90355 qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
90356 ++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
90357 Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
90358 guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
90359 OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
90360 CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
90361 lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
90362 rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
90363 hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
90364 9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
90365 -----END CERTIFICATE-----
90366
90367 SSL.com EV Root Certification Authority ECC
90368 ===========================================
90369 -----BEGIN CERTIFICATE-----
90370 MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
90371 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
90372 BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
90373 MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
90374 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
90375 LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
90376 BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
90377 3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
90378 BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
90379 5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
90380 N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
90381 m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
90382 -----END CERTIFICATE-----
90383
90384 GlobalSign Root CA - R6
90385 =======================
90386 -----BEGIN CERTIFICATE-----
90387 MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
90388 R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
90389 b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
90390 YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
90391 U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
90392 grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
90393 3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
90394 vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
90395 PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
90396 azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
90397 WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
90398 CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
90399 0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
90400 b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
90401 AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
90402 HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
90403 nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
90404 lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
90405 BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
90406 Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
90407 3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
90408 0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
90409 uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
90410 oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
90411 JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
90412 -----END CERTIFICATE-----
90413
90414 OISTE WISeKey Global Root GC CA
90415 ===============================
90416 -----BEGIN CERTIFICATE-----
90417 MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
90418 SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
90419 MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
90420 Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
90421 ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
90422 bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
90423 VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
90424 NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
90425 BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
90426 AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
90427 AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
90428 -----END CERTIFICATE-----
90429
90430 GTS Root R1
90431 ===========
90432 -----BEGIN CERTIFICATE-----
90433 MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
90434 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
90435 b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
90436 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi
90437 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx
90438 9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r
90439 aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW
90440 r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM
90441 LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly
90442 4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr
90443 06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
90444 wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om
90445 3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu
90446 JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
90447 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM
90448 BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
90449 d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv
90450 fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm
90451 ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b
90452 gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq
90453 4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr
90454 tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo
90455 pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0
90456 sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql
90457 CFF1pkgl
90458 -----END CERTIFICATE-----
90459
90460 GTS Root R2
90461 ===========
90462 -----BEGIN CERTIFICATE-----
90463 MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
90464 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
90465 b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
90466 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi
90467 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk
90468 k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo
90469 7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI
90470 m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm
90471 dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu
90472 ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz
90473 cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
90474 Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl
90475 aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy
90476 5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
90477 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM
90478 BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
90479 vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ
90480 +YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw
90481 c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da
90482 WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r
90483 n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu
90484 Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ
90485 7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs
90486 gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld
90487 o/DUhgkC
90488 -----END CERTIFICATE-----
90489
90490 GTS Root R3
90491 ===========
90492 -----BEGIN CERTIFICATE-----
90493 MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
90494 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
90495 UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
90496 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq
90497 hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU
90498 Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej
90499 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP
90500 0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0
90501 glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa
90502 KaqW04MjyaR7YbPMAuhd
90503 -----END CERTIFICATE-----
90504
90505 GTS Root R4
90506 ===========
90507 -----BEGIN CERTIFICATE-----
90508 MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
90509 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
90510 UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
90511 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq
90512 hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa
90513 6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj
90514 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV
90515 2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI
90516 N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x
90517 zPKwTdb+mciUqXWi4w==
90518 -----END CERTIFICATE-----
90519
90520 UCA Global G2 Root
90521 ==================
90522 -----BEGIN CERTIFICATE-----
90523 MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG
90524 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x
90525 NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU
90526 cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
90527 MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT
90528 oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV
90529 8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS
90530 h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o
90531 LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/
90532 R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe
90533 KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa
90534 4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc
90535 OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97
90536 8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
90537 BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo
90538 5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
90539 1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A
90540 Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9
90541 yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX
90542 c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo
90543 jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk
90544 bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x
90545 ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn
90546 RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A==
90547 -----END CERTIFICATE-----
90548
90549 UCA Extended Validation Root
90550 ============================
90551 -----BEGIN CERTIFICATE-----
90552 MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
90553 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u
90554 IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G
90555 A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi
90556 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs
90557 iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF
90558 Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu
90559 eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR
90560 59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH
90561 0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR
90562 el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv
90563 B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth
90564 WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS
90565 NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS
90566 3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL
90567 BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
90568 ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM
90569 aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4
90570 dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb
90571 +7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW
90572 F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi
90573 GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc
90574 GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi
90575 djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr
90576 dhh2n1ax
90577 -----END CERTIFICATE-----
90578
90579 Certigna Root CA
90580 ================
90581 -----BEGIN CERTIFICATE-----
90582 MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE
90583 BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ
90584 MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda
90585 MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz
90586 MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
90587 DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX
90588 stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz
90589 KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8
90590 JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16
90591 XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq
90592 4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej
90593 wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ
90594 lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI
90595 jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/
90596 /TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
90597 HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
90598 1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy
90599 dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h
90600 LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl
90601 cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt
90602 OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP
90603 TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq
90604 7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3
90605 4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd
90606 8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS
90607 6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY
90608 tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
90609 aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
90610 E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
90611 -----END CERTIFICATE-----
90612
90613 emSign Root CA - G1
90614 ===================
90615 -----BEGIN CERTIFICATE-----
90616 MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
90617 MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
90618 ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
90619 ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
90620 aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
90621 IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
90622 LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
90623 cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
90624 DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
90625 6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
90626 hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
90627 MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
90628 vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
90629 NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
90630 +Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
90631 U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
90632 iN66zB+Afko=
90633 -----END CERTIFICATE-----
90634
90635 emSign ECC Root CA - G3
90636 =======================
90637 -----BEGIN CERTIFICATE-----
90638 MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
90639 A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
90640 MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
90641 MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
90642 ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
90643 RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
90644 58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
90645 MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
90646 AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
90647 CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
90648 jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
90649 -----END CERTIFICATE-----
90650
90651 emSign Root CA - C1
90652 ===================
90653 -----BEGIN CERTIFICATE-----
90654 MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
90655 EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
90656 Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
90657 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
90658 ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
90659 ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
90660 Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
90661 OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
90662 I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
90663 lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
90664 XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
90665 ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
90666 /6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
90667 NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
90668 wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
90669 BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
90670 -----END CERTIFICATE-----
90671
90672 emSign ECC Root CA - C3
90673 =======================
90674 -----BEGIN CERTIFICATE-----
90675 MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
90676 A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
90677 Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
90678 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
90679 ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
90680 6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
90681 SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
90682 B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
90683 MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
90684 ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
90685 -----END CERTIFICATE-----
90686
90687 Hongkong Post Root CA 3
90688 =======================
90689 -----BEGIN CERTIFICATE-----
90690 MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
90691 A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
90692 Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
90693 MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
90694 bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
90695 SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
90696 iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
90697 jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
90698 5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
90699 sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
90700 0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
90701 JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
90702 y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
90703 +bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
90704 xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
90705 AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
90706 i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
90707 AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
90708 W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
90709 y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
90710 +BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
90711 eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
90712 9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
90713 nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
90714 hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
90715 60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
90716 dBb9HxEGmpv0
90717 -----END CERTIFICATE-----
90718
90719 Entrust Root Certification Authority - G4
90720 =========================================
90721 -----BEGIN CERTIFICATE-----
90722 MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV
90723 BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu
90724 bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1
90725 dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
90726 dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT
90727 AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
90728 L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv
90729 cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv
90730 cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D
90731 umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV
90732 3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds
90733 8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ
90734 e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7
90735 ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X
90736 xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV
90737 7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
90738 dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW
90739 Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T
90740 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n
90741 MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q
90742 jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht
90743 7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK
90744 YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt
90745 jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+
90746 m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW
90747 RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA
90748 JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G
90749 +TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT
90750 kcpG2om3PVODLAgfi49T3f+sHw==
90751 -----END CERTIFICATE-----
90752 <?php
90753
90754 if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
90755     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
90756 }
90757
90758 setlocale(LC_ALL, 'C');
90759 require __DIR__.'/../src/bootstrap.php';
90760
90761 use Composer\Console\Application;
90762 use Composer\XdebugHandler\XdebugHandler;
90763
90764 error_reporting(-1);
90765
90766 // Restart without xdebug
90767 $xdebug = new XdebugHandler('Composer', '--ansi');
90768 $xdebug->check();
90769 unset($xdebug);
90770
90771 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '4.0', '>=')) {
90772     echo 'HHVM 4.0 has dropped support for Composer, please use PHP instead. Aborting.'.PHP_EOL;
90773     exit(1);
90774 }
90775
90776 if (function_exists('ini_set')) {
90777     @ini_set('display_errors', 1);
90778
90779     $memoryInBytes = function ($value) {
90780         $unit = strtolower(substr($value, -1, 1));
90781         $value = (int) $value;
90782         switch($unit) {
90783             case 'g':
90784                 $value *= 1024;
90785                 // no break (cumulative multiplier)
90786             case 'm':
90787                 $value *= 1024;
90788                 // no break (cumulative multiplier)
90789             case 'k':
90790                 $value *= 1024;
90791         }
90792
90793         return $value;
90794     };
90795
90796     $memoryLimit = trim(ini_get('memory_limit'));
90797     // Increase memory_limit if it is lower than 1.5GB
90798     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
90799         @ini_set('memory_limit', '1536M');
90800     }
90801     // Set user defined memory limit
90802     if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
90803         @ini_set('memory_limit', $memoryLimit);
90804     }
90805     unset($memoryInBytes, $memoryLimit);
90806 }
90807
90808 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
90809
90810 // run the command application
90811 $application = new Application();
90812 $application->run();
90813
90814 Copyright (c) Nils Adermann, Jordi Boggiano
90815
90816 Permission is hereby granted, free of charge, to any person obtaining a copy
90817 of this software and associated documentation files (the "Software"), to deal
90818 in the Software without restriction, including without limitation the rights
90819 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
90820 copies of the Software, and to permit persons to whom the Software is furnished
90821 to do so, subject to the following conditions:
90822
90823 The above copyright notice and this permission notice shall be included in all
90824 copies or substantial portions of the Software.
90825
90826 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
90827 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
90828 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
90829 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
90830 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90831 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
90832 THE SOFTWARE.
90833
90834 \ 3hQáDâaâ\96
90835 Ín\ 5ñS\13h\b\ 2\0\0\0GBMB