]> git.mxchange.org Git - friendica.git/blob - bin/composer.phar
Merge pull request #7988 from friendica/MrPetovan-notice
[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\0A[¼]üc\0\0ÊÇv`¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php¨\12\0\0A[¼]¨\12\0\0   \99f\11\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpç\13\0\0A[¼]ç\13\0\0³\9bî\1d\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpØ\ 2\0\0A[¼]Ø\ 2\0\0ö÷;\87\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.php\9e\14\0\0A[¼]\9e\14\0\0\19lG\ f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÜ\v\0\0A[¼]Ü\v\0\0\1a\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpñ\18\0\0A[¼]ñ\18\0\0XgFð¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Command/CheckPlatformReqsCommand.php        \ f\0\0A[¼] \ f\0\0*Þ¯T¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.phpµ\ 5\0\0A[¼]µ\ 5\0\0vÿy\83\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\15M\0\0A[¼]\15M\0\0Û=\ 4\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.phpß5\0\0A[¼]ß5\0\0ü\90_÷¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.phpø\ 2\0\0A[¼]ø\ 2\0\0ªe\11á¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpåM\0\0A[¼]åM\0\0\13hÇÔ¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.phpL\f\0\0A[¼]L\f\0\0°E²ù¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpï\a\0\0A[¼]ï\a\0\0Xr\9c¾¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpz      \0\0A[¼]z \0\0³çå?¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.php\ 4\ f\0\0A[¼]\ 4\ f\0\0qLB\8e\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.php¯Q\0\0A[¼]¯Q\0\0\9cÁ    ´¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpT\14\0\0A[¼]T\14\0\0Þùõ\9b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php\82\ e\0\0A[¼]\82\ e\0\0±s'\ e\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php\ f\f\0\0A[¼]\ f\f\0\0ا\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.php\12\ 3\0\0A[¼]\12\ 3\0\0_¤éS¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.phpá\18\0\0A[¼]á\18\0\0½í\9d\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php"'\0\0A[¼]"'\0\0ü¤Ø²¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php=\ f\0\0A[¼]=\ f\0\0rºmܶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.php¯\ 5\0\0A[¼]¯\ 5\0\0?=\10Ѷ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpU   \0\0A[¼]U \0\0\85ß\ f\ f\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.php;3\0\0A[¼];3\0\0\98\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.phphq\0\0A[¼]hq\0\0+a_\11\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php\96\15\0\0A[¼]\96\15\0\0ù\1cjض\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.phpò\r\0\0A[¼]ò\r\0\0íA\0Ƕ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.phpñ#\0\0A[¼]ñ#\0\0p\F\19\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.php\80\14\0\0A[¼]\80\14\0\0ÍÃ\90î¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpN\v\0\0A[¼]N\v\0\0\ 3ç¶\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phph$\0\0A[¼]h$\0\0»\89\1dÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0A[¼]\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php²\13\0\0A[¼]²\13\0\0QiÃb¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.phpý6\0\0A[¼]ý6\0\0ò|-\ f\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0A[¼]3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.php'\10\0\0A[¼]'\10\0\0¹Ô\8e¼¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0A[¼]\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.phpµ\ 3\0\0A[¼]µ\ 3\0\0\19᫤¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0A[¼]C\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0A[¼]÷\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0A[¼]ý\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0A[¼]Ó\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0A[¼]¹\ 1\0\0&¢e
28\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0A[¼]I\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0A[¼]h\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0A[¼]­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php¯"\0\0A[¼]¯"\0\0\r ¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.phpú\17\0\0A[¼]ú\17\0\0\16]D5¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0A[¼]\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php?\19\0\0A[¼]?\19\0\0¬\91\9cü¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php\18\ 5\0\0A[¼]\18\ 5\0\0tZÅɶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
29 \0\0A[¼]ª
30 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpÊ\1e\0\0A[¼]Ê\1e\0\0D¦õZ¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\11\ 6\0\0A[¼]\11\ 6\0\0\9bCü$¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0A[¼]i\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0A[¼]á\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.php\ 5\ 4\0\0A[¼]\ 5\ 4\0\0\8fGd7¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php\9d:\0\0A[¼]\9d:\0\0æ¯Ép¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\99\ 1\0\0A[¼]\99\ 1\0\0X\12g6¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpô\a\0\0A[¼]ô\a\0\0×|Ŧ¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.php×\13\0\0A[¼]×\13\0\0Vmì\9f\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.phpÆ      \0\0A[¼]Æ \0\0G s0¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0A[¼]Ì\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.php`\15\0\0A[¼]`\15\0\0#ÏX\14\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0A[¼]Ê\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0A[¼]Ñ\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.phpG\1c\0\0A[¼]G\1c\0\0ä\11Oж\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
31 \ 1\0\0A[¼]
32 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php\82\v\0\0A[¼]\82\v\0\0Ü\81Ii¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php³6\0\0A[¼]³6\0\0¦Ü(9¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0A[¼]ó\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php\94\b\0\0A[¼]\94\b\0\0ßis̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpé\14\0\0A[¼]é\14\0\0$²FQ¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0A[¼]u\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.php\9e\a\0\0A[¼]\9e\a\0\0Öüñ9¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0A[¼]å\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0A[¼]\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpG\14\0\0A[¼]G\14\0\0M#j\1d\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0A[¼]ã\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0A[¼]=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0A[¼]Ô\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php¡\16\0\0A[¼]¡\16\0\0(   à>¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0A[¼]§\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.phpk\15\0\0A[¼]k\15\0\0Òo\94ζ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0A[¼] \ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.php$4\0\0A[¼]$4\0\0\ 1x\8b\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0A[¼]©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0A[¼]v\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0A[¼]f\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.php_=\0\0A[¼]_=\0\0x"\10Ŷ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.phpÝ\10\0\0A[¼]Ý\10\0\0\7f¢âº¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php¾\ 6\0\0A[¼]¾\ 6\0\0X~d\1e\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php7\17\0\0A[¼]7\17\0\0¥\10<ȶ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0A[¼]ì\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0A[¼]À\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.phpÚ\9e\0\0A[¼]Ú\9e\0\0¾g«\89\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php
33 \12\0\0A[¼]
34 \12\0\0t¤{ø¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0A[¼]Ë\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0A[¼]-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0A[¼]\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0A[¼]Þ\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0A[¼]ã\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php%\14\0\0A[¼]%\14\0\0\f»\8f̶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.phpÊ\a\0\0A[¼]Ê\a\0\0Ùti·¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0A[¼]+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0A[¼]e\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0A[¼]¸\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpø\f\0\0A[¼]ø\f\0\0\95\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0A[¼]¢\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\8b\ 6\0\0A[¼]\8b\ 6\0\0\ fÒX8¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0A[¼]\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php:\a\0\0A[¼]:\a\0\0\82´UV¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.php[\14\0\0A[¼][\14\0\0°\90Ë\99\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.phpb\ 6\0\0A[¼]b\ 6\0\0\12ÝN\9a\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.phpÀ3\0\0A[¼]À3\0\0\90\99 \7f\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0A[¼]\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php§\17\0\0A[¼]§\17\0\0Õ\94R\99\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php      \ 2\0\0A[¼] \ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0A[¼]Þ\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.phpÝ\f\0\0A[¼]Ý\f\0\0í<´B¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0A[¼]\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0A[¼]\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0A[¼]\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpr\ 3\0\0A[¼]r\ 3\0\03\91Mh¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\v\ 5\0\0A[¼]\v\ 5\0\0\r\95¦S¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php?\ 6\0\0A[¼]?\ 6\0\0®\97      u¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php½\ 4\0\0A[¼]½\ 4\0\0\82¨¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php\11\ e\0\0A[¼]\11\ e\0\0D|\9fȶ\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Comparer/Comparer.phpR\b\0\0A[¼]R\b\0\0Ïسî¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0A[¼]ü\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0A[¼]õ\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpW\f\0\0A[¼]W\f\0\0¿éÁ¦¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0A[¼]\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0A[¼]\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0A[¼]d\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0A[¼]\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0A[¼]i\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0A[¼]X\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.phpN\1e\0\0A[¼]N\1e\0\0â\ 3Q¬¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0A[¼]E\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0A[¼]ù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0A[¼]²\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.phpó\19\0\0A[¼]ó\19\0\0l\94.ض\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.php(>\0\0A[¼](>\0\0\ 6\84´P¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php¥!\0\0A[¼]¥!\0\0/=xö¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0A[¼]É\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php\\b\0\0A[¼]\\b\0\0xåp¨¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f        \0\0A[¼]\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0A[¼]\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0A[¼]¹\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpÏ\1d\0\0A[¼]Ï\1d\0\0ÌÂß\ 4\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.php¥\ 5\0\0A[¼]¥\ 5\0\0ô´\16à¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0A[¼]K\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0A[¼]W\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0A[¼]\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0A[¼]\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0A[¼]â\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpö\0\0\0A[¼]ö\0\0\0á1=z¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0A[¼]ô\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.phpª$\0\0A[¼]ª$\0\0m\89\83ä¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Plugin/PreCommandRunEvent.phpõ\ 1\0\0A[¼]õ\ 1\0\0:ðd\1e\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0A[¼]`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0A[¼]\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0A[¼]\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.phpí\b\0\0A[¼]í\b\0\0q9OS¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php\8a\ f\0\0A[¼]\8a\ f\0\0\13äÝ÷¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php\87T\0\0A[¼]\87T\0\0\8e÷\bƶ\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0A[¼];\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0A[¼]\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.phpp\ 5\0\0A[¼]p\ 5\0\0#\18ù\7f\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0A[¼]£\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0A[¼]£\0\0\0V
35 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0A[¼]\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0A[¼]n\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0A[¼]j\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.phpõ\v\0\0A[¼]õ\v\0\0ì[r=¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0A[¼]I\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0A[¼]Ä\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0A[¼]í\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.php®        \0\0A[¼]® \0\0\99ÖÛú¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0A[¼]& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0A[¼]q\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0A[¼]q\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0A[¼]\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0A[¼]°\ 3\0\0\9f\r¸\f\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ReleaseInfo.php\92\ 1\0\0A[¼]\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0A[¼]ª\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.phpå\1f\0\0A[¼]å\1f\0\0»G÷å¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php`\12\0\0A[¼]`\12\0\0K¾du¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0A[¼]Û\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php2
36 \0\0A[¼]2
37 \0\0á\855#¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0A[¼]o\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.php\95 \0\0A[¼]\95 \0\0$©Rç¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php³\13\0\0A[¼]³\13\0\0ÐCk\ 3\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpë\ 5\0\0A[¼]ë\ 5\0\0\9c´½X¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.phpu\12\0\0A[¼]u\12\0\0}Ýs!¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.php})\0\0A[¼]})\0\0ê¦x®¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.php]%\0\0A[¼]]%\0\0sÇø\r\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpå\ 5\0\0A[¼]å\ 5\0\0@)\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpB\12\0\0A[¼]B\12\0\0»\7f\83î¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.phpù     \0\0A[¼]ù \0\0&½tÙ¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php¤\1c\0\0A[¼]¤\1c\0\0\1e\11\1f\f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
38 \0\0A[¼]æ
39 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0A[¼]÷\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.phpÙ*\0\0A[¼]Ù*\0\0~Á£f¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/VersionCacheInterface.php\94\0\0\0A[¼]\94\0\0\0A?Rï¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0A[¼]\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0A[¼]\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0A[¼]W\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpº\ 4\0\0A[¼]º\ 4\0\0ò\9d»¤¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0A[¼]\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0A[¼]P\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0A[¼]\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0A[¼]ì\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0A[¼]Ë\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php*\15\0\0A[¼]*\15\0\0,L\9a\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0A[¼]±\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.php÷\13\0\0A[¼]÷\13\0\0v\95Í\ 4\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php»\ 4\0\0A[¼]»\ 4\0\0O\9brk¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.phpr/\0\0A[¼]r/\0\0\eÒ^j¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.phpí-\0\0A[¼]í-\0\0\11\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.php|\r\0\0A[¼]|\r\0\0`0tü¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php¬\r\0\0A[¼]¬\r\0\0B3\vë¶\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Util/Hg.php¾\a\0\0A[¼]¾\a\0\0\f\9d\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.phph\ 2\0\0A[¼]h\ 2\0\0;F\b\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0A[¼]¾\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Util/PackageSorter.phpÞ\ 5\0\0A[¼]Þ\ 5\0\0ê×ìY¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php¸2\0\0A[¼]¸2\0\0Ás&}¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0A[¼]ü\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.phpl\f\0\0A[¼]l\f\0\0m7_\9a\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.phpøn\0\0A[¼]øn\0\0?\9b\1a\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpé\ 2\0\0A[¼]é\ 2\0\0\93Vjf¶\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0A[¼]\ 3\ 1\0\0¾7
40 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.php\ 6\10\0\0A[¼]\ 6\10\0\0\85ù¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php,\14\0\0A[¼],\14\0\0Ì\r\9eĶ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpL
41 \0\0A[¼]L
42 \0\0"\fi\1e\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Url.php£\a\0\0A[¼]£\a\0\03\9cÉܶ\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Zip.php´\ 5\0\0A[¼]´\ 5\0\0°\ 4³¶¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.phpð\ 1\0\0A[¼]ð\ 1\0\0zÓf~¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0A[¼]¹\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.php\934\0\0A[¼]\934\0\0²z\8d\96\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0A[¼]ð\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.json\e\98\0\0A[¼]\e\98\0\0\1cÖý ¶\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.json%
43 \0\0A[¼]%
44 \0\0ïBð\a\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.jsonÓ\98\0\0A[¼]Ó\98\0\0Id¤÷¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Resources/bin/hiddeninput.exe\0$\0\0A[¼]\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php=X\0\0A[¼]=X\0\0\8f S\92\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.phpî"\0\0A[¼]î"\0\0x°jÕ¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpØ\a\0\0A[¼]Ø\a\0\0¦Ú-:¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0A[¼]Z\b\0\0»w\ 4\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpé\0\0\0A[¼]é\0\0\0RÛÔe¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpÐ\b\0\0A[¼]Ð\b\0\0\99\8e5°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\8f\a\0\0A[¼]\8f\a\0\0¿N\ f\95\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0A[¼]ü\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpÜ\r\0\0A[¼]Ü\r\0\0\9dɶ\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¶\ e\0\0A[¼]¶\ e\0\0·Ô;ݶ\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php¼\1e\0\0A[¼]¼\1e\0\0òç\ 6\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ 1\1c\0\0A[¼]\ 1\1c\0\0\7fb{<¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php°\ 1\0\0A[¼]°\ 1\0\0\a!\0ȶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0A[¼]Å\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0A[¼]\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0A[¼]z\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0A[¼]Ô\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0A[¼]f\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0A[¼]¦\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0A[¼]¦\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0A[¼]\92\0\0\0ÍO\e¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/console/Exception/RuntimeException.php\96\0\0\0A[¼]\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php6\ e\0\0A[¼]6\ e\0\0?=¨\ 4\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0A[¼]\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpF\10\0\0A[¼]F\10\0\0\1d𦴶\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\84\ 1\0\0A[¼]\84\ 1\0\0÷½\10\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.php@\ 5\0\0A[¼]@\ 5\0\0G¨ýU¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpy\b\0\0A[¼]y\b\0\0Ì8Æж\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpw\ 5\0\0A[¼]w\ 5\0\0\ 1\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.php\ 3\1f\0\0A[¼]\ 3\1f\0\0¹ÜÃ_¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpd\ 4\0\0A[¼]d\ 4\0\0§×,¸¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php«\a\0\0A[¼]«\a\0\0!\90§\97\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpå\0\0\0A[¼]å\0\0\0\1f\8a \18\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÊ\a\0\0A[¼]Ê\a\0\0áÏW"¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0A[¼]c\ 1\0\0\ 6Ìø\83\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÓ      \0\0A[¼]Ó \0\0©w\82\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phpl%\0\0A[¼]l%\0\0 díÛ¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php]\e\0\0A[¼]]\e\0\0ù»\89\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpN\14\0\0A[¼]N\14\0\0ÿ§³l¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.phpl\1d\0\0A[¼]l\1d\0\0Nt\bó¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.php\96
45 \0\0A[¼]\96
46 \0\0-\fØ\1a\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.phpÄ*\0\0A[¼]Ä*\0\0¾\99ØT¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\81\ 3\0\0A[¼]\81\ 3\0\0å\16V^¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\ e\f\0\0A[¼]\ e\f\0\0\9b\99\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÊ\0\0\0A[¼]Ê\0\0\0az\1f\1c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php 
47 \0\0A[¼] 
48 \0\0_ÍI"¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\ f\16\0\0A[¼]\ f\16\0\0×ö\86\9b\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php)\v\0\0A[¼])\v\0\0¥Ñ\ 6\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.php£\v\0\0A[¼]£\v\0\0\13f¡?¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\12\ 6\0\0A[¼]\12\ 6\0\0D\r£\ 6\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\98\0\0\0A[¼]\98\0\0\0­\ fO°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\86\19\0\0A[¼]\86\19\0\0¤U)¤¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php£\ 3\0\0A[¼]£\ 3\0\0ÆB\8c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\14\f\0\0A[¼]\14\f\0\0\¢Ü=¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\9a\ 6\0\0A[¼]\9a\ 6\0\0\9eµ\rè¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0A[¼])\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php0    \0\0A[¼]0 \0\0\85\8d\r¸¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.php_\ 1\0\0A[¼]_\ 1\0\0\8b >P¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.php±\a\0\0A[¼]±\a\0\0nì!f¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpà\0\0\0A[¼]à\0\0\0\87\86Æʶ\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0A[¼]Ï\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\98  \0\0A[¼]\98 \0\00p\ 4\b\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\17\ 3\0\0A[¼]\17\ 3\0\0\0ì\ 6\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.php\9d\ 6\0\0A[¼]\9d\ 6\0\0Ä\92Oç¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpx
49 \0\0A[¼]x
50 \0\0W\16\80\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpè\ 2\0\0A[¼]è\ 2\0\0/\1dÔ\8f\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.phpΠ    \0\0A[¼]Π\0\0lF\ f\10\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpæ\ f\0\0A[¼]æ\ f\0\0¼XÒA¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php\\ 5\0\0A[¼]\\ 5\0\0wפ\ 4\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÏ\ 3\0\0A[¼]Ï\ 3\0\0&nÅѶ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.phpä\1f\0\0A[¼]ä\1f\0\0­å (¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÏ\ 5\0\0A[¼]Ï\ 5\0\0s\9e9i¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.phpª\ 6\0\0A[¼]ª\ 6\0\0¬K\f\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0A[¼]t\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.php,\ 3\0\0A[¼],\ 3\0\0Ë~\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.phpµ\1d\0\0A[¼]µ\1d\0\01rEÓ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\1dH\0\0A[¼]\1dH\0\0¹:D#¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\96\ 1\0\0A[¼]\96\ 1\0\0i\89æô¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0A[¼]\98\ 1\0\0-
51 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0A[¼]\ 2\ 1\0\0®+Ãê¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.php\ e\a\0\0A[¼]\ e\a\0\0\e\17\99Ķ\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpW\ 2\0\0A[¼]W\ 2\0\0?àèK¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php¼\16\0\0A[¼]¼\16\0\0\11\15\f׶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0A[¼]~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\9a\ 1\0\0A[¼]\9a\ 1\0\0\81ñJÀ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\98\ 1\0\0A[¼]\98\ 1\0\0nöêض\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php)3\0\0A[¼])3\0\0\81h5=¶\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.phpA\12\0\0A[¼]A\12\0\0Ϥ¹l¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0A[¼]\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpx\b\0\0A[¼]x\b\0\0~ò"\7f\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpO\ 5\0\0A[¼]O\ 5\0\0\8d\9e¦*¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0A[¼])\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0A[¼]i\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0A[¼]¼\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0A[¼]\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0A[¼]¦\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.phpc4\0\0A[¼]c4\0\0\8b×@þ¶\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0A[¼])\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.phpö\ 5\0\0A[¼]ö\ 5\0\0\9fZµ1¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0A[¼]\\v\0\0h\19\88\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\8f\19\0\0A[¼]\8f\19\0\0HC\80\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php\9b\ 3\0\0A[¼]\9b\ 3\0\0M\aþ\e\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php3\a\0\0A[¼]3\a\0\075$·¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0A[¼]\15\a\0\0\9f\1c`]¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0A[¼]ô\a\0\0Þdè;¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8d\ 3\0\0A[¼]\8d\ 3\0\0¾ü\9cµ¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php#\ 3\0\0A[¼]#\ 3\0\0\16°\1fζ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php|\ 3\0\0A[¼]|\ 3\0\0ITÇͶ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0A[¼]\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¬\ 2\0\0A[¼]¬\ 2\0\0w\1e\18\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0A[¼]\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0A[¼])\ 1\0\0x\1f§e¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpº\ 2\0\0A[¼]º\ 2\0\0\98þ\15\98\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0A[¼]\a\ 6\0\0i¥:Ŷ\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpf\ 4\0\0A[¼]f\ 4\0\0DÞcj¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 4\ f\0\0A[¼]\ 4\ f\0\0ü(Ã϶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0A[¼]Í\ 1\0\0\p4\86\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.phpc.\0\0A[¼]c.\0\0:\885g¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpL\ 5\0\0A[¼]L\ 5\0\0jÍ9׶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php]\ 2\0\0A[¼]]\ 2\0\0ÎoÅƶ\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpx\ 2\0\0A[¼]x\ 2\0\0\ fô\ 3\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpî\ 1\0\0A[¼]î\ 1\0\0üÍ\9d\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpí\ 5\0\0A[¼]í\ 5\0\0n\ 5õH¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php#\ 6\0\0A[¼]#\ 6\0\0G?T½¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpZ\ 2\0\0A[¼]Z\ 2\0\0(\1a&ø¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0A[¼]5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0A[¼]r\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0A[¼]Ã\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php-\ 5\0\0A[¼]-\ 5\0\0ºÎÒ_¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÐ\ 1\0\0A[¼]Ð\ 1\0\0\12\82\b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\15   \0\0A[¼]\15 \0\0ë]í»¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpe\ 2\0\0A[¼]e\ 2\0\0\9f\92áé¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php+\ 6\0\0A[¼]+\ 6\0\0õÝË ¶\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0A[¼])\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.php>\v\0\0A[¼]>\v\0\0_~u\f\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpr\ 4\0\0A[¼]r\ 4\0\0þ\1dpN¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.php\ 6\ 3\0\0A[¼]\ 6\ 3\0\0þ\0íù¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/polyfill-ctype/Ctype.phpH   \0\0A[¼]H \0\0³\9dÕݶ\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/polyfill-ctype/LICENSE)\ 4\0\0A[¼])\ 4\0\0´`e0¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/polyfill-ctype/bootstrap.phpI\ 3\0\0A[¼]I\ 3\0\0\8fD!e¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0A[¼])\ 4\0\0\1f\93\ª¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.phpõE\0\0A[¼]õE\0\0\17K"ܶ\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php÷@\0\0A[¼]÷@\0\0õ\10\9eض\ 1\0\0\0\0\0\0F\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpã\17\0\0A[¼]ã\17\0\0öy_\95\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpfA\0\0A[¼]fA\0\0Úf\94߶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php\82\11\0\0A[¼]\82\11\0\0À\91 \8a\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0A[¼]f\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0A[¼]¨\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0A[¼]\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0A[¼]x\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0A[¼]\1f\ 4\0\0\7fï\ e«¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0A[¼]\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9d\ 4\0\0A[¼]\9d\ 4\0\0ûus\80\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0A[¼])\ 4\0\0NUN½¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpÏ\ 4\0\0A[¼]Ï\ 4\0\0Î%h\1c\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpü\ 3\0\0A[¼]ü\ 3\0\0\87jûü¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php½\a\0\0A[¼]½\a\0\0æ\18\86\ 1\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0A[¼]D\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.php>\b\0\0A[¼]>\b\0\0ª\95ir¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.phpp\f\0\0A[¼]p\f\0\0âU~ɶ\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php·R\0\0A[¼]·R\0\0\8a\18`Õ¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpâ
52 \0\0A[¼]â
53 \0\0\86\1eM¶¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpQ\ 6\0\0A[¼]Q\ 6\0\0b-$m¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0A[¼]"\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0A[¼]*\ 1\0\0\19\95pñ¶\ 1\0\0\0\0\0\05\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php82\0\0A[¼]82\0\0ªÃZt¶\ 1\0\0\0\0\0\00\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php\ 6\ f\0\0A[¼]\ 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\0A[¼]\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\0A[¼]>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0A[¼] \ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0A[¼]ñ\ 1\0\0f\e\12\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php¡      \0\0A[¼]¡ \0\0\86wÌl¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php\8f
54 \0\0A[¼]\8f
55 \0\0ÍèÓ¯¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php§\r\0\0A[¼]§\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\0A[¼]¼\ 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\0A[¼]]\ 3\0\0V\8eU<¶\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.phpã\f\0\0A[¼]ã\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\0A[¼]\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\0A[¼]\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\0A[¼]Ã\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php0 \0\0A[¼]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\0A[¼]\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\0A[¼]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\0A[¼]\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\0A[¼]\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\0A[¼]&\ f\0\04\98©T¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.phpa"\0\0A[¼]a"\0\0\8fMÙë¶\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0A[¼]è\ 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\0A[¼]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\0A[¼]\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\0A[¼]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\0A[¼]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\0A[¼]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\0A[¼]w\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0A[¼]Þ\ 2\0\0\r
56\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0A[¼]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\0A[¼]\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\0A[¼]\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\0A[¼]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\0A[¼]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\0A[¼]þ\ 5\0\0M\8f\84õ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php \ 2\0\0A[¼] \ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\9c\r\0\0A[¼]\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\0A[¼]\ 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\0A[¼]á\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\0A[¼]¥\ 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\0A[¼]%\ 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\0A[¼],\ 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\0A[¼]®\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\0A[¼]\ 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\0A[¼]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\0A[¼]\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\0A[¼]\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpv\ 5\0\0A[¼]v\ 5\0\0õÍ\ 5\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0A[¼]\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpH\14\0\0A[¼]H\14\0\0Í\89T\ 4\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0A[¼]\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0A[¼]\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.phpî\ 2\0\0A[¼]î\ 2\0\0Õ­w-¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.phpª\f\0\0A[¼]ª\f\0\0ÇO7²¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0A[¼]ß\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpé\ 1\0\0A[¼]é\ 1\0\0!-Ø\99\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php1\ 5\0\0A[¼]1\ 5\0\0í xU¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.phpv\ 6\0\0A[¼]v\ 6\0\0\8b×È\9b\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¯*\0\0A[¼]¯*\0\0Z\eÒ\93\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0A[¼]\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php±\1c\0\0A[¼]±\1c\0\0à\v\11\93\ 1\0\0\0\0\0\0&\0\0\0vendor/composer/xdebug-handler/LICENSE)\ 4\0\0A[¼])\ 4\0\0#Ô;^¶\ 1\0\0\0\0\0\00\0\0\0vendor/composer/xdebug-handler/src/PhpConfig.php´\ 2\0\0A[¼]´\ 2\0\0*D\92\0\ 1\0\0\0\0\0\0.\0\0\0vendor/composer/xdebug-handler/src/Process.php\ 2   \0\0A[¼]\ 2 \0\0`çîȶ\ 1\0\0\0\0\0\0-\0\0\0vendor/composer/xdebug-handler/src/Status.php\ f
57 \0\0A[¼]\ f
58 \0\0²\17\82²¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/xdebug-handler/src/XdebugHandler.php\13!\0\0A[¼]\13!\0\02|¿C¶\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0A[¼]=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0A[¼];\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0A[¼]`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0A[¼]û\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0A[¼]|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0A[¼]§\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÈ\ 2\0\0A[¼]È\ 2\0\0\9a\1fx\1d\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpk\ 4\0\0A[¼]k\ 4\0\0£}\89\92\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php \0\0\0A[¼] \0\0\0ÆDi¯¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.phpj\r\0\0A[¼]j\r\0\0Nÿ\11\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/Test/TestLogger.php<\b\0\0A[¼]<\b\0\0þ(åI¶\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0A[¼]\82\0\0\0Ä-ë%¶\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0A[¼]d\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php÷\ 4\0\0A[¼]÷\ 4\0\0Å*\9a\16\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0A[¼]d\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.php\1f\ 1\0\0A[¼]\1f\ 1\0\0¥\0 ®¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0A[¼]I\a\0\0È)ü\83\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php§
59 \0\0A[¼]§
60 \0\0q\b\96Ù¶\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php¨\18\0\0A[¼]¨\18\0\0xää`¶\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pemUk\ 3\0A[¼]Uk\ 3\0\94J̸¶\ 1\0\0\0\0\0\0\f\0\0\0bin/composerÊ\ 6\0\0A[¼]Ê\ 6\0\0ÿêP\17\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0A[¼].\ 4\0\0 Õ\b\ 3\ 1\0\0\0\0\0\0<?php
61
62
63
64
65
66
67
68
69
70
71
72 namespace Composer\Autoload;
73
74 use Composer\Config;
75 use Composer\EventDispatcher\EventDispatcher;
76 use Composer\Installer\InstallationManager;
77 use Composer\IO\IOInterface;
78 use Composer\Package\AliasPackage;
79 use Composer\Package\PackageInterface;
80 use Composer\Repository\InstalledRepositoryInterface;
81 use Composer\Util\Filesystem;
82 use Composer\Script\ScriptEvents;
83 use Composer\Util\PackageSorter;
84
85
86
87
88
89 class AutoloadGenerator
90 {
91
92
93
94 private $eventDispatcher;
95
96
97
98
99 private $io;
100
101
102
103
104 private $devMode = false;
105
106
107
108
109 private $classMapAuthoritative = false;
110
111
112
113
114 private $apcu = false;
115
116
117
118
119 private $runScripts = false;
120
121 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
122 {
123 $this->eventDispatcher = $eventDispatcher;
124 $this->io = $io;
125 }
126
127 public function setDevMode($devMode = true)
128 {
129 $this->devMode = (bool) $devMode;
130 }
131
132
133
134
135
136
137
138 public function setClassMapAuthoritative($classMapAuthoritative)
139 {
140 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
141 }
142
143
144
145
146
147
148 public function setApcu($apcu)
149 {
150 $this->apcu = (bool) $apcu;
151 }
152
153
154
155
156
157
158 public function setRunScripts($runScripts = true)
159 {
160 $this->runScripts = (bool) $runScripts;
161 }
162
163 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
164 {
165 if ($this->classMapAuthoritative) {
166
167  $scanPsr0Packages = true;
168 }
169 if ($this->runScripts) {
170 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
171 'optimize' => (bool) $scanPsr0Packages,
172 ));
173 }
174
175 $filesystem = new Filesystem();
176 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
177
178  
179  
180  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
181 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
182 $useGlobalIncludePath = (bool) $config->get('use-include-path');
183 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
184 $targetDir = $vendorPath.'/'.$targetDir;
185 $filesystem->ensureDirectoryExists($targetDir);
186
187 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
188 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
189 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
190
191 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
192 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
193
194 $namespacesFile = <<<EOF
195 <?php
196
197 // autoload_namespaces.php @generated by Composer
198
199 \$vendorDir = $vendorPathCode52;
200 \$baseDir = $appBaseDirCode;
201
202 return array(
203
204 EOF;
205
206 $psr4File = <<<EOF
207 <?php
208
209 // autoload_psr4.php @generated by Composer
210
211 \$vendorDir = $vendorPathCode52;
212 \$baseDir = $appBaseDirCode;
213
214 return array(
215
216 EOF;
217
218
219  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
220 $autoloads = $this->parseAutoloads($packageMap, $mainPackage, $this->devMode === false);
221
222
223  foreach ($autoloads['psr-0'] as $namespace => $paths) {
224 $exportedPaths = array();
225 foreach ($paths as $path) {
226 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
227 }
228 $exportedPrefix = var_export($namespace, true);
229 $namespacesFile .= "    $exportedPrefix => ";
230 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
231 }
232 $namespacesFile .= ");\n";
233
234
235  foreach ($autoloads['psr-4'] as $namespace => $paths) {
236 $exportedPaths = array();
237 foreach ($paths as $path) {
238 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
239 }
240 $exportedPrefix = var_export($namespace, true);
241 $psr4File .= "    $exportedPrefix => ";
242 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
243 }
244 $psr4File .= ");\n";
245
246 $classmapFile = <<<EOF
247 <?php
248
249 // autoload_classmap.php @generated by Composer
250
251 \$vendorDir = $vendorPathCode52;
252 \$baseDir = $appBaseDirCode;
253
254 return array(
255
256 EOF;
257
258
259  $targetDirLoader = null;
260 $mainAutoload = $mainPackage->getAutoload();
261 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
262 $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
263 $prefixes = implode(', ', array_map(function ($prefix) {
264 return var_export($prefix, true);
265 }, array_keys($mainAutoload['psr-0'])));
266 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
267
268 $targetDirLoader = <<<EOF
269
270     public static function autoload(\$class)
271     {
272         \$dir = $baseDirFromTargetDirCode . '/';
273         \$prefixes = array($prefixes);
274         foreach (\$prefixes as \$prefix) {
275             if (0 !== strpos(\$class, \$prefix)) {
276                 continue;
277             }
278             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
279             if (!\$path = stream_resolve_include_path(\$path)) {
280                 return false;
281             }
282             require \$path;
283
284             return true;
285         }
286     }
287
288 EOF;
289 }
290
291 $blacklist = null;
292 if (!empty($autoloads['exclude-from-classmap'])) {
293 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
294 }
295
296
297  $classMap = array();
298 if ($scanPsr0Packages) {
299 $namespacesToScan = array();
300
301
302  foreach (array('psr-0', 'psr-4') as $psrType) {
303 foreach ($autoloads[$psrType] as $namespace => $paths) {
304 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
305 }
306 }
307
308 krsort($namespacesToScan);
309
310 foreach ($namespacesToScan as $namespace => $groups) {
311 foreach ($groups as $group) {
312 foreach ($group['paths'] as $dir) {
313 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
314 if (!is_dir($dir)) {
315 continue;
316 }
317
318 $namespaceFilter = $namespace === '' ? null : $namespace;
319 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
320 }
321 }
322 }
323 }
324
325 foreach ($autoloads['classmap'] as $dir) {
326 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
327 }
328
329 ksort($classMap);
330 foreach ($classMap as $class => $code) {
331 $classmapFile .= '    '.var_export($class, true).' => '.$code;
332 }
333 $classmapFile .= ");\n";
334
335 if (!$suffix) {
336 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
337 $content = file_get_contents($vendorPath.'/autoload.php');
338 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
339 $suffix = $match[1];
340 }
341 }
342
343 if (!$suffix) {
344 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
345 }
346 }
347
348 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
349 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
350 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
351 $includePathFilePath = $targetDir.'/include_paths.php';
352 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
353 file_put_contents($includePathFilePath, $includePathFileContents);
354 } elseif (file_exists($includePathFilePath)) {
355 unlink($includePathFilePath);
356 }
357 $includeFilesFilePath = $targetDir.'/autoload_files.php';
358 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
359 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
360 } elseif (file_exists($includeFilesFilePath)) {
361 unlink($includeFilesFilePath);
362 }
363 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
364 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
365 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
366
367 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
368 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
369
370 if ($this->runScripts) {
371 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
372 'optimize' => (bool) $scanPsr0Packages,
373 ));
374 }
375
376 return count($classMap);
377 }
378
379 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
380 {
381 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
382 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
383 if (!isset($classMap[$class])) {
384 $classMap[$class] = $pathCode;
385 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
386 $this->io->writeError(
387 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
388 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
389 );
390 }
391 }
392
393 return $classMap;
394 }
395
396 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
397 {
398 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
399 }
400
401 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
402 {
403
404  $packageMap = array(array($mainPackage, ''));
405
406 foreach ($packages as $package) {
407 if ($package instanceof AliasPackage) {
408 continue;
409 }
410 $this->validatePackage($package);
411
412 $packageMap[] = array(
413 $package,
414 $installationManager->getInstallPath($package),
415 );
416 }
417
418 return $packageMap;
419 }
420
421
422
423
424
425
426 protected function validatePackage(PackageInterface $package)
427 {
428 $autoload = $package->getAutoload();
429 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
430 $name = $package->getName();
431 $package->getTargetDir();
432 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
433 }
434 if (!empty($autoload['psr-4'])) {
435 foreach ($autoload['psr-4'] as $namespace => $dirs) {
436 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
437 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
438 }
439 }
440 }
441 }
442
443
444
445
446
447
448
449
450
451 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage, $filterOutRequireDevPackages = false)
452 {
453 $mainPackageMap = array_shift($packageMap);
454 if ($filterOutRequireDevPackages) {
455 $packageMap = $this->filterPackageMap($packageMap, $mainPackage);
456 }
457 $sortedPackageMap = $this->sortPackageMap($packageMap);
458 $sortedPackageMap[] = $mainPackageMap;
459 array_unshift($packageMap, $mainPackageMap);
460
461 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
462 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
463 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
464 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
465 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
466
467 krsort($psr0);
468 krsort($psr4);
469
470 return array(
471 'psr-0' => $psr0,
472 'psr-4' => $psr4,
473 'classmap' => $classmap,
474 'files' => $files,
475 'exclude-from-classmap' => $exclude,
476 );
477 }
478
479
480
481
482
483
484
485 public function createLoader(array $autoloads)
486 {
487 $loader = new ClassLoader();
488
489 if (isset($autoloads['psr-0'])) {
490 foreach ($autoloads['psr-0'] as $namespace => $path) {
491 $loader->add($namespace, $path);
492 }
493 }
494
495 if (isset($autoloads['psr-4'])) {
496 foreach ($autoloads['psr-4'] as $namespace => $path) {
497 $loader->addPsr4($namespace, $path);
498 }
499 }
500
501 if (isset($autoloads['classmap'])) {
502 $blacklist = null;
503 if (!empty($autoloads['exclude-from-classmap'])) {
504 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
505 }
506
507 foreach ($autoloads['classmap'] as $dir) {
508 try {
509 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
510 } catch (\RuntimeException $e) {
511 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
512 }
513 }
514 }
515
516 return $loader;
517 }
518
519 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
520 {
521 $includePaths = array();
522
523 foreach ($packageMap as $item) {
524 list($package, $installPath) = $item;
525
526 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
527 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
528 }
529
530 foreach ($package->getIncludePaths() as $includePath) {
531 $includePath = trim($includePath, '/');
532 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
533 }
534 }
535
536 if (!$includePaths) {
537 return;
538 }
539
540 $includePathsCode = '';
541 foreach ($includePaths as $path) {
542 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
543 }
544
545 return <<<EOF
546 <?php
547
548 // include_paths.php @generated by Composer
549
550 \$vendorDir = $vendorPathCode;
551 \$baseDir = $appBaseDirCode;
552
553 return array(
554 $includePathsCode);
555
556 EOF;
557 }
558
559 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
560 {
561 $filesCode = '';
562 foreach ($files as $fileIdentifier => $functionFile) {
563 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
564 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
565 }
566
567 if (!$filesCode) {
568 return false;
569 }
570
571 return <<<EOF
572 <?php
573
574 // autoload_files.php @generated by Composer
575
576 \$vendorDir = $vendorPathCode;
577 \$baseDir = $appBaseDirCode;
578
579 return array(
580 $filesCode);
581
582 EOF;
583 }
584
585 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
586 {
587 if (!$filesystem->isAbsolutePath($path)) {
588 $path = $basePath . '/' . $path;
589 }
590 $path = $filesystem->normalizePath($path);
591
592 $baseDir = '';
593 if (strpos($path.'/', $vendorPath.'/') === 0) {
594 $path = substr($path, strlen($vendorPath));
595 $baseDir = '$vendorDir';
596
597 if ($path !== false) {
598 $baseDir .= " . ";
599 }
600 } else {
601 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
602 if (!$filesystem->isAbsolutePath($path)) {
603 $baseDir = '$baseDir . ';
604 $path = '/' . $path;
605 }
606 }
607
608 if (strpos($path, '.phar') !== false) {
609 $baseDir = "'phar://' . " . $baseDir;
610 }
611
612 return $baseDir . (($path !== false) ? var_export($path, true) : "");
613 }
614
615 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
616 {
617 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
618 if ("'" === $lastChar || '"' === $lastChar) {
619 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
620 } else {
621 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
622 }
623
624 return <<<AUTOLOAD
625 <?php
626
627 // autoload.php @generated by Composer
628
629 require_once $vendorPathToTargetDirCode;
630
631 return ComposerAutoloaderInit$suffix::getLoader();
632
633 AUTOLOAD;
634 }
635
636 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
637 {
638 $file = <<<HEADER
639 <?php
640
641 // autoload_real.php @generated by Composer
642
643 class ComposerAutoloaderInit$suffix
644 {
645     private static \$loader;
646
647     public static function loadClassLoader(\$class)
648     {
649         if ('Composer\\Autoload\\ClassLoader' === \$class) {
650             require __DIR__ . '/ClassLoader.php';
651         }
652     }
653
654     public static function getLoader()
655     {
656         if (null !== self::\$loader) {
657             return self::\$loader;
658         }
659
660         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
661         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
662         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
663
664
665 HEADER;
666
667 if ($useIncludePath) {
668 $file .= <<<'INCLUDE_PATH'
669         $includePaths = require __DIR__ . '/include_paths.php';
670         $includePaths[] = get_include_path();
671         set_include_path(implode(PATH_SEPARATOR, $includePaths));
672
673
674 INCLUDE_PATH;
675 }
676
677 $file .= <<<STATIC_INIT
678         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
679         if (\$useStaticLoader) {
680             require_once __DIR__ . '/autoload_static.php';
681
682             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
683         } else {
684
685 STATIC_INIT;
686
687 if (!$this->classMapAuthoritative) {
688 $file .= <<<'PSR04'
689             $map = require __DIR__ . '/autoload_namespaces.php';
690             foreach ($map as $namespace => $path) {
691                 $loader->set($namespace, $path);
692             }
693
694             $map = require __DIR__ . '/autoload_psr4.php';
695             foreach ($map as $namespace => $path) {
696                 $loader->setPsr4($namespace, $path);
697             }
698
699
700 PSR04;
701 }
702
703 if ($useClassMap) {
704 $file .= <<<'CLASSMAP'
705             $classMap = require __DIR__ . '/autoload_classmap.php';
706             if ($classMap) {
707                 $loader->addClassMap($classMap);
708             }
709
710 CLASSMAP;
711 }
712
713 $file .= "        }\n\n";
714
715 if ($this->classMapAuthoritative) {
716 $file .= <<<'CLASSMAPAUTHORITATIVE'
717         $loader->setClassMapAuthoritative(true);
718
719 CLASSMAPAUTHORITATIVE;
720 }
721
722 if ($this->apcu) {
723 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
724 $file .= <<<APCU
725         \$loader->setApcuPrefix('$apcuPrefix');
726
727 APCU;
728 }
729
730 if ($useGlobalIncludePath) {
731 $file .= <<<'INCLUDEPATH'
732         $loader->setUseIncludePath(true);
733
734 INCLUDEPATH;
735 }
736
737 if ($targetDirLoader) {
738 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
739         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
740
741
742 REGISTER_TARGET_DIR_AUTOLOAD;
743 }
744
745 $file .= <<<REGISTER_LOADER
746         \$loader->register($prependAutoloader);
747
748
749 REGISTER_LOADER;
750
751 if ($useIncludeFiles) {
752 $file .= <<<INCLUDE_FILES
753         if (\$useStaticLoader) {
754             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
755         } else {
756             \$includeFiles = require __DIR__ . '/autoload_files.php';
757         }
758         foreach (\$includeFiles as \$fileIdentifier => \$file) {
759             composerRequire$suffix(\$fileIdentifier, \$file);
760         }
761
762
763 INCLUDE_FILES;
764 }
765
766 $file .= <<<METHOD_FOOTER
767         return \$loader;
768     }
769
770 METHOD_FOOTER;
771
772 $file .= $targetDirLoader;
773
774 if ($useIncludeFiles) {
775 return $file . <<<FOOTER
776 }
777
778 function composerRequire$suffix(\$fileIdentifier, \$file)
779 {
780     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
781         require \$file;
782
783         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
784     }
785 }
786
787 FOOTER;
788 }
789
790 return $file . <<<FOOTER
791 }
792
793 FOOTER;
794 }
795
796 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
797 {
798 $staticPhpVersion = 50600;
799
800 $file = <<<HEADER
801 <?php
802
803 // autoload_static.php @generated by Composer
804
805 namespace Composer\Autoload;
806
807 class ComposerStaticInit$suffix
808 {
809
810 HEADER;
811
812 $loader = new ClassLoader();
813
814 $map = require $targetDir . '/autoload_namespaces.php';
815 foreach ($map as $namespace => $path) {
816 $loader->set($namespace, $path);
817 }
818
819 $map = require $targetDir . '/autoload_psr4.php';
820 foreach ($map as $namespace => $path) {
821 $loader->setPsr4($namespace, $path);
822 }
823
824 $classMap = require $targetDir . '/autoload_classmap.php';
825 if ($classMap) {
826 $loader->addClassMap($classMap);
827 }
828
829 $filesystem = new Filesystem();
830
831 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
832 $vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
833 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
834 $appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
835
836 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
837 $absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\\/') . '/', true), 0, -1);
838 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
839 $absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\\/') . '/', true), 0, -1);
840
841 $initializer = '';
842 $prefix = "\0Composer\Autoload\ClassLoader\0";
843 $prefixLen = strlen($prefix);
844 if (file_exists($targetDir . '/autoload_files.php')) {
845 $maps = array('files' => require $targetDir . '/autoload_files.php');
846 } else {
847 $maps = array();
848 }
849
850 foreach ((array) $loader as $prop => $value) {
851 if ($value && 0 === strpos($prop, $prefix)) {
852 $maps[substr($prop, $prefixLen)] = $value;
853 }
854 }
855
856 foreach ($maps as $prop => $value) {
857 if (count($value) > 32767) {
858
859  
860  $staticPhpVersion = 70000;
861 }
862 $value = strtr(
863 var_export($value, true),
864 array(
865 $absoluteVendorPathCode => $vendorPathCode,
866 $absoluteVendorPharPathCode => $vendorPharPathCode,
867 $absoluteAppBaseDirCode => $appBaseDirCode,
868 $absoluteAppBaseDirPharCode => $appBaseDirPharCode,
869 )
870 );
871 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
872
873 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
874 if ('files' !== $prop) {
875 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
876 }
877 }
878
879 return $file . <<<INITIALIZER
880     public static function getInitializer(ClassLoader \$loader)
881     {
882         return \Closure::bind(function () use (\$loader) {
883 $initializer
884         }, null, ClassLoader::class);
885     }
886 }
887
888 INITIALIZER;
889 }
890
891 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
892 {
893 $autoloads = array();
894
895 foreach ($packageMap as $item) {
896 list($package, $installPath) = $item;
897
898 $autoload = $package->getAutoload();
899 if ($this->devMode && $package === $mainPackage) {
900 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
901 }
902
903
904  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
905 continue;
906 }
907 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
908 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
909 }
910
911 foreach ($autoload[$type] as $namespace => $paths) {
912 foreach ((array) $paths as $path) {
913 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
914
915  if ($package === $mainPackage) {
916 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
917 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
918 } else {
919
920  $path = $package->getTargetDir() . '/' . $path;
921 }
922 }
923
924 if ($type === 'exclude-from-classmap') {
925
926  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
927
928
929  $path = str_replace('\\*\\*', '.+?', $path);
930 $path = str_replace('\\*', '[^/]+?', $path);
931
932
933  $updir = null;
934 $path = preg_replace_callback(
935 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
936 function ($matches) use (&$updir) {
937 if (isset($matches[1])) {
938
939  $updir = str_replace('\\.', '.', $matches[1]);
940 }
941
942 return '';
943 },
944 $path
945 );
946 if (empty($installPath)) {
947 $installPath = strtr(getcwd(), '\\', '/');
948 }
949
950 $resolvedPath = realpath($installPath . '/' . $updir);
951 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
952 continue;
953 }
954
955 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
956
957 if ($type === 'files') {
958 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
959 continue;
960 } elseif ($type === 'classmap') {
961 $autoloads[] = $relativePath;
962 continue;
963 }
964
965 $autoloads[$namespace][] = $relativePath;
966 }
967 }
968 }
969
970 return $autoloads;
971 }
972
973 protected function getFileIdentifier(PackageInterface $package, $path)
974 {
975 return md5($package->getName() . ':' . $path);
976 }
977
978
979
980
981
982
983
984
985 protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage)
986 {
987 $packages = array();
988 $include = array();
989
990 foreach ($packageMap as $item) {
991 $package = $item[0];
992 $name = $package->getName();
993 $packages[$name] = $package;
994 }
995
996 $add = function (PackageInterface $package) use (&$add, $packages, &$include) {
997 foreach ($package->getRequires() as $link) {
998 $target = $link->getTarget();
999 if (!isset($include[$target])) {
1000 $include[$target] = true;
1001 if (isset($packages[$target])) {
1002 $add($packages[$target]);
1003 }
1004 }
1005 }
1006 };
1007 $add($mainPackage);
1008
1009 return array_filter(
1010 $packageMap,
1011 function ($item) use ($include) {
1012 $package = $item[0];
1013 foreach ($package->getNames() as $name) {
1014 if (isset($include[$name])) {
1015 return true;
1016 }
1017 }
1018
1019 return false;
1020 }
1021 );
1022 }
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032 protected function sortPackageMap(array $packageMap)
1033 {
1034 $packages = array();
1035 $paths = array();
1036
1037 foreach ($packageMap as $item) {
1038 list($package, $path) = $item;
1039 $name = $package->getName();
1040 $packages[$name] = $package;
1041 $paths[$name] = $path;
1042 }
1043
1044 $sortedPackages = PackageSorter::sortPackages($packages);
1045
1046
1047 $sortedPackageMap = array();
1048
1049 foreach ($sortedPackages as $package) {
1050 $name = $package->getName();
1051 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1052 }
1053
1054 return $sortedPackageMap;
1055 }
1056
1057
1058
1059
1060
1061
1062
1063 protected function safeCopy($source, $target)
1064 {
1065 $source = fopen($source, 'r');
1066 $target = fopen($target, 'w+');
1067
1068 stream_copy_to_stream($source, $target);
1069 fclose($source);
1070 fclose($target);
1071 }
1072 }
1073 <?php
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091 namespace Composer\Autoload;
1092
1093 use Symfony\Component\Finder\Finder;
1094 use Composer\IO\IOInterface;
1095 use Composer\Util\Filesystem;
1096
1097
1098
1099
1100
1101
1102
1103 class ClassMapGenerator
1104 {
1105
1106
1107
1108
1109
1110
1111 public static function dump($dirs, $file)
1112 {
1113 $maps = array();
1114
1115 foreach ($dirs as $dir) {
1116 $maps = array_merge($maps, static::createMap($dir));
1117 }
1118
1119 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1120 }
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1134 {
1135 if (is_string($path)) {
1136 if (is_file($path)) {
1137 $path = array(new \SplFileInfo($path));
1138 } elseif (is_dir($path)) {
1139 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1140 } else {
1141 throw new \RuntimeException(
1142 'Could not scan for classes inside "'.$path.
1143 '" which does not appear to be a file nor a folder'
1144 );
1145 }
1146 }
1147
1148 $map = array();
1149 $filesystem = new Filesystem();
1150 $cwd = realpath(getcwd());
1151
1152 foreach ($path as $file) {
1153 $filePath = $file->getPathname();
1154 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1155 continue;
1156 }
1157
1158 if (!$filesystem->isAbsolutePath($filePath)) {
1159 $filePath = $cwd . '/' . $filePath;
1160 $filePath = $filesystem->normalizePath($filePath);
1161 } else {
1162 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1163 }
1164
1165
1166  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1167 continue;
1168 }
1169
1170  if ($blacklist && preg_match($blacklist, strtr($filePath, '\\', '/'))) {
1171 continue;
1172 }
1173
1174 $classes = self::findClasses($filePath);
1175
1176 foreach ($classes as $class) {
1177
1178  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1179 continue;
1180 }
1181
1182 if (!isset($map[$class])) {
1183 $map[$class] = $filePath;
1184 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1185 $io->writeError(
1186 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1187 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1188 );
1189 }
1190 }
1191 }
1192
1193 return $map;
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203 private static function findClasses($path)
1204 {
1205 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1206 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1207 $extraTypes .= '|enum';
1208 }
1209
1210
1211  
1212  $contents = @php_strip_whitespace($path);
1213 if (!$contents) {
1214 if (!file_exists($path)) {
1215 $message = 'File at "%s" does not exist, check your classmap definitions';
1216 } elseif (!is_readable($path)) {
1217 $message = 'File at "%s" is not readable, check its permissions';
1218 } elseif ('' === trim(file_get_contents($path))) {
1219
1220  return array();
1221 } else {
1222 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1223 }
1224 $error = error_get_last();
1225 if (isset($error['message'])) {
1226 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1227 }
1228 throw new \RuntimeException(sprintf($message, $path));
1229 }
1230
1231
1232  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1233 return array();
1234 }
1235
1236
1237  $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
1238
1239  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1240
1241  if (substr($contents, 0, 2) !== '<?') {
1242 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1243 if ($replacements === 0) {
1244 return array();
1245 }
1246 }
1247
1248  $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
1249
1250  $pos = strrpos($contents, '?>');
1251 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1252 $contents = substr($contents, 0, $pos);
1253 }
1254
1255  if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
1256 $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
1257 }
1258
1259 preg_match_all('{
1260             (?:
1261                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1262                | \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*+ [\{;]
1263             )
1264         }ix', $contents, $matches);
1265
1266 $classes = array();
1267 $namespace = '';
1268
1269 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1270 if (!empty($matches['ns'][$i])) {
1271 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1272 } else {
1273 $name = $matches['name'][$i];
1274
1275  if ($name === 'extends' || $name === 'implements') {
1276 continue;
1277 }
1278 if ($name[0] === ':') {
1279
1280  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1281 } elseif ($matches['type'][$i] === 'enum') {
1282
1283  
1284  
1285  
1286  $name = rtrim($name, ':');
1287 }
1288 $classes[] = ltrim($namespace . $name, '\\');
1289 }
1290 }
1291
1292 return $classes;
1293 }
1294 }
1295 <?php
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307 namespace Composer;
1308
1309 use Composer\IO\IOInterface;
1310 use Composer\Util\Filesystem;
1311 use Composer\Util\Silencer;
1312 use Symfony\Component\Finder\Finder;
1313
1314
1315
1316
1317
1318
1319 class Cache
1320 {
1321 private static $cacheCollected = false;
1322 private $io;
1323 private $root;
1324 private $enabled = true;
1325 private $whitelist;
1326 private $filesystem;
1327
1328
1329
1330
1331
1332
1333
1334 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1335 {
1336 $this->io = $io;
1337 $this->root = rtrim($cacheDir, '/\\') . '/';
1338 $this->whitelist = $whitelist;
1339 $this->filesystem = $filesystem ?: new Filesystem();
1340
1341 if (!self::isUsable($cacheDir)) {
1342 $this->enabled = false;
1343
1344 return;
1345 }
1346
1347 if (
1348 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1349 || !is_writable($this->root)
1350 ) {
1351 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1352 $this->enabled = false;
1353 }
1354 }
1355
1356 public static function isUsable($path)
1357 {
1358 return !preg_match('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path);
1359 }
1360
1361 public function isEnabled()
1362 {
1363 return $this->enabled;
1364 }
1365
1366 public function getRoot()
1367 {
1368 return $this->root;
1369 }
1370
1371 public function read($file)
1372 {
1373 if ($this->enabled) {
1374 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1375 if (file_exists($this->root . $file)) {
1376 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1377
1378 return file_get_contents($this->root . $file);
1379 }
1380 }
1381
1382 return false;
1383 }
1384
1385 public function write($file, $contents)
1386 {
1387 if ($this->enabled) {
1388 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1389
1390 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1391
1392 try {
1393 return file_put_contents($this->root . $file, $contents);
1394 } catch (\ErrorException $e) {
1395 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1396 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1397
1398  unlink($this->root . $file);
1399
1400 $message = sprintf(
1401 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1402 $this->root . $file,
1403 $m[1],
1404 $m[2],
1405 @disk_free_space($this->root . dirname($file))
1406 );
1407
1408 $this->io->writeError($message);
1409
1410 return false;
1411 }
1412
1413 throw $e;
1414 }
1415 }
1416
1417 return false;
1418 }
1419
1420
1421
1422
1423 public function copyFrom($file, $source)
1424 {
1425 if ($this->enabled) {
1426 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1427 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1428
1429 if (!file_exists($source)) {
1430 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1431 } elseif ($this->io->isDebug()) {
1432 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1433 }
1434
1435 return copy($source, $this->root . $file);
1436 }
1437
1438 return false;
1439 }
1440
1441
1442
1443
1444 public function copyTo($file, $target)
1445 {
1446 if ($this->enabled) {
1447 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1448 if (file_exists($this->root . $file)) {
1449 try {
1450 touch($this->root . $file, filemtime($this->root . $file), time());
1451 } catch (\ErrorException $e) {
1452
1453  
1454  Silencer::call('touch', $this->root . $file);
1455 }
1456
1457 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1458
1459 return copy($this->root . $file, $target);
1460 }
1461 }
1462
1463 return false;
1464 }
1465
1466 public function gcIsNecessary()
1467 {
1468 return (!self::$cacheCollected && !mt_rand(0, 50));
1469 }
1470
1471 public function remove($file)
1472 {
1473 if ($this->enabled) {
1474 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1475 if (file_exists($this->root . $file)) {
1476 return $this->filesystem->unlink($this->root . $file);
1477 }
1478 }
1479
1480 return false;
1481 }
1482
1483 public function clear()
1484 {
1485 if ($this->enabled) {
1486 $this->filesystem->emptyDirectory($this->root);
1487 return true;
1488 }
1489
1490 return false;
1491 }
1492
1493 public function gc($ttl, $maxSize)
1494 {
1495 if ($this->enabled) {
1496 $expire = new \DateTime();
1497 $expire->modify('-'.$ttl.' seconds');
1498
1499 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1500 foreach ($finder as $file) {
1501 $this->filesystem->unlink($file->getPathname());
1502 }
1503
1504 $totalSize = $this->filesystem->size($this->root);
1505 if ($totalSize > $maxSize) {
1506 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1507 while ($totalSize > $maxSize && $iterator->valid()) {
1508 $filepath = $iterator->current()->getPathname();
1509 $totalSize -= $this->filesystem->size($filepath);
1510 $this->filesystem->unlink($filepath);
1511 $iterator->next();
1512 }
1513 }
1514
1515 self::$cacheCollected = true;
1516
1517 return true;
1518 }
1519
1520 return false;
1521 }
1522
1523 public function sha1($file)
1524 {
1525 if ($this->enabled) {
1526 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1527 if (file_exists($this->root . $file)) {
1528 return sha1_file($this->root . $file);
1529 }
1530 }
1531
1532 return false;
1533 }
1534
1535 public function sha256($file)
1536 {
1537 if ($this->enabled) {
1538 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1539 if (file_exists($this->root . $file)) {
1540 return hash_file('sha256', $this->root . $file);
1541 }
1542 }
1543
1544 return false;
1545 }
1546
1547 protected function getFinder()
1548 {
1549 return Finder::create()->in($this->root)->files();
1550 }
1551 }
1552 <?php
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564 namespace Composer\Command;
1565
1566 use Symfony\Component\Console\Input\InputInterface;
1567 use Symfony\Component\Console\Output\OutputInterface;
1568
1569
1570
1571
1572 class AboutCommand extends BaseCommand
1573 {
1574 protected function configure()
1575 {
1576 $this
1577 ->setName('about')
1578 ->setDescription('Shows the short information about Composer.')
1579 ->setHelp(
1580 <<<EOT
1581 <info>php composer.phar about</info>
1582 EOT
1583 )
1584 ;
1585 }
1586
1587 protected function execute(InputInterface $input, OutputInterface $output)
1588 {
1589 $this->getIO()->write(
1590 <<<EOT
1591 <info>Composer - Dependency Manager for PHP</info>
1592 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1593 See https://getcomposer.org/ for more information.</comment>
1594 EOT
1595 );
1596
1597 return 0;
1598 }
1599 }
1600 <?php
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612 namespace Composer\Command;
1613
1614 use Composer\Factory;
1615 use Composer\IO\IOInterface;
1616 use Composer\Config;
1617 use Composer\Composer;
1618 use Composer\Repository\CompositeRepository;
1619 use Composer\Repository\RepositoryFactory;
1620 use Composer\Script\ScriptEvents;
1621 use Composer\Plugin\CommandEvent;
1622 use Composer\Plugin\PluginEvents;
1623 use Composer\Util\Filesystem;
1624 use Symfony\Component\Console\Input\InputArgument;
1625 use Symfony\Component\Console\Input\InputInterface;
1626 use Symfony\Component\Console\Input\InputOption;
1627 use Symfony\Component\Console\Output\OutputInterface;
1628
1629
1630
1631
1632
1633
1634 class ArchiveCommand extends BaseCommand
1635 {
1636 protected function configure()
1637 {
1638 $this
1639 ->setName('archive')
1640 ->setDescription('Creates an archive of this composer package.')
1641 ->setDefinition(array(
1642 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1643 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1644 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1645 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1646 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1647 .' Note that the format will be appended.'),
1648 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1649 ))
1650 ->setHelp(
1651 <<<EOT
1652 The <info>archive</info> command creates an archive of the specified format
1653 containing the files and directories of the Composer project or the specified
1654 package in the specified version and writes it to the specified directory.
1655
1656 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1657
1658 Read more at https://getcomposer.org/doc/03-cli.md#archive
1659 EOT
1660 )
1661 ;
1662 }
1663
1664 protected function execute(InputInterface $input, OutputInterface $output)
1665 {
1666 $config = Factory::createConfig();
1667 $composer = $this->getComposer(false);
1668 if ($composer) {
1669 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1670 $eventDispatcher = $composer->getEventDispatcher();
1671 $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent);
1672 $eventDispatcher->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1673 }
1674
1675 if (null === $input->getOption('format')) {
1676 $input->setOption('format', $config->get('archive-format'));
1677 }
1678 if (null === $input->getOption('dir')) {
1679 $input->setOption('dir', $config->get('archive-dir'));
1680 }
1681
1682 $returnCode = $this->archive(
1683 $this->getIO(),
1684 $config,
1685 $input->getArgument('package'),
1686 $input->getArgument('version'),
1687 $input->getOption('format'),
1688 $input->getOption('dir'),
1689 $input->getOption('file'),
1690 $input->getOption('ignore-filters'),
1691 $composer
1692 );
1693
1694 if (0 === $returnCode && $composer) {
1695 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1696 }
1697
1698 return $returnCode;
1699 }
1700
1701 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1702 {
1703 if ($composer) {
1704 $archiveManager = $composer->getArchiveManager();
1705 } else {
1706 $factory = new Factory;
1707 $downloadManager = $factory->createDownloadManager($io, $config);
1708 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1709 }
1710
1711 if ($packageName) {
1712 $package = $this->selectPackage($io, $packageName, $version);
1713
1714 if (!$package) {
1715 return 1;
1716 }
1717 } else {
1718 $package = $this->getComposer()->getPackage();
1719 }
1720
1721 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1722 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1723 $fs = new Filesystem;
1724 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1725
1726 $io->writeError('Created: ', false);
1727 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1728
1729 return 0;
1730 }
1731
1732 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1733 {
1734 $io->writeError('<info>Searching for the specified package.</info>');
1735
1736 if ($composer = $this->getComposer(false)) {
1737 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1738 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1739 } else {
1740 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1741 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1742 $repo = new CompositeRepository($defaultRepos);
1743 }
1744
1745 $packages = $repo->findPackages($packageName, $version);
1746
1747 if (count($packages) > 1) {
1748 $package = reset($packages);
1749 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1750 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1751 return $p->getPrettyString();
1752 }, $packages)).'.');
1753 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1754 } elseif ($packages) {
1755 $package = reset($packages);
1756 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1757 } else {
1758 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1759
1760 return false;
1761 }
1762
1763 return $package;
1764 }
1765 }
1766 <?php
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778 namespace Composer\Command;
1779
1780 use Composer\Composer;
1781 use Composer\Config;
1782 use Composer\Console\Application;
1783 use Composer\Factory;
1784 use Composer\IO\IOInterface;
1785 use Composer\IO\NullIO;
1786 use Composer\Plugin\PreCommandRunEvent;
1787 use Composer\Plugin\PluginEvents;
1788 use Symfony\Component\Console\Input\InputInterface;
1789 use Symfony\Component\Console\Output\OutputInterface;
1790 use Symfony\Component\Console\Command\Command;
1791
1792
1793
1794
1795
1796
1797
1798 abstract class BaseCommand extends Command
1799 {
1800
1801
1802
1803 private $composer;
1804
1805
1806
1807
1808 private $io;
1809
1810
1811
1812
1813
1814
1815
1816 public function getComposer($required = true, $disablePlugins = null)
1817 {
1818 if (null === $this->composer) {
1819 $application = $this->getApplication();
1820 if ($application instanceof Application) {
1821
1822 $this->composer = $application->getComposer($required, $disablePlugins);
1823 } elseif ($required) {
1824 throw new \RuntimeException(
1825 'Could not create a Composer\Composer instance, you must inject '.
1826 'one if this command is not used with a Composer\Console\Application instance'
1827 );
1828 }
1829 }
1830
1831 return $this->composer;
1832 }
1833
1834
1835
1836
1837 public function setComposer(Composer $composer)
1838 {
1839 $this->composer = $composer;
1840 }
1841
1842
1843
1844
1845 public function resetComposer()
1846 {
1847 $this->composer = null;
1848 $this->getApplication()->resetComposer();
1849 }
1850
1851
1852
1853
1854
1855
1856
1857
1858 public function isProxyCommand()
1859 {
1860 return false;
1861 }
1862
1863
1864
1865
1866 public function getIO()
1867 {
1868 if (null === $this->io) {
1869 $application = $this->getApplication();
1870 if ($application instanceof Application) {
1871
1872 $this->io = $application->getIO();
1873 } else {
1874 $this->io = new NullIO();
1875 }
1876 }
1877
1878 return $this->io;
1879 }
1880
1881
1882
1883
1884 public function setIO(IOInterface $io)
1885 {
1886 $this->io = $io;
1887 }
1888
1889
1890
1891
1892 protected function initialize(InputInterface $input, OutputInterface $output)
1893 {
1894
1895  $disablePlugins = $input->hasParameterOption('--no-plugins');
1896 $composer = $this->getComposer(false, $disablePlugins);
1897 if (null === $composer) {
1898 $composer = Factory::createGlobal($this->getIO(), $disablePlugins);
1899 }
1900 if ($composer) {
1901 $preCommandRunEvent = new PreCommandRunEvent(PluginEvents::PRE_COMMAND_RUN, $input, $this->getName());
1902 $composer->getEventDispatcher()->dispatch($preCommandRunEvent->getName(), $preCommandRunEvent);
1903 }
1904
1905 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1906 $input->setOption('no-progress', true);
1907 }
1908
1909 parent::initialize($input, $output);
1910 }
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1922 {
1923 $preferSource = false;
1924 $preferDist = false;
1925
1926 switch ($config->get('preferred-install')) {
1927 case 'source':
1928 $preferSource = true;
1929 break;
1930 case 'dist':
1931 $preferDist = true;
1932 break;
1933 case 'auto':
1934 default:
1935
1936  break;
1937 }
1938
1939 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1940 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1941 $preferDist = $input->getOption('prefer-dist');
1942 }
1943
1944 return array($preferSource, $preferDist);
1945 }
1946 }
1947 <?php
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959 namespace Composer\Command;
1960
1961 use Composer\DependencyResolver\Pool;
1962 use Composer\Package\Link;
1963 use Composer\Package\PackageInterface;
1964 use Composer\Repository\ArrayRepository;
1965 use Composer\Repository\CompositeRepository;
1966 use Composer\Repository\PlatformRepository;
1967 use Composer\Repository\RepositoryFactory;
1968 use Composer\Plugin\CommandEvent;
1969 use Composer\Plugin\PluginEvents;
1970 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1971 use Composer\Package\Version\VersionParser;
1972 use Symfony\Component\Console\Helper\Table;
1973 use Symfony\Component\Console\Input\InputArgument;
1974 use Symfony\Component\Console\Input\InputInterface;
1975 use Symfony\Component\Console\Input\InputOption;
1976 use Symfony\Component\Console\Output\OutputInterface;
1977
1978
1979
1980
1981
1982
1983 class BaseDependencyCommand extends BaseCommand
1984 {
1985 const ARGUMENT_PACKAGE = 'package';
1986 const ARGUMENT_CONSTRAINT = 'constraint';
1987 const OPTION_RECURSIVE = 'recursive';
1988 const OPTION_TREE = 'tree';
1989
1990 protected $colors;
1991
1992
1993
1994
1995 protected function configure()
1996 {
1997 $this->setDefinition(array(
1998 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
1999 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
2000 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
2001 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
2002 ));
2003 }
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
2014 {
2015
2016  $composer = $this->getComposer();
2017 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
2018 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
2019
2020
2021  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
2022 $repository = new CompositeRepository(array(
2023 new ArrayRepository(array($composer->getPackage())),
2024 $composer->getRepositoryManager()->getLocalRepository(),
2025 new PlatformRepository(array(), $platformOverrides),
2026 ));
2027 $pool = new Pool();
2028 $pool->addRepository($repository);
2029
2030
2031  list($needle, $textConstraint) = array_pad(
2032 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
2033 2,
2034 $input->getArgument(self::ARGUMENT_CONSTRAINT)
2035 );
2036
2037
2038  $packages = $pool->whatProvides(strtolower($needle));
2039 if (empty($packages)) {
2040 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
2041 }
2042
2043
2044  
2045  if (!$repository->findPackage($needle, $textConstraint)) {
2046 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2047 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2048 $repository->addRepository(new ArrayRepository(array(clone $match)));
2049 }
2050 }
2051
2052
2053  $needles = array($needle);
2054 if ($inverted) {
2055 foreach ($packages as $package) {
2056 $needles = array_merge($needles, array_map(function (Link $link) {
2057 return $link->getTarget();
2058 }, $package->getReplaces()));
2059 }
2060 }
2061
2062
2063  if ('*' !== $textConstraint) {
2064 $versionParser = new VersionParser();
2065 $constraint = $versionParser->parseConstraints($textConstraint);
2066 } else {
2067 $constraint = null;
2068 }
2069
2070
2071  $renderTree = $input->getOption(self::OPTION_TREE);
2072 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2073
2074
2075  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2076 if (empty($results)) {
2077 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2078 $this->getIO()->writeError(sprintf(
2079 '<info>There is no installed package depending on "%s"%s</info>',
2080 $needle,
2081 $extra
2082 ));
2083 } elseif ($renderTree) {
2084 $this->initStyles($output);
2085 $root = $packages[0];
2086 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2087 $this->printTree($results);
2088 } else {
2089 $this->printTable($output, $results);
2090 }
2091
2092 return 0;
2093 }
2094
2095
2096
2097
2098
2099
2100
2101 protected function printTable(OutputInterface $output, $results)
2102 {
2103 $table = array();
2104 $doubles = array();
2105 do {
2106 $queue = array();
2107 $rows = array();
2108 foreach ($results as $result) {
2109
2110
2111
2112
2113 list($package, $link, $children) = $result;
2114 $unique = (string) $link;
2115 if (isset($doubles[$unique])) {
2116 continue;
2117 }
2118 $doubles[$unique] = true;
2119 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2120 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2121 if ($children) {
2122 $queue = array_merge($queue, $children);
2123 }
2124 }
2125 $results = $queue;
2126 $table = array_merge($rows, $table);
2127 } while (!empty($results));
2128
2129
2130  $renderer = new Table($output);
2131 $renderer->setStyle('compact');
2132 $rendererStyle = $renderer->getStyle();
2133 $rendererStyle->setVerticalBorderChar('');
2134 $rendererStyle->setCellRowContentFormat('%s  ');
2135 $renderer->setRows($table)->render();
2136 }
2137
2138
2139
2140
2141
2142
2143 protected function initStyles(OutputInterface $output)
2144 {
2145 $this->colors = array(
2146 'green',
2147 'yellow',
2148 'cyan',
2149 'magenta',
2150 'blue',
2151 );
2152
2153 foreach ($this->colors as $color) {
2154 $style = new OutputFormatterStyle($color);
2155 $output->getFormatter()->setStyle($color, $style);
2156 }
2157 }
2158
2159
2160
2161
2162
2163
2164
2165
2166 protected function printTree($results, $prefix = '', $level = 1)
2167 {
2168 $count = count($results);
2169 $idx = 0;
2170 foreach ($results as $result) {
2171
2172
2173
2174
2175
2176 list($package, $link, $children) = $result;
2177
2178 $color = $this->colors[$level % count($this->colors)];
2179 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2180 $isLast = (++$idx == $count);
2181 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2182 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2183 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2184 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2185 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2186 if ($children) {
2187 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2188 }
2189 }
2190 }
2191
2192 private function writeTreeLine($line)
2193 {
2194 $io = $this->getIO();
2195 if (!$io->isDecorated()) {
2196 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2197 }
2198
2199 $io->write($line);
2200 }
2201 }
2202 <?php
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214 namespace Composer\Command;
2215
2216 use Composer\Package\Link;
2217 use Composer\Package\PackageInterface;
2218 use Composer\Semver\Constraint\Constraint;
2219 use Symfony\Component\Console\Helper\Table;
2220 use Symfony\Component\Console\Input\InputInterface;
2221 use Symfony\Component\Console\Input\InputOption;
2222 use Symfony\Component\Console\Output\OutputInterface;
2223 use Composer\Repository\PlatformRepository;
2224
2225 class CheckPlatformReqsCommand extends BaseCommand
2226 {
2227 protected function configure()
2228 {
2229 $this->setName('check-platform-reqs')
2230 ->setDescription('Check that platform requirements are satisfied.')
2231 ->setDefinition(array(
2232 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables checking of require-dev packages requirements.'),
2233 ))
2234 ->setHelp(
2235 <<<EOT
2236 Checks that your PHP and extensions versions match the platform requirements of the installed packages.
2237
2238 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.
2239
2240 <info>php composer.phar check-platform-reqs</info>
2241
2242 EOT
2243 );
2244 }
2245
2246 protected function execute(InputInterface $input, OutputInterface $output)
2247 {
2248 $composer = $this->getComposer();
2249
2250 $requires = $composer->getPackage()->getRequires();
2251 if ($input->getOption('no-dev')) {
2252 $dependencies = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'))->getPackages();
2253 } else {
2254 $dependencies = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
2255
2256  if (!$dependencies) {
2257 $dependencies = $composer->getLocker()->getLockedRepository(true)->getPackages();
2258 }
2259 $requires += $composer->getPackage()->getDevRequires();
2260 }
2261 foreach ($requires as $require => $link) {
2262 $requires[$require] = array($link);
2263 }
2264
2265 foreach ($dependencies as $package) {
2266 foreach ($package->getRequires() as $require => $link) {
2267 $requires[$require][] = $link;
2268 }
2269 }
2270
2271 ksort($requires);
2272
2273 $platformRepo = new PlatformRepository(array(), array());
2274 $currentPlatformPackages = $platformRepo->getPackages();
2275 $currentPlatformPackageMap = array();
2276
2277
2278
2279
2280 foreach ($currentPlatformPackages as $currentPlatformPackage) {
2281 $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
2282 }
2283
2284 $results = array();
2285
2286 $exitCode = 0;
2287
2288
2289
2290
2291 foreach ($requires as $require => $links) {
2292 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
2293 if (isset($currentPlatformPackageMap[$require])) {
2294 $pass = true;
2295 $version = $currentPlatformPackageMap[$require]->getVersion();
2296
2297 foreach ($links as $link) {
2298 if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
2299 $results[] = array(
2300 $currentPlatformPackageMap[$require]->getPrettyName(),
2301 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2302 $link,
2303 '<error>failed</error>',
2304 );
2305 $pass = false;
2306
2307 $exitCode = max($exitCode, 1);
2308 }
2309 }
2310
2311 if ($pass) {
2312 $results[] = array(
2313 $currentPlatformPackageMap[$require]->getPrettyName(),
2314 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2315 null,
2316 '<info>success</info>',
2317 );
2318 }
2319 } else {
2320 $results[] = array(
2321 $require,
2322 'n/a',
2323 $links[0],
2324 '<error>missing</error>',
2325 );
2326
2327 $exitCode = max($exitCode, 2);
2328 }
2329 }
2330 }
2331
2332 $this->printTable($output, $results);
2333
2334 return $exitCode;
2335 }
2336
2337 protected function printTable(OutputInterface $output, $results)
2338 {
2339 $table = array();
2340 $rows = array();
2341 foreach ($results as $result) {
2342
2343
2344
2345 list($platformPackage, $version, $link, $status) = $result;
2346 $rows[] = array(
2347 $platformPackage,
2348 $version,
2349 $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '',
2350 $status,
2351 );
2352 }
2353 $table = array_merge($rows, $table);
2354
2355
2356  $renderer = new Table($output);
2357 $renderer->setStyle('compact');
2358 $rendererStyle = $renderer->getStyle();
2359 $rendererStyle->setVerticalBorderChar('');
2360 $rendererStyle->setCellRowContentFormat('%s  ');
2361 $renderer->setRows($table)->render();
2362 }
2363 }
2364 <?php
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376 namespace Composer\Command;
2377
2378 use Composer\Cache;
2379 use Composer\Factory;
2380 use Symfony\Component\Console\Input\InputInterface;
2381 use Symfony\Component\Console\Output\OutputInterface;
2382
2383
2384
2385
2386 class ClearCacheCommand extends BaseCommand
2387 {
2388 protected function configure()
2389 {
2390 $this
2391 ->setName('clear-cache')
2392 ->setAliases(array('clearcache'))
2393 ->setDescription('Clears composer\'s internal package cache.')
2394 ->setHelp(
2395 <<<EOT
2396 The <info>clear-cache</info> deletes all cached packages from composer's
2397 cache directory.
2398
2399 Read more at https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-
2400 EOT
2401 )
2402 ;
2403 }
2404
2405 protected function execute(InputInterface $input, OutputInterface $output)
2406 {
2407 $config = Factory::createConfig();
2408 $io = $this->getIO();
2409
2410 $cachePaths = array(
2411 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2412 'cache-repo-dir' => $config->get('cache-repo-dir'),
2413 'cache-files-dir' => $config->get('cache-files-dir'),
2414 'cache-dir' => $config->get('cache-dir'),
2415 );
2416
2417 foreach ($cachePaths as $key => $cachePath) {
2418 $cachePath = realpath($cachePath);
2419 if (!$cachePath) {
2420 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2421
2422 continue;
2423 }
2424 $cache = new Cache($io, $cachePath);
2425 if (!$cache->isEnabled()) {
2426 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2427
2428 continue;
2429 }
2430
2431 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2432 $cache->clear();
2433 }
2434
2435 $io->writeError('<info>All caches cleared.</info>');
2436
2437 return 0;
2438 }
2439 }
2440 <?php
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452 namespace Composer\Command;
2453
2454 use Composer\Util\Platform;
2455 use Composer\Util\Silencer;
2456 use Symfony\Component\Console\Input\InputInterface;
2457 use Symfony\Component\Console\Input\InputArgument;
2458 use Symfony\Component\Console\Input\InputOption;
2459 use Symfony\Component\Console\Output\OutputInterface;
2460 use Composer\Config;
2461 use Composer\Config\JsonConfigSource;
2462 use Composer\Factory;
2463 use Composer\IO\IOInterface;
2464 use Composer\Json\JsonFile;
2465 use Composer\Semver\VersionParser;
2466 use Composer\Package\BasePackage;
2467
2468
2469
2470
2471
2472 class ConfigCommand extends BaseCommand
2473 {
2474
2475
2476
2477 protected $config;
2478
2479
2480
2481
2482 protected $configFile;
2483
2484
2485
2486
2487 protected $configSource;
2488
2489
2490
2491
2492 protected $authConfigFile;
2493
2494
2495
2496
2497 protected $authConfigSource;
2498
2499
2500
2501
2502 protected function configure()
2503 {
2504 $this
2505 ->setName('config')
2506 ->setDescription('Sets config options.')
2507 ->setDefinition(array(
2508 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2509 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2510 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2511 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2512 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2513 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2514 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2515 new InputArgument('setting-key', null, 'Setting key'),
2516 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2517 ))
2518 ->setHelp(
2519 <<<EOT
2520 This command allows you to edit composer config settings and repositories
2521 in either the local composer.json file or the global config.json file.
2522
2523 Additionally it lets you edit most properties in the local composer.json.
2524
2525 To set a config setting:
2526
2527     <comment>%command.full_name% bin-dir bin/</comment>
2528
2529 To read a config setting:
2530
2531     <comment>%command.full_name% bin-dir</comment>
2532     Outputs: <info>bin</info>
2533
2534 To edit the global config.json file:
2535
2536     <comment>%command.full_name% --global</comment>
2537
2538 To add a repository:
2539
2540     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2541
2542 To remove a repository (repo is a short alias for repositories):
2543
2544     <comment>%command.full_name% --unset repo.foo</comment>
2545
2546 To disable packagist:
2547
2548     <comment>%command.full_name% repo.packagist false</comment>
2549
2550 You can alter repositories in the global config.json file by passing in the
2551 <info>--global</info> option.
2552
2553 To edit the file in an external editor:
2554
2555     <comment>%command.full_name% --editor</comment>
2556
2557 To choose your editor you can set the "EDITOR" env variable.
2558
2559 To get a list of configuration values in the file:
2560
2561     <comment>%command.full_name% --list</comment>
2562
2563 You can always pass more than one option. As an example, if you want to edit the
2564 global config.json file.
2565
2566     <comment>%command.full_name% --editor --global</comment>
2567
2568 Read more at https://getcomposer.org/doc/03-cli.md#config
2569 EOT
2570 )
2571 ;
2572 }
2573
2574
2575
2576
2577 protected function initialize(InputInterface $input, OutputInterface $output)
2578 {
2579 parent::initialize($input, $output);
2580
2581 if ($input->getOption('global') && null !== $input->getOption('file')) {
2582 throw new \RuntimeException('--file and --global can not be combined');
2583 }
2584
2585 $io = $this->getIO();
2586 $this->config = Factory::createConfig($io);
2587
2588
2589  
2590  $configFile = $input->getOption('global')
2591 ? ($this->config->get('home') . '/config.json')
2592 : ($input->getOption('file') ?: Factory::getComposerFile());
2593
2594
2595  if (
2596 ($configFile === 'composer.json' || $configFile === './composer.json')
2597 && !file_exists($configFile)
2598 && realpath(getcwd()) === realpath($this->config->get('home'))
2599 ) {
2600 file_put_contents($configFile, "{\n}\n");
2601 }
2602
2603 $this->configFile = new JsonFile($configFile, null, $io);
2604 $this->configSource = new JsonConfigSource($this->configFile);
2605
2606 $authConfigFile = $input->getOption('global')
2607 ? ($this->config->get('home') . '/auth.json')
2608 : dirname(realpath($configFile)) . '/auth.json';
2609
2610 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2611 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2612
2613
2614  if ($input->getOption('global') && !$this->configFile->exists()) {
2615 touch($this->configFile->getPath());
2616 $this->configFile->write(array('config' => new \ArrayObject));
2617 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2618 }
2619 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2620 touch($this->authConfigFile->getPath());
2621 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2622 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2623 }
2624
2625 if (!$this->configFile->exists()) {
2626 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2627 }
2628 }
2629
2630
2631
2632
2633 protected function execute(InputInterface $input, OutputInterface $output)
2634 {
2635
2636  if ($input->getOption('editor')) {
2637 $editor = escapeshellcmd(getenv('EDITOR'));
2638 if (!$editor) {
2639 if (Platform::isWindows()) {
2640 $editor = 'notepad';
2641 } else {
2642 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2643 if (exec('which '.$candidate)) {
2644 $editor = $candidate;
2645 break;
2646 }
2647 }
2648 }
2649 }
2650
2651 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2652 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2653
2654 return 0;
2655 }
2656
2657 if (!$input->getOption('global')) {
2658 $this->config->merge($this->configFile->read());
2659 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2660 }
2661
2662
2663  if ($input->getOption('list')) {
2664 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2665
2666 return 0;
2667 }
2668
2669 $settingKey = $input->getArgument('setting-key');
2670 if (!$settingKey) {
2671 return 0;
2672 }
2673
2674
2675  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2676 throw new \RuntimeException('You can not combine a setting value with --unset');
2677 }
2678
2679
2680  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2681 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2682 $rawData = $this->configFile->read();
2683 $data = $this->config->all();
2684 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2685 if (!isset($matches[1]) || $matches[1] === '') {
2686 $value = isset($data['repositories']) ? $data['repositories'] : array();
2687 } else {
2688 if (!isset($data['repositories'][$matches[1]])) {
2689 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2690 }
2691
2692 $value = $data['repositories'][$matches[1]];
2693 }
2694 } elseif (strpos($settingKey, '.')) {
2695 $bits = explode('.', $settingKey);
2696 if ($bits[0] === 'extra') {
2697 $data = $rawData;
2698 } else {
2699 $data = $data['config'];
2700 }
2701 $match = false;
2702 foreach ($bits as $bit) {
2703 $key = isset($key) ? $key.'.'.$bit : $bit;
2704 $match = false;
2705 if (isset($data[$key])) {
2706 $match = true;
2707 $data = $data[$key];
2708 unset($key);
2709 }
2710 }
2711
2712 if (!$match) {
2713 throw new \RuntimeException($settingKey.' is not defined.');
2714 }
2715
2716 $value = $data;
2717 } elseif (isset($data['config'][$settingKey])) {
2718 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2719 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2720 $value = $rawData[$settingKey];
2721 } else {
2722 throw new \RuntimeException($settingKey.' is not defined');
2723 }
2724
2725 if (is_array($value)) {
2726 $value = json_encode($value);
2727 }
2728
2729 $this->getIO()->write($value, true, IOInterface::QUIET);
2730
2731 return 0;
2732 }
2733
2734 $values = $input->getArgument('setting-value'); 
2735
2736 $booleanValidator = function ($val) {
2737 return in_array($val, array('true', 'false', '1', '0'), true);
2738 };
2739 $booleanNormalizer = function ($val) {
2740 return $val !== 'false' && (bool) $val;
2741 };
2742
2743
2744  $uniqueConfigValues = array(
2745 'process-timeout' => array('is_numeric', 'intval'),
2746 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2747 'use-github-api' => array($booleanValidator, $booleanNormalizer),
2748 'preferred-install' => array(
2749 function ($val) {
2750 return in_array($val, array('auto', 'source', 'dist'), true);
2751 },
2752 function ($val) {
2753 return $val;
2754 },
2755 ),
2756 'store-auths' => array(
2757 function ($val) {
2758 return in_array($val, array('true', 'false', 'prompt'), true);
2759 },
2760 function ($val) {
2761 if ('prompt' === $val) {
2762 return 'prompt';
2763 }
2764
2765 return $val !== 'false' && (bool) $val;
2766 },
2767 ),
2768 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2769 'vendor-dir' => array('is_string', function ($val) {
2770 return $val;
2771 }),
2772 'bin-dir' => array('is_string', function ($val) {
2773 return $val;
2774 }),
2775 'archive-dir' => array('is_string', function ($val) {
2776 return $val;
2777 }),
2778 'archive-format' => array('is_string', function ($val) {
2779 return $val;
2780 }),
2781 'data-dir' => array('is_string', function ($val) {
2782 return $val;
2783 }),
2784 'cache-dir' => array('is_string', function ($val) {
2785 return $val;
2786 }),
2787 'cache-files-dir' => array('is_string', function ($val) {
2788 return $val;
2789 }),
2790 'cache-repo-dir' => array('is_string', function ($val) {
2791 return $val;
2792 }),
2793 'cache-vcs-dir' => array('is_string', function ($val) {
2794 return $val;
2795 }),
2796 'cache-ttl' => array('is_numeric', 'intval'),
2797 'cache-files-ttl' => array('is_numeric', 'intval'),
2798 'cache-files-maxsize' => array(
2799 function ($val) {
2800 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2801 },
2802 function ($val) {
2803 return $val;
2804 },
2805 ),
2806 'bin-compat' => array(
2807 function ($val) {
2808 return in_array($val, array('auto', 'full'));
2809 },
2810 function ($val) {
2811 return $val;
2812 },
2813 ),
2814 'discard-changes' => array(
2815 function ($val) {
2816 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2817 },
2818 function ($val) {
2819 if ('stash' === $val) {
2820 return 'stash';
2821 }
2822
2823 return $val !== 'false' && (bool) $val;
2824 },
2825 ),
2826 'autoloader-suffix' => array('is_string', function ($val) {
2827 return $val === 'null' ? null : $val;
2828 }),
2829 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2830 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2831 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2832 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2833 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2834 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2835 'secure-http' => array($booleanValidator, $booleanNormalizer),
2836 'cafile' => array(
2837 function ($val) {
2838 return file_exists($val) && is_readable($val);
2839 },
2840 function ($val) {
2841 return $val === 'null' ? null : $val;
2842 },
2843 ),
2844 'capath' => array(
2845 function ($val) {
2846 return is_dir($val) && is_readable($val);
2847 },
2848 function ($val) {
2849 return $val === 'null' ? null : $val;
2850 },
2851 ),
2852 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2853 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2854 );
2855 $multiConfigValues = array(
2856 'github-protocols' => array(
2857 function ($vals) {
2858 if (!is_array($vals)) {
2859 return 'array expected';
2860 }
2861
2862 foreach ($vals as $val) {
2863 if (!in_array($val, array('git', 'https', 'ssh'))) {
2864 return 'valid protocols include: git, https, ssh';
2865 }
2866 }
2867
2868 return true;
2869 },
2870 function ($vals) {
2871 return $vals;
2872 },
2873 ),
2874 'github-domains' => array(
2875 function ($vals) {
2876 if (!is_array($vals)) {
2877 return 'array expected';
2878 }
2879
2880 return true;
2881 },
2882 function ($vals) {
2883 return $vals;
2884 },
2885 ),
2886 'gitlab-domains' => array(
2887 function ($vals) {
2888 if (!is_array($vals)) {
2889 return 'array expected';
2890 }
2891
2892 return true;
2893 },
2894 function ($vals) {
2895 return $vals;
2896 },
2897 ),
2898 );
2899
2900 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2901 if ($settingKey === 'disable-tls' && $this->config->get('disable-tls')) {
2902 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
2903 }
2904
2905 $this->configSource->removeConfigSetting($settingKey);
2906
2907 return 0;
2908 }
2909 if (isset($uniqueConfigValues[$settingKey])) {
2910 $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2911
2912 return 0;
2913 }
2914 if (isset($multiConfigValues[$settingKey])) {
2915 $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2916
2917 return 0;
2918 }
2919
2920
2921  $uniqueProps = array(
2922 'name' => array('is_string', function ($val) {
2923 return $val;
2924 }),
2925 'type' => array('is_string', function ($val) {
2926 return $val;
2927 }),
2928 'description' => array('is_string', function ($val) {
2929 return $val;
2930 }),
2931 'homepage' => array('is_string', function ($val) {
2932 return $val;
2933 }),
2934 'version' => array('is_string', function ($val) {
2935 return $val;
2936 }),
2937 'minimum-stability' => array(
2938 function ($val) {
2939 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2940 },
2941 function ($val) {
2942 return VersionParser::normalizeStability($val);
2943 },
2944 ),
2945 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2946 );
2947 $multiProps = array(
2948 'keywords' => array(
2949 function ($vals) {
2950 if (!is_array($vals)) {
2951 return 'array expected';
2952 }
2953
2954 return true;
2955 },
2956 function ($vals) {
2957 return $vals;
2958 },
2959 ),
2960 'license' => array(
2961 function ($vals) {
2962 if (!is_array($vals)) {
2963 return 'array expected';
2964 }
2965
2966 return true;
2967 },
2968 function ($vals) {
2969 return $vals;
2970 },
2971 ),
2972 );
2973
2974 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2975 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');
2976 }
2977 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2978 $this->configSource->removeProperty($settingKey);
2979
2980 return 0;
2981 }
2982 if (isset($uniqueProps[$settingKey])) {
2983 $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2984
2985 return 0;
2986 }
2987 if (isset($multiProps[$settingKey])) {
2988 $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2989
2990 return 0;
2991 }
2992
2993
2994  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2995 if ($input->getOption('unset')) {
2996 $this->configSource->removeRepository($matches[1]);
2997
2998 return 0;
2999 }
3000
3001 if (2 === count($values)) {
3002 $this->configSource->addRepository($matches[1], array(
3003 'type' => $values[0],
3004 'url' => $values[1],
3005 ));
3006
3007 return 0;
3008 }
3009
3010 if (1 === count($values)) {
3011 $value = strtolower($values[0]);
3012 if (true === $booleanValidator($value)) {
3013 if (false === $booleanNormalizer($value)) {
3014 $this->configSource->addRepository($matches[1], false);
3015
3016 return 0;
3017 }
3018 } else {
3019 $value = JsonFile::parseJson($values[0]);
3020 $this->configSource->addRepository($matches[1], $value);
3021
3022 return 0;
3023 }
3024 }
3025
3026 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
3027 }
3028
3029
3030  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
3031 if ($input->getOption('unset')) {
3032 $this->configSource->removeProperty($settingKey);
3033
3034 return 0;
3035 }
3036
3037 $this->configSource->addProperty($settingKey, $values[0]);
3038
3039 return 0;
3040 }
3041
3042
3043  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
3044 if ($input->getOption('unset')) {
3045 $this->configSource->removeConfigSetting($settingKey);
3046
3047 return 0;
3048 }
3049
3050 $this->configSource->addConfigSetting($settingKey, $values[0]);
3051
3052 return 0;
3053 }
3054 if ($settingKey === 'platform' && $input->getOption('unset')) {
3055 $this->configSource->removeConfigSetting($settingKey);
3056
3057 return 0;
3058 }
3059
3060
3061  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
3062 if ($input->getOption('unset')) {
3063 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3064 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3065
3066 return 0;
3067 }
3068
3069 if ($matches[1] === 'bitbucket-oauth') {
3070 if (2 !== count($values)) {
3071 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
3072 }
3073 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3074 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
3075 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
3076 if (1 !== count($values)) {
3077 throw new \RuntimeException('Too many arguments, expected only one token');
3078 }
3079 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3080 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
3081 } elseif ($matches[1] === 'http-basic') {
3082 if (2 !== count($values)) {
3083 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
3084 }
3085 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3086 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
3087 }
3088
3089 return 0;
3090 }
3091
3092
3093  if (preg_match('/^scripts\.(.+)/', $settingKey, $matches)) {
3094 if ($input->getOption('unset')) {
3095 $this->configSource->removeProperty($settingKey);
3096
3097 return 0;
3098 }
3099
3100 $this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
3101
3102 return 0;
3103 }
3104
3105 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
3106 }
3107
3108 protected function handleSingleValue($key, array $callbacks, array $values, $method)
3109 {
3110 list($validator, $normalizer) = $callbacks;
3111 if (1 !== count($values)) {
3112 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
3113 }
3114
3115 if (true !== $validation = $validator($values[0])) {
3116 throw new \RuntimeException(sprintf(
3117 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3118 $values[0]
3119 ));
3120 }
3121
3122 $normalizedValue = $normalizer($values[0]);
3123
3124 if ($key === 'disable-tls') {
3125 if (!$normalizedValue && $this->config->get('disable-tls')) {
3126 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
3127 } elseif ($normalizedValue && !$this->config->get('disable-tls')) {
3128 $this->getIO()->writeError('<warning>You are now running Composer with SSL/TLS protection disabled.</warning>');
3129 }
3130 }
3131
3132 return call_user_func(array($this->configSource, $method), $key, $normalizedValue);
3133 }
3134
3135 protected function handleMultiValue($key, array $callbacks, array $values, $method)
3136 {
3137 list($validator, $normalizer) = $callbacks;
3138 if (true !== $validation = $validator($values)) {
3139 throw new \RuntimeException(sprintf(
3140 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3141 json_encode($values)
3142 ));
3143 }
3144
3145 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
3146 }
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
3157 {
3158 $origK = $k;
3159 $io = $this->getIO();
3160 foreach ($contents as $key => $value) {
3161 if ($k === null && !in_array($key, array('config', 'repositories'))) {
3162 continue;
3163 }
3164
3165 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
3166
3167 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
3168 $k .= preg_replace('{^config\.}', '', $key . '.');
3169 $this->listConfiguration($value, $rawVal, $output, $k);
3170 $k = $origK;
3171
3172 continue;
3173 }
3174
3175 if (is_array($value)) {
3176 $value = array_map(function ($val) {
3177 return is_array($val) ? json_encode($val) : $val;
3178 }, $value);
3179
3180 $value = '['.implode(', ', $value).']';
3181 }
3182
3183 if (is_bool($value)) {
3184 $value = var_export($value, true);
3185 }
3186
3187 if (is_string($rawVal) && $rawVal != $value) {
3188 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>', true, IOInterface::QUIET);
3189 } else {
3190 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>', true, IOInterface::QUIET);
3191 }
3192 }
3193 }
3194 }
3195 <?php
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207 namespace Composer\Command;
3208
3209 use Composer\Config;
3210 use Composer\Factory;
3211 use Composer\Installer;
3212 use Composer\Installer\ProjectInstaller;
3213 use Composer\Installer\InstallationManager;
3214 use Composer\Installer\SuggestedPackagesReporter;
3215 use Composer\IO\IOInterface;
3216 use Composer\Package\BasePackage;
3217 use Composer\DependencyResolver\Pool;
3218 use Composer\DependencyResolver\Operation\InstallOperation;
3219 use Composer\Package\Version\VersionSelector;
3220 use Composer\Package\AliasPackage;
3221 use Composer\Repository\RepositoryFactory;
3222 use Composer\Repository\CompositeRepository;
3223 use Composer\Repository\PlatformRepository;
3224 use Composer\Repository\InstalledFilesystemRepository;
3225 use Composer\Script\ScriptEvents;
3226 use Composer\Util\Silencer;
3227 use Symfony\Component\Console\Input\InputArgument;
3228 use Symfony\Component\Console\Input\InputInterface;
3229 use Symfony\Component\Console\Input\InputOption;
3230 use Symfony\Component\Console\Output\OutputInterface;
3231 use Symfony\Component\Finder\Finder;
3232 use Composer\Json\JsonFile;
3233 use Composer\Config\JsonConfigSource;
3234 use Composer\Util\Filesystem;
3235 use Composer\Package\Version\VersionParser;
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245 class CreateProjectCommand extends BaseCommand
3246 {
3247
3248
3249
3250 protected $suggestedPackagesReporter;
3251
3252 protected function configure()
3253 {
3254 $this
3255 ->setName('create-project')
3256 ->setDescription('Creates new project from a package into given directory.')
3257 ->setDefinition(array(
3258 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
3259 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
3260 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
3261 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
3262 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
3263 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
3264 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
3265 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
3266 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
3267 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
3268 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
3269 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
3270 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
3271 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.'),
3272 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'),
3273 new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'),
3274 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
3275 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
3276 ))
3277 ->setHelp(
3278 <<<EOT
3279 The <info>create-project</info> command creates a new project from a given
3280 package into a new directory. If executed without params and in a directory
3281 with a composer.json file it installs the packages for the current project.
3282
3283 You can use this command to bootstrap new projects or setup a clean
3284 version-controlled installation for developers of your project.
3285
3286 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3287
3288 You can also specify the version with the package name using = or : as separator.
3289
3290 <info>php composer.phar create-project vendor/project:version target-directory</info>
3291
3292 To install unstable packages, either specify the version you want, or use the
3293 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3294
3295 To setup a developer workable version you should create the project using the source
3296 controlled code by appending the <info>'--prefer-source'</info> flag.
3297
3298 To install a package from another repository than the default one you
3299 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3300
3301 Read more at https://getcomposer.org/doc/03-cli.md#create-project
3302 EOT
3303 )
3304 ;
3305 }
3306
3307 protected function execute(InputInterface $input, OutputInterface $output)
3308 {
3309 $config = Factory::createConfig();
3310 $io = $this->getIO();
3311
3312 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3313
3314 if ($input->getOption('dev')) {
3315 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3316 }
3317 if ($input->getOption('no-custom-installers')) {
3318 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3319 $input->setOption('no-plugins', true);
3320 }
3321
3322 return $this->installProject(
3323 $io,
3324 $config,
3325 $input,
3326 $input->getArgument('package'),
3327 $input->getArgument('directory'),
3328 $input->getArgument('version'),
3329 $input->getOption('stability'),
3330 $preferSource,
3331 $preferDist,
3332 !$input->getOption('no-dev'),
3333 $input->getOption('repository') ?: $input->getOption('repository-url'),
3334 $input->getOption('no-plugins'),
3335 $input->getOption('no-scripts'),
3336 $input->getOption('no-progress'),
3337 $input->getOption('no-install'),
3338 $input->getOption('ignore-platform-reqs'),
3339 !$input->getOption('no-secure-http')
3340 );
3341 }
3342
3343 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)
3344 {
3345 $oldCwd = getcwd();
3346
3347
3348  $io->loadConfiguration($config);
3349
3350 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3351
3352 if ($packageName !== null) {
3353 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
3354 } else {
3355 $installedFromVcs = false;
3356 }
3357
3358 $composer = Factory::create($io, null, $disablePlugins);
3359 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3360
3361 $fs = new Filesystem();
3362
3363 if ($noScripts === false) {
3364
3365  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3366 }
3367
3368
3369  $config = $composer->getConfig();
3370 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3371
3372
3373  if ($noInstall === false) {
3374 $installer = Installer::create($io, $composer);
3375 $installer->setPreferSource($preferSource)
3376 ->setPreferDist($preferDist)
3377 ->setDevMode($installDevPackages)
3378 ->setRunScripts(!$noScripts)
3379 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3380 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3381 ->setOptimizeAutoloader($config->get('optimize-autoloader'))
3382 ->setClassMapAuthoritative($config->get('classmap-authoritative'))
3383 ->setApcuAutoloader($config->get('apcu-autoloader'));
3384
3385 if ($disablePlugins) {
3386 $installer->disablePlugins();
3387 }
3388
3389 $status = $installer->run();
3390 if (0 !== $status) {
3391 return $status;
3392 }
3393 }
3394
3395 $hasVcs = $installedFromVcs;
3396 if (
3397 !$input->getOption('keep-vcs')
3398 && $installedFromVcs
3399 && (
3400 $input->getOption('remove-vcs')
3401 || !$io->isInteractive()
3402 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3403 )
3404 ) {
3405 $finder = new Finder();
3406 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3407 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3408 $finder->name($vcsName);
3409 }
3410
3411 try {
3412 $dirs = iterator_to_array($finder);
3413 unset($finder);
3414 foreach ($dirs as $dir) {
3415 if (!$fs->removeDirectory($dir)) {
3416 throw new \RuntimeException('Could not remove '.$dir);
3417 }
3418 }
3419 } catch (\Exception $e) {
3420 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3421 }
3422
3423 $hasVcs = false;
3424 }
3425
3426
3427  if (!$hasVcs) {
3428 $package = $composer->getPackage();
3429 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3430 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3431 foreach ($package->{'get'.$meta['method']}() as $link) {
3432 if ($link->getPrettyConstraint() === 'self.version') {
3433 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3434 }
3435 }
3436 }
3437 }
3438
3439 if ($noScripts === false) {
3440
3441  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3442 }
3443
3444 chdir($oldCwd);
3445 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3446 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3447 Silencer::call('rmdir', $vendorComposerDir);
3448 $vendorDir = $config->get('vendor-dir');
3449 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3450 Silencer::call('rmdir', $vendorDir);
3451 }
3452 }
3453
3454 return 0;
3455 }
3456
3457 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)
3458 {
3459 if (!$secureHttp) {
3460 $config->merge(array('config' => array('secure-http' => false)));
3461 }
3462
3463 if (null === $repository) {
3464 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3465 } else {
3466 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3467 }
3468
3469 $parser = new VersionParser();
3470 $requirements = $parser->parseNameVersionPairs(array($packageName));
3471 $name = strtolower($requirements[0]['name']);
3472 if (!$packageVersion && isset($requirements[0]['version'])) {
3473 $packageVersion = $requirements[0]['version'];
3474 }
3475
3476 if (null === $stability) {
3477 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3478 $stability = $match[1];
3479 } else {
3480 $stability = VersionParser::parseStability($packageVersion);
3481 }
3482 }
3483
3484 $stability = VersionParser::normalizeStability($stability);
3485
3486 if (!isset(BasePackage::$stabilities[$stability])) {
3487 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3488 }
3489
3490 $pool = new Pool($stability);
3491 $pool->addRepository($sourceRepo);
3492
3493 $phpVersion = null;
3494 $prettyPhpVersion = null;
3495 if (!$ignorePlatformReqs) {
3496 $platformOverrides = $config->get('platform') ?: array();
3497
3498  $platform = new PlatformRepository(array(), $platformOverrides);
3499 $phpPackage = $platform->findPackage('php', '*');
3500 $phpVersion = $phpPackage->getVersion();
3501 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3502 }
3503
3504
3505  $versionSelector = new VersionSelector($pool);
3506 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3507
3508 if (!$package) {
3509 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3510 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3511 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3512 }
3513
3514 throw new \InvalidArgumentException($errorMessage .'.');
3515 }
3516
3517 if (null === $directory) {
3518 $parts = explode("/", $name, 2);
3519 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3520 }
3521
3522
3523  if (function_exists('pcntl_async_signals')) {
3524 @mkdir($directory, 0777, true);
3525 if ($realDir = realpath($directory)) {
3526 pcntl_async_signals(true);
3527 pcntl_signal(SIGINT, function () use ($realDir) {
3528 $fs = new Filesystem();
3529 $fs->removeDirectory($realDir);
3530 exit(130);
3531 });
3532 }
3533 }
3534
3535 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3536
3537 if ($disablePlugins) {
3538 $io->writeError('<info>Plugins have been disabled.</info>');
3539 }
3540
3541 if ($package instanceof AliasPackage) {
3542 $package = $package->getAliasOf();
3543 }
3544
3545 $dm = $this->createDownloadManager($io, $config);
3546 $dm->setPreferSource($preferSource)
3547 ->setPreferDist($preferDist)
3548 ->setOutputProgress(!$noProgress);
3549
3550 $projectInstaller = new ProjectInstaller($directory, $dm);
3551 $im = $this->createInstallationManager();
3552 $im->addInstaller($projectInstaller);
3553 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3554 $im->notifyInstalls($io);
3555
3556
3557  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3558
3559 $installedFromVcs = 'source' === $package->getInstallationSource();
3560
3561 $io->writeError('<info>Created project in ' . $directory . '</info>');
3562 chdir($directory);
3563
3564 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3565 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3566
3567 return $installedFromVcs;
3568 }
3569
3570 protected function createDownloadManager(IOInterface $io, Config $config)
3571 {
3572 $factory = new Factory();
3573
3574 return $factory->createDownloadManager($io, $config);
3575 }
3576
3577 protected function createInstallationManager()
3578 {
3579 return new InstallationManager();
3580 }
3581 }
3582 <?php
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594 namespace Composer\Command;
3595
3596 use Symfony\Component\Console\Input\InputInterface;
3597 use Symfony\Component\Console\Output\OutputInterface;
3598
3599
3600
3601
3602 class DependsCommand extends BaseDependencyCommand
3603 {
3604
3605
3606
3607 protected function configure()
3608 {
3609 parent::configure();
3610
3611 $this
3612 ->setName('depends')
3613 ->setAliases(array('why'))
3614 ->setDescription('Shows which packages cause the given package to be installed.')
3615 ->setHelp(
3616 <<<EOT
3617 Displays detailed information about where a package is referenced.
3618
3619 <info>php composer.phar depends composer/composer</info>
3620
3621 Read more at https://getcomposer.org/doc/03-cli.md#depends-why-
3622 EOT
3623 )
3624 ;
3625 }
3626
3627
3628
3629
3630
3631
3632
3633
3634 protected function execute(InputInterface $input, OutputInterface $output)
3635 {
3636 return parent::doExecute($input, $output, false);
3637 }
3638 }
3639 <?php
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651 namespace Composer\Command;
3652
3653 use Composer\Composer;
3654 use Composer\Factory;
3655 use Composer\Config;
3656 use Composer\Downloader\TransportException;
3657 use Composer\Repository\PlatformRepository;
3658 use Composer\Plugin\CommandEvent;
3659 use Composer\Plugin\PluginEvents;
3660 use Composer\Util\ConfigValidator;
3661 use Composer\Util\IniHelper;
3662 use Composer\Util\ProcessExecutor;
3663 use Composer\Util\RemoteFilesystem;
3664 use Composer\Util\StreamContextFactory;
3665 use Composer\SelfUpdate\Keys;
3666 use Composer\SelfUpdate\Versions;
3667 use Composer\IO\NullIO;
3668 use Symfony\Component\Console\Input\InputInterface;
3669 use Symfony\Component\Console\Output\OutputInterface;
3670
3671
3672
3673
3674 class DiagnoseCommand extends BaseCommand
3675 {
3676
3677 protected $rfs;
3678
3679
3680 protected $process;
3681
3682
3683 protected $exitCode = 0;
3684
3685 protected function configure()
3686 {
3687 $this
3688 ->setName('diagnose')
3689 ->setDescription('Diagnoses the system to identify common errors.')
3690 ->setHelp(
3691 <<<EOT
3692 The <info>diagnose</info> command checks common errors to help debugging problems.
3693
3694 The process exit code will be 1 in case of warnings and 2 for errors.
3695
3696 Read more at https://getcomposer.org/doc/03-cli.md#diagnose
3697 EOT
3698 )
3699 ;
3700 }
3701
3702
3703
3704
3705 protected function execute(InputInterface $input, OutputInterface $output)
3706 {
3707 $composer = $this->getComposer(false);
3708 $io = $this->getIO();
3709
3710 if ($composer) {
3711 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3712 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3713
3714 $io->write('Checking composer.json: ', false);
3715 $this->outputResult($this->checkComposerSchema());
3716 }
3717
3718 if ($composer) {
3719 $config = $composer->getConfig();
3720 } else {
3721 $config = Factory::createConfig();
3722 }
3723
3724 $config->merge(array('config' => array('secure-http' => false)));
3725 $config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO);
3726
3727 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3728 $this->process = new ProcessExecutor($io);
3729
3730 $io->write('Checking platform settings: ', false);
3731 $this->outputResult($this->checkPlatform());
3732
3733 $io->write('Checking git settings: ', false);
3734 $this->outputResult($this->checkGit());
3735
3736 $io->write('Checking http connectivity to packagist: ', false);
3737 $this->outputResult($this->checkHttp('http', $config));
3738
3739 $io->write('Checking https connectivity to packagist: ', false);
3740 $this->outputResult($this->checkHttp('https', $config));
3741
3742 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3743 if (!empty($opts['http']['proxy'])) {
3744 $io->write('Checking HTTP proxy: ', false);
3745 $this->outputResult($this->checkHttpProxy());
3746 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3747 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3748 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3749 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3750 }
3751
3752 if ($oauth = $config->get('github-oauth')) {
3753 foreach ($oauth as $domain => $token) {
3754 $io->write('Checking '.$domain.' oauth access: ', false);
3755 $this->outputResult($this->checkGithubOauth($domain, $token));
3756 }
3757 } else {
3758 $io->write('Checking github.com rate limit: ', false);
3759 try {
3760 $rate = $this->getGithubRateLimit('github.com');
3761 if (!is_array($rate)) {
3762 $this->outputResult($rate);
3763 } elseif (10 > $rate['remaining']) {
3764 $io->write('<warning>WARNING</warning>');
3765 $io->write(sprintf(
3766 '<comment>Github has a rate limit on their API. '
3767 . 'You currently have <options=bold>%u</options=bold> '
3768 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3769 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3770 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3771 $rate['remaining'],
3772 $rate['limit']
3773 ));
3774 } else {
3775 $this->outputResult(true);
3776 }
3777 } catch (\Exception $e) {
3778 if ($e instanceof TransportException && $e->getCode() === 401) {
3779 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3780 } else {
3781 $this->outputResult($e);
3782 }
3783 }
3784 }
3785
3786 $io->write('Checking disk free space: ', false);
3787 $this->outputResult($this->checkDiskSpace($config));
3788
3789 if ('phar:' === substr(__FILE__, 0, 5)) {
3790 $io->write('Checking pubkeys: ', false);
3791 $this->outputResult($this->checkPubKeys($config));
3792
3793 $io->write('Checking composer version: ', false);
3794 $this->outputResult($this->checkVersion($config));
3795 }
3796
3797 $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::VERSION));
3798
3799 $platformOverrides = $config->get('platform') ?: array();
3800 $platformRepo = new PlatformRepository(array(), $platformOverrides);
3801 $phpPkg = $platformRepo->findPackage('php', '*');
3802 $phpVersion = $phpPkg->getPrettyVersion();
3803 if (false !== strpos($phpPkg->getDescription(), 'overridden')) {
3804 $phpVersion .= ' - ' . $phpPkg->getDescription();
3805 }
3806
3807 $io->write(sprintf('PHP version: <comment>%s</comment>', $phpVersion));
3808
3809 if (defined('PHP_BINARY')) {
3810 $io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
3811 }
3812
3813 return $this->exitCode;
3814 }
3815
3816 private function checkComposerSchema()
3817 {
3818 $validator = new ConfigValidator($this->getIO());
3819 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3820
3821 if ($errors || $warnings) {
3822 $messages = array(
3823 'error' => $errors,
3824 'warning' => $warnings,
3825 );
3826
3827 $output = '';
3828 foreach ($messages as $style => $msgs) {
3829 foreach ($msgs as $msg) {
3830 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3831 }
3832 }
3833
3834 return rtrim($output);
3835 }
3836
3837 return true;
3838 }
3839
3840 private function checkGit()
3841 {
3842 $this->process->execute('git config color.ui', $output);
3843 if (strtolower(trim($output)) === 'always') {
3844 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>';
3845 }
3846
3847 return true;
3848 }
3849
3850 private function checkHttp($proto, Config $config)
3851 {
3852 $result = $this->checkConnectivity();
3853 if ($result !== true) {
3854 return $result;
3855 }
3856
3857 $disableTls = false;
3858 $result = array();
3859 if ($proto === 'https' && $config->get('disable-tls') === true) {
3860 $disableTls = true;
3861 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3862 }
3863 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3864 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3865 }
3866
3867 try {
3868 $this->rfs->getContents('packagist.org', $proto . '://repo.packagist.org/packages.json', false);
3869 } catch (TransportException $e) {
3870 if (false !== strpos($e->getMessage(), 'cafile')) {
3871 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3872 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3873 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3874 } else {
3875 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3876 }
3877 }
3878
3879 if (count($result) > 0) {
3880 return $result;
3881 }
3882
3883 return true;
3884 }
3885
3886 private function checkHttpProxy()
3887 {
3888 $result = $this->checkConnectivity();
3889 if ($result !== true) {
3890 return $result;
3891 }
3892
3893 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3894 try {
3895 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/packages.json', false), true);
3896 $hash = reset($json['provider-includes']);
3897 $hash = $hash['sha256'];
3898 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3899 $provider = $this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/'.$path, false);
3900
3901 if (hash('sha256', $provider) !== $hash) {
3902 return 'It seems that your proxy is modifying http traffic on the fly';
3903 }
3904 } catch (\Exception $e) {
3905 return $e;
3906 }
3907
3908 return true;
3909 }
3910
3911
3912
3913
3914
3915
3916
3917
3918 private function checkHttpProxyFullUriRequestParam()
3919 {
3920 $result = $this->checkConnectivity();
3921 if ($result !== true) {
3922 return $result;
3923 }
3924
3925 $url = 'http://repo.packagist.org/packages.json';
3926 try {
3927 $this->rfs->getContents('packagist.org', $url, false);
3928 } catch (TransportException $e) {
3929 try {
3930 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3931 } catch (TransportException $e) {
3932 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3933 }
3934
3935 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"';
3936 }
3937
3938 return true;
3939 }
3940
3941
3942
3943
3944
3945
3946
3947
3948 private function checkHttpsProxyFullUriRequestParam()
3949 {
3950 $result = $this->checkConnectivity();
3951 if ($result !== true) {
3952 return $result;
3953 }
3954
3955 if (!extension_loaded('openssl')) {
3956 return 'You need the openssl extension installed for this check';
3957 }
3958
3959 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3960 try {
3961 $this->rfs->getContents('github.com', $url, false);
3962 } catch (TransportException $e) {
3963 try {
3964 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3965 } catch (TransportException $e) {
3966 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3967 }
3968
3969 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3970 }
3971
3972 return true;
3973 }
3974
3975 private function checkGithubOauth($domain, $token)
3976 {
3977 $result = $this->checkConnectivity();
3978 if ($result !== true) {
3979 return $result;
3980 }
3981
3982 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3983 try {
3984 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3985
3986 return $this->rfs->getContents($domain, $url, false, array(
3987 'retry-auth-failure' => false,
3988 )) ? true : 'Unexpected error';
3989 } catch (\Exception $e) {
3990 if ($e instanceof TransportException && $e->getCode() === 401) {
3991 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3992 }
3993
3994 return $e;
3995 }
3996 }
3997
3998
3999
4000
4001
4002
4003
4004 private function getGithubRateLimit($domain, $token = null)
4005 {
4006 $result = $this->checkConnectivity();
4007 if ($result !== true) {
4008 return $result;
4009 }
4010
4011 if ($token) {
4012 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
4013 }
4014
4015 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
4016 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
4017 $data = json_decode($json, true);
4018
4019 return $data['resources']['core'];
4020 }
4021
4022 private function checkDiskSpace($config)
4023 {
4024 $minSpaceFree = 1024 * 1024;
4025 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
4026 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
4027 ) {
4028 return '<error>The disk hosting '.$dir.' is full</error>';
4029 }
4030
4031 return true;
4032 }
4033
4034 private function checkPubKeys($config)
4035 {
4036 $home = $config->get('home');
4037 $errors = array();
4038 $io = $this->getIO();
4039
4040 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
4041 $io->write('');
4042 }
4043
4044 if (file_exists($home.'/keys.tags.pub')) {
4045 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
4046 } else {
4047 $errors[] = '<error>Missing pubkey for tags verification</error>';
4048 }
4049
4050 if (file_exists($home.'/keys.dev.pub')) {
4051 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
4052 } else {
4053 $errors[] = '<error>Missing pubkey for dev verification</error>';
4054 }
4055
4056 if ($errors) {
4057 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
4058 }
4059
4060 return $errors ?: true;
4061 }
4062
4063 private function checkVersion($config)
4064 {
4065 $result = $this->checkConnectivity();
4066 if ($result !== true) {
4067 return $result;
4068 }
4069
4070 $versionsUtil = new Versions($config, $this->rfs);
4071 $latest = $versionsUtil->getLatest();
4072
4073 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
4074 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
4075 }
4076
4077 return true;
4078 }
4079
4080
4081
4082
4083 private function outputResult($result)
4084 {
4085 $io = $this->getIO();
4086 if (true === $result) {
4087 $io->write('<info>OK</info>');
4088
4089 return;
4090 }
4091
4092 $hadError = false;
4093 $hadWarning = false;
4094 if ($result instanceof \Exception) {
4095 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
4096 }
4097
4098 if (!$result) {
4099
4100  $hadError = true;
4101 } else {
4102 if (!is_array($result)) {
4103 $result = array($result);
4104 }
4105 foreach ($result as $message) {
4106 if (false !== strpos($message, '<error>')) {
4107 $hadError = true;
4108 } elseif (false !== strpos($message, '<warning>')) {
4109 $hadWarning = true;
4110 }
4111 }
4112 }
4113
4114 if ($hadError) {
4115 $io->write('<error>FAIL</error>');
4116 $this->exitCode = max($this->exitCode, 2);
4117 } elseif ($hadWarning) {
4118 $io->write('<warning>WARNING</warning>');
4119 $this->exitCode = max($this->exitCode, 1);
4120 }
4121
4122 if ($result) {
4123 foreach ($result as $message) {
4124 $io->write($message);
4125 }
4126 }
4127 }
4128
4129 private function checkPlatform()
4130 {
4131 $output = '';
4132 $out = function ($msg, $style) use (&$output) {
4133 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
4134 };
4135
4136
4137  $errors = array();
4138 $warnings = array();
4139 $displayIniMessage = false;
4140
4141 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
4142 $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.';
4143
4144 if (!function_exists('json_decode')) {
4145 $errors['json'] = true;
4146 }
4147
4148 if (!extension_loaded('Phar')) {
4149 $errors['phar'] = true;
4150 }
4151
4152 if (!extension_loaded('filter')) {
4153 $errors['filter'] = true;
4154 }
4155
4156 if (!extension_loaded('hash')) {
4157 $errors['hash'] = true;
4158 }
4159
4160 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
4161 $errors['iconv_mbstring'] = true;
4162 }
4163
4164 if (!filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
4165 $errors['allow_url_fopen'] = true;
4166 }
4167
4168 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
4169 $errors['ioncube'] = ioncube_loader_version();
4170 }
4171
4172 if (PHP_VERSION_ID < 50302) {
4173 $errors['php'] = PHP_VERSION;
4174 }
4175
4176 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
4177 $warnings['php'] = PHP_VERSION;
4178 }
4179
4180 if (!extension_loaded('openssl')) {
4181 $errors['openssl'] = true;
4182 }
4183
4184 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
4185 $warnings['openssl_version'] = true;
4186 }
4187
4188 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) {
4189 $warnings['apc_cli'] = true;
4190 }
4191
4192 if (!extension_loaded('zlib')) {
4193 $warnings['zlib'] = true;
4194 }
4195
4196 ob_start();
4197 phpinfo(INFO_GENERAL);
4198 $phpinfo = ob_get_clean();
4199 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
4200 $configure = $match[1];
4201
4202 if (false !== strpos($configure, '--enable-sigchild')) {
4203 $warnings['sigchild'] = true;
4204 }
4205
4206 if (false !== strpos($configure, '--with-curlwrappers')) {
4207 $warnings['curlwrappers'] = true;
4208 }
4209 }
4210
4211 if (filter_var(ini_get('xdebug.profiler_enabled'), FILTER_VALIDATE_BOOLEAN)) {
4212 $warnings['xdebug_profile'] = true;
4213 } elseif (extension_loaded('xdebug')) {
4214 $warnings['xdebug_loaded'] = true;
4215 }
4216
4217 if (!empty($errors)) {
4218 foreach ($errors as $error => $current) {
4219 switch ($error) {
4220 case 'json':
4221 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
4222 $text .= "Install it or recompile php without --disable-json";
4223 break;
4224
4225 case 'phar':
4226 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
4227 $text .= "Install it or recompile php without --disable-phar";
4228 break;
4229
4230 case 'filter':
4231 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
4232 $text .= "Install it or recompile php without --disable-filter";
4233 break;
4234
4235 case 'hash':
4236 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
4237 $text .= "Install it or recompile php without --disable-hash";
4238 break;
4239
4240 case 'iconv_mbstring':
4241 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
4242 $text .= "Install either of them or recompile php without --disable-iconv";
4243 break;
4244
4245 case 'unicode':
4246 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
4247 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4248 $text .= "    detect_unicode = Off";
4249 $displayIniMessage = true;
4250 break;
4251
4252 case 'suhosin':
4253 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
4254 $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;
4255 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
4256 $displayIniMessage = true;
4257 break;
4258
4259 case 'php':
4260 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
4261 break;
4262
4263 case 'allow_url_fopen':
4264 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
4265 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4266 $text .= "    allow_url_fopen = On";
4267 $displayIniMessage = true;
4268 break;
4269
4270 case 'ioncube':
4271 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
4272 $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;
4273 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
4274 $displayIniMessage = true;
4275 break;
4276
4277 case 'openssl':
4278 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
4279 $text .= "If possible you should enable it or recompile php with --with-openssl";
4280 break;
4281 }
4282 $out($text, 'error');
4283 }
4284
4285 $output .= PHP_EOL;
4286 }
4287
4288 if (!empty($warnings)) {
4289 foreach ($warnings as $warning => $current) {
4290 switch ($warning) {
4291 case 'apc_cli':
4292 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
4293 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4294 $text .= "  apc.enable_cli = Off";
4295 $displayIniMessage = true;
4296 break;
4297
4298 case 'zlib':
4299 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
4300 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
4301 $displayIniMessage = true;
4302 break;
4303
4304 case 'sigchild':
4305 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
4306 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
4307 $text .= "  https://bugs.php.net/bug.php?id=22999";
4308 break;
4309
4310 case 'curlwrappers':
4311 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
4312 $text .= " Recompile it without this flag if possible";
4313 break;
4314
4315 case 'php':
4316 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
4317 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
4318 break;
4319
4320 case 'openssl_version':
4321
4322  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
4323 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
4324
4325 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
4326 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
4327 break;
4328
4329 case 'xdebug_loaded':
4330 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
4331 $text .= " Disabling it when using Composer is recommended.";
4332 break;
4333
4334 case 'xdebug_profile':
4335 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
4336 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
4337 $text .= "  xdebug.profiler_enabled = 0";
4338 $displayIniMessage = true;
4339 break;
4340 }
4341 $out($text, 'comment');
4342 }
4343 }
4344
4345 if ($displayIniMessage) {
4346 $out($iniMessage, 'comment');
4347 }
4348
4349 return !$warnings && !$errors ? true : $output;
4350 }
4351
4352
4353
4354
4355
4356
4357
4358 private function checkConnectivity()
4359 {
4360 if (!ini_get('allow_url_fopen')) {
4361 $result = '<info>Skipped because allow_url_fopen is missing.</info>';
4362 return $result;
4363 }
4364
4365 return true;
4366 }
4367 }
4368 <?php
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380 namespace Composer\Command;
4381
4382 use Composer\Plugin\CommandEvent;
4383 use Composer\Plugin\PluginEvents;
4384 use Symfony\Component\Console\Input\InputInterface;
4385 use Symfony\Component\Console\Input\InputOption;
4386 use Symfony\Component\Console\Output\OutputInterface;
4387
4388
4389
4390
4391 class DumpAutoloadCommand extends BaseCommand
4392 {
4393 protected function configure()
4394 {
4395 $this
4396 ->setName('dump-autoload')
4397 ->setAliases(array('dumpautoload'))
4398 ->setDescription('Dumps the autoloader.')
4399 ->setDefinition(array(
4400 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4401 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4402 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4403 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4404 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4405 ))
4406 ->setHelp(
4407 <<<EOT
4408 <info>php composer.phar dump-autoload</info>
4409
4410 Read more at https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload-
4411 EOT
4412 )
4413 ;
4414 }
4415
4416 protected function execute(InputInterface $input, OutputInterface $output)
4417 {
4418 $composer = $this->getComposer();
4419
4420 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4421 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4422
4423 $installationManager = $composer->getInstallationManager();
4424 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4425 $package = $composer->getPackage();
4426 $config = $composer->getConfig();
4427
4428 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4429 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4430 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4431
4432 if ($authoritative) {
4433 $this->getIO()->writeError('<info>Generating optimized autoload files (authoritative)</info>', false);
4434 } elseif ($optimize) {
4435 $this->getIO()->writeError('<info>Generating optimized autoload files</info>', false);
4436 } else {
4437 $this->getIO()->writeError('<info>Generating autoload files</info>', false);
4438 }
4439
4440 $generator = $composer->getAutoloadGenerator();
4441 $generator->setDevMode(!$input->getOption('no-dev'));
4442 $generator->setClassMapAuthoritative($authoritative);
4443 $generator->setApcu($apcu);
4444 $generator->setRunScripts(!$input->getOption('no-scripts'));
4445 $numberOfClasses = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4446
4447 if ($authoritative) {
4448 $this->getIO()->overwriteError('<info>Generated optimized autoload files (authoritative) containing '. $numberOfClasses .' classes</info>');
4449 } elseif ($optimize) {
4450 $this->getIO()->overwriteError('<info>Generated optimized autoload files containing '. $numberOfClasses .' classes</info>');
4451 } else {
4452 $this->getIO()->overwriteError('<info>Generated autoload files containing '. $numberOfClasses .' classes</info>');
4453 }
4454
4455 return 0;
4456 }
4457 }
4458 <?php
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470 namespace Composer\Command;
4471
4472 use Symfony\Component\Console\Input\InputInterface;
4473 use Symfony\Component\Console\Input\InputOption;
4474 use Symfony\Component\Console\Output\OutputInterface;
4475 use Symfony\Component\Console\Input\InputArgument;
4476
4477
4478
4479
4480 class ExecCommand extends BaseCommand
4481 {
4482 protected function configure()
4483 {
4484 $this
4485 ->setName('exec')
4486 ->setDescription('Executes a vendored binary/script.')
4487 ->setDefinition(array(
4488 new InputOption('list', 'l', InputOption::VALUE_NONE),
4489 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4490 new InputArgument(
4491 'args',
4492 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4493 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4494 ),
4495 ))
4496 ->setHelp(
4497 <<<EOT
4498 Executes a vendored binary/script.
4499                 
4500 Read more at https://getcomposer.org/doc/03-cli.md#exec
4501 EOT
4502 )
4503 ;
4504 }
4505
4506 protected function execute(InputInterface $input, OutputInterface $output)
4507 {
4508 $composer = $this->getComposer();
4509 $binDir = $composer->getConfig()->get('bin-dir');
4510 if ($input->getOption('list') || !$input->getArgument('binary')) {
4511 $bins = glob($binDir . '/*');
4512 $bins = array_merge($bins, array_map(function ($e) {
4513 return "$e (local)";
4514 }, $composer->getPackage()->getBinaries()));
4515
4516 if (!$bins) {
4517 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4518 }
4519
4520 $this->getIO()->write(
4521 <<<EOT
4522 <comment>Available binaries:</comment>
4523 EOT
4524 );
4525
4526 foreach ($bins as $bin) {
4527
4528  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4529 continue;
4530 }
4531
4532 $previousBin = $bin;
4533 $bin = basename($bin);
4534 $this->getIO()->write(
4535 <<<EOT
4536 <info>- $bin</info>
4537 EOT
4538 );
4539 }
4540
4541 return 0;
4542 }
4543
4544 $binary = $input->getArgument('binary');
4545
4546 $dispatcher = $composer->getEventDispatcher();
4547 $dispatcher->addListener('__exec_command', $binary);
4548 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4549 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4550 }
4551
4552 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4553 }
4554 }
4555 <?php
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567 namespace Composer\Command;
4568
4569 use Composer\Factory;
4570 use Composer\Util\Filesystem;
4571 use Symfony\Component\Console\Input\InputInterface;
4572 use Symfony\Component\Console\Input\InputArgument;
4573 use Symfony\Component\Console\Input\StringInput;
4574 use Symfony\Component\Console\Output\OutputInterface;
4575
4576
4577
4578
4579 class GlobalCommand extends BaseCommand
4580 {
4581 protected function configure()
4582 {
4583 $this
4584 ->setName('global')
4585 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4586 ->setDefinition(array(
4587 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4588 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4589 ))
4590 ->setHelp(
4591 <<<EOT
4592 Use this command as a wrapper to run other Composer commands
4593 within the global context of COMPOSER_HOME.
4594
4595 You can use this to install CLI utilities globally, all you need
4596 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4597
4598 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4599 and /home/<user>/.composer on unix systems.
4600
4601 If your system uses freedesktop.org standards, then it will first check
4602 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4603
4604 Note: This path may vary depending on customizations to bin-dir in
4605 composer.json or the environmental variable COMPOSER_BIN_DIR.
4606
4607 Read more at https://getcomposer.org/doc/03-cli.md#global
4608 EOT
4609 )
4610 ;
4611 }
4612
4613 public function run(InputInterface $input, OutputInterface $output)
4614 {
4615
4616  $tokens = preg_split('{\s+}', $input->__toString());
4617 $args = array();
4618 foreach ($tokens as $token) {
4619 if ($token && $token[0] !== '-') {
4620 $args[] = $token;
4621 if (count($args) >= 2) {
4622 break;
4623 }
4624 }
4625 }
4626
4627
4628  if (count($args) < 2) {
4629 return parent::run($input, $output);
4630 }
4631
4632
4633  $config = Factory::createConfig();
4634 $home = $config->get('home');
4635
4636 if (!is_dir($home)) {
4637 $fs = new Filesystem();
4638 $fs->ensureDirectoryExists($home);
4639 if (!is_dir($home)) {
4640 throw new \RuntimeException('Could not create home directory');
4641 }
4642 }
4643
4644 try {
4645 chdir($home);
4646 } catch (\Exception $e) {
4647 throw new \RuntimeException('Could not switch to home directory "'.$home.'"', 0, $e);
4648 }
4649 $this->getIO()->writeError('<info>Changed current directory to '.$home.'</info>');
4650
4651
4652  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4653 $this->getApplication()->resetComposer();
4654
4655 return $this->getApplication()->run($input, $output);
4656 }
4657
4658
4659
4660
4661 public function isProxyCommand()
4662 {
4663 return true;
4664 }
4665 }
4666 <?php
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678 namespace Composer\Command;
4679
4680 use Composer\Package\CompletePackageInterface;
4681 use Composer\Repository\RepositoryInterface;
4682 use Composer\Repository\ArrayRepository;
4683 use Composer\Repository\RepositoryFactory;
4684 use Composer\Util\Platform;
4685 use Composer\Util\ProcessExecutor;
4686 use Symfony\Component\Console\Input\InputArgument;
4687 use Symfony\Component\Console\Input\InputOption;
4688 use Symfony\Component\Console\Input\InputInterface;
4689 use Symfony\Component\Console\Output\OutputInterface;
4690
4691
4692
4693
4694 class HomeCommand extends BaseCommand
4695 {
4696
4697
4698
4699 protected function configure()
4700 {
4701 $this
4702 ->setName('browse')
4703 ->setAliases(array('home'))
4704 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4705 ->setDefinition(array(
4706 new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.'),
4707 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4708 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4709 ))
4710 ->setHelp(
4711 <<<EOT
4712 The home command opens or shows a package's repository URL or
4713 homepage in your default browser.
4714
4715 To open the homepage by default, use -H or --homepage.
4716 To show instead of open the repository or homepage URL, use -s or --show.
4717
4718 Read more at https://getcomposer.org/doc/03-cli.md#browse-home
4719 EOT
4720 );
4721 }
4722
4723
4724
4725
4726 protected function execute(InputInterface $input, OutputInterface $output)
4727 {
4728 $repos = $this->initializeRepos();
4729 $io = $this->getIO();
4730 $return = 0;
4731
4732 $packages = $input->getArgument('packages');
4733 if (!$packages) {
4734 $io->writeError('No package specified, opening homepage for the root package');
4735 $packages = array($this->getComposer()->getPackage()->getName());
4736 }
4737
4738 foreach ($packages as $packageName) {
4739 $handled = false;
4740 $packageExists = false;
4741 foreach ($repos as $repo) {
4742 foreach ($repo->findPackages($packageName) as $package) {
4743 $packageExists = true;
4744 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4745 $handled = true;
4746 break 2;
4747 }
4748 }
4749 }
4750
4751 if (!$packageExists) {
4752 $return = 1;
4753 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4754 }
4755
4756 if (!$handled) {
4757 $return = 1;
4758 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4759 }
4760 }
4761
4762 return $return;
4763 }
4764
4765 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4766 {
4767 $support = $package->getSupport();
4768 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4769 if (!$url || $showHomepage) {
4770 $url = $package->getHomepage();
4771 }
4772
4773 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4774 return false;
4775 }
4776
4777 if ($showOnly) {
4778 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4779 } else {
4780 $this->openBrowser($url);
4781 }
4782
4783 return true;
4784 }
4785
4786
4787
4788
4789
4790
4791 private function openBrowser($url)
4792 {
4793 $url = ProcessExecutor::escape($url);
4794
4795 $process = new ProcessExecutor($this->getIO());
4796 if (Platform::isWindows()) {
4797 return $process->execute('start "web" explorer "' . $url . '"', $output);
4798 }
4799
4800 $linux = $process->execute('which xdg-open', $output);
4801 $osx = $process->execute('which open', $output);
4802
4803 if (0 === $linux) {
4804 $process->execute('xdg-open ' . $url, $output);
4805 } elseif (0 === $osx) {
4806 $process->execute('open ' . $url, $output);
4807 } else {
4808 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4809 }
4810 }
4811
4812
4813
4814
4815
4816
4817
4818
4819 private function initializeRepos()
4820 {
4821 $composer = $this->getComposer(false);
4822
4823 if ($composer) {
4824 return array_merge(
4825 array(new ArrayRepository(array($composer->getPackage()))), 
4826  array($composer->getRepositoryManager()->getLocalRepository()), 
4827  $composer->getRepositoryManager()->getRepositories() 
4828  );
4829 }
4830
4831 return RepositoryFactory::defaultRepos($this->getIO());
4832 }
4833 }
4834 <?php
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846 namespace Composer\Command;
4847
4848 use Composer\DependencyResolver\Pool;
4849 use Composer\Factory;
4850 use Composer\Json\JsonFile;
4851 use Composer\Package\BasePackage;
4852 use Composer\Package\Version\VersionParser;
4853 use Composer\Package\Version\VersionSelector;
4854 use Composer\Repository\CompositeRepository;
4855 use Composer\Repository\PlatformRepository;
4856 use Composer\Repository\RepositoryFactory;
4857 use Composer\Util\ProcessExecutor;
4858 use Symfony\Component\Console\Input\ArrayInput;
4859 use Symfony\Component\Console\Input\InputInterface;
4860 use Symfony\Component\Console\Input\InputOption;
4861 use Symfony\Component\Console\Output\OutputInterface;
4862 use Symfony\Component\Process\ExecutableFinder;
4863 use Symfony\Component\Process\Process;
4864
4865
4866
4867
4868
4869 class InitCommand extends BaseCommand
4870 {
4871
4872 protected $repos;
4873
4874
4875 private $gitConfig;
4876
4877
4878 private $pools;
4879
4880
4881
4882
4883 protected function configure()
4884 {
4885 $this
4886 ->setName('init')
4887 ->setDescription('Creates a basic composer.json file in current directory.')
4888 ->setDefinition(array(
4889 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4890 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4891 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4892
4893  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4894 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4895 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"'),
4896 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"'),
4897 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4898 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4899 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4900 ))
4901 ->setHelp(
4902 <<<EOT
4903 The <info>init</info> command creates a basic composer.json file
4904 in the current directory.
4905
4906 <info>php composer.phar init</info>
4907
4908 Read more at https://getcomposer.org/doc/03-cli.md#init
4909 EOT
4910 )
4911 ;
4912 }
4913
4914
4915
4916
4917 protected function execute(InputInterface $input, OutputInterface $output)
4918 {
4919 $io = $this->getIO();
4920
4921 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4922 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4923
4924 if (isset($options['author'])) {
4925 $options['authors'] = $this->formatAuthors($options['author']);
4926 unset($options['author']);
4927 }
4928
4929 $repositories = $input->getOption('repository');
4930 if ($repositories) {
4931 $config = Factory::createConfig($io);
4932 foreach ($repositories as $repo) {
4933 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4934 }
4935 }
4936
4937 if (isset($options['stability'])) {
4938 $options['minimum-stability'] = $options['stability'];
4939 unset($options['stability']);
4940 }
4941
4942 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4943 if (array() === $options['require']) {
4944 $options['require'] = new \stdClass;
4945 }
4946
4947 if (isset($options['require-dev'])) {
4948 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4949 if (array() === $options['require-dev']) {
4950 $options['require-dev'] = new \stdClass;
4951 }
4952 }
4953
4954 $file = new JsonFile(Factory::getComposerFile());
4955 $json = $file->encode($options);
4956
4957 if ($input->isInteractive()) {
4958 $io->writeError(array('', $json, ''));
4959 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4960 $io->writeError('<error>Command aborted</error>');
4961
4962 return 1;
4963 }
4964 }
4965
4966 $file->write($options);
4967
4968 if ($input->isInteractive() && is_dir('.git')) {
4969 $ignoreFile = realpath('.gitignore');
4970
4971 if (false === $ignoreFile) {
4972 $ignoreFile = realpath('.') . '/.gitignore';
4973 }
4974
4975 if (!$this->hasVendorIgnore($ignoreFile)) {
4976 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4977
4978 if ($io->askConfirmation($question, true)) {
4979 $this->addVendorIgnore($ignoreFile);
4980 }
4981 }
4982 }
4983
4984 $question = 'Would you like to install dependencies now [<comment>yes</comment>]? ';
4985 if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question, true)) {
4986 $this->installDependencies($output);
4987 }
4988
4989 return 0;
4990 }
4991
4992
4993
4994
4995 protected function interact(InputInterface $input, OutputInterface $output)
4996 {
4997 $git = $this->getGitConfig();
4998 $io = $this->getIO();
4999 $formatter = $this->getHelperSet()->get('formatter');
5000
5001
5002  $repositories = $input->getOption('repository');
5003 if ($repositories) {
5004 $config = Factory::createConfig($io);
5005 $repos = array(new PlatformRepository);
5006 $createDefaultPackagistRepo = true;
5007 foreach ($repositories as $repo) {
5008 $repoConfig = RepositoryFactory::configFromString($io, $config, $repo);
5009 if (
5010 (isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
5011 || (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
5012 ) {
5013 $createDefaultPackagistRepo = false;
5014 continue;
5015 }
5016 $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig);
5017 }
5018
5019 if ($createDefaultPackagistRepo) {
5020 $repos[] = RepositoryFactory::createRepo($io, $config, array(
5021 'type' => 'composer',
5022 'url' => 'https://repo.packagist.org',
5023 ));
5024 }
5025
5026 $this->repos = new CompositeRepository($repos);
5027 unset($repos, $config, $repositories);
5028 }
5029
5030 $io->writeError(array(
5031 '',
5032 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
5033 '',
5034 ));
5035
5036
5037  $io->writeError(array(
5038 '',
5039 'This command will guide you through creating your composer.json config.',
5040 '',
5041 ));
5042
5043 $cwd = realpath(".");
5044
5045 if (!$name = $input->getOption('name')) {
5046 $name = basename($cwd);
5047 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
5048 $name = strtolower($name);
5049 if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
5050 $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
5051 } elseif (isset($git['github.user'])) {
5052 $name = $git['github.user'] . '/' . $name;
5053 } elseif (!empty($_SERVER['USERNAME'])) {
5054 $name = $_SERVER['USERNAME'] . '/' . $name;
5055 } elseif (!empty($_SERVER['USER'])) {
5056 $name = $_SERVER['USER'] . '/' . $name;
5057 } elseif (get_current_user()) {
5058 $name = get_current_user() . '/' . $name;
5059 } else {
5060
5061  $name .= '/' . $name;
5062 }
5063 $name = strtolower($name);
5064 } else {
5065 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $name)) {
5066 throw new \InvalidArgumentException(
5067 '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_.-]+'
5068 );
5069 }
5070 }
5071
5072 $name = $io->askAndValidate(
5073 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
5074 function ($value) use ($name) {
5075 if (null === $value) {
5076 return $name;
5077 }
5078
5079 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $value)) {
5080 throw new \InvalidArgumentException(
5081 '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_.-]+'
5082 );
5083 }
5084
5085 return $value;
5086 },
5087 null,
5088 $name
5089 );
5090 $input->setOption('name', $name);
5091
5092 $description = $input->getOption('description') ?: false;
5093 $description = $io->ask(
5094 'Description [<comment>'.$description.'</comment>]: ',
5095 $description
5096 );
5097 $input->setOption('description', $description);
5098
5099 if (null === $author = $input->getOption('author')) {
5100 if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
5101 $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
5102 } elseif (isset($git['user.name'])) {
5103 $author_name = $git['user.name'];
5104 }
5105
5106 if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
5107 $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
5108 } elseif (isset($git['user.email'])) {
5109 $author_email = $git['user.email'];
5110 }
5111
5112 if (isset($author_name) && isset($author_email)) {
5113 $author = sprintf('%s <%s>', $author_name, $author_email);
5114 }
5115 }
5116
5117 $self = $this;
5118 $author = $io->askAndValidate(
5119 'Author [<comment>'.$author.'</comment>, n to skip]: ',
5120 function ($value) use ($self, $author) {
5121 if ($value === 'n' || $value === 'no') {
5122 return;
5123 }
5124 $value = $value ?: $author;
5125 $author = $self->parseAuthorString($value);
5126
5127 return sprintf('%s <%s>', $author['name'], $author['email']);
5128 },
5129 null,
5130 $author
5131 );
5132 $input->setOption('author', $author);
5133
5134 $minimumStability = $input->getOption('stability') ?: null;
5135 $minimumStability = $io->askAndValidate(
5136 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
5137 function ($value) use ($minimumStability) {
5138 if (null === $value) {
5139 return $minimumStability;
5140 }
5141
5142 if (!isset(BasePackage::$stabilities[$value])) {
5143 throw new \InvalidArgumentException(
5144 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
5145 implode(', ', array_keys(BasePackage::$stabilities))
5146 );
5147 }
5148
5149 return $value;
5150 },
5151 null,
5152 $minimumStability
5153 );
5154 $input->setOption('stability', $minimumStability);
5155
5156 $type = $input->getOption('type') ?: false;
5157 $type = $io->ask(
5158 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
5159 $type
5160 );
5161 $input->setOption('type', $type);
5162
5163 if (null === $license = $input->getOption('license')) {
5164 if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
5165 $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
5166 }
5167 }
5168
5169 $license = $io->ask(
5170 'License [<comment>'.$license.'</comment>]: ',
5171 $license
5172 );
5173 $input->setOption('license', $license);
5174
5175 $io->writeError(array('', 'Define your dependencies.', ''));
5176
5177
5178  $repos = $this->getRepos();
5179 $preferredStability = $minimumStability ?: 'stable';
5180 $phpVersion = $repos->findPackage('php', '*')->getPrettyVersion();
5181
5182 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
5183 $require = $input->getOption('require');
5184 $requirements = array();
5185 if ($require || $io->askConfirmation($question, true)) {
5186 $requirements = $this->determineRequirements($input, $output, $require, $phpVersion, $preferredStability);
5187 }
5188 $input->setOption('require', $requirements);
5189
5190 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
5191 $requireDev = $input->getOption('require-dev');
5192 $devRequirements = array();
5193 if ($requireDev || $io->askConfirmation($question, true)) {
5194 $devRequirements = $this->determineRequirements($input, $output, $requireDev, $phpVersion, $preferredStability);
5195 }
5196 $input->setOption('require-dev', $devRequirements);
5197 }
5198
5199
5200
5201
5202
5203
5204 public function parseAuthorString($author)
5205 {
5206 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
5207 if ($this->isValidEmail($match['email'])) {
5208 return array(
5209 'name' => trim($match['name']),
5210 'email' => $match['email'],
5211 );
5212 }
5213 }
5214
5215 throw new \InvalidArgumentException(
5216 'Invalid author string.  Must be in the format: '.
5217 'John Smith <john@example.com>'
5218 );
5219 }
5220
5221 protected function findPackages($name)
5222 {
5223 return $this->getRepos()->search($name);
5224 }
5225
5226 protected function getRepos()
5227 {
5228 if (!$this->repos) {
5229 $this->repos = new CompositeRepository(array_merge(
5230 array(new PlatformRepository),
5231 RepositoryFactory::defaultRepos($this->getIO())
5232 ));
5233 }
5234
5235 return $this->repos;
5236 }
5237
5238 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true)
5239 {
5240 if ($requires) {
5241 $requires = $this->normalizeRequirements($requires);
5242 $result = array();
5243 $io = $this->getIO();
5244
5245 foreach ($requires as $requirement) {
5246 if (!isset($requirement['version'])) {
5247
5248  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
5249 $requirement['version'] = $version;
5250
5251
5252  $requirement['name'] = $name;
5253
5254 $io->writeError(sprintf(
5255 'Using version <info>%s</info> for <info>%s</info>',
5256 $requirement['version'],
5257 $requirement['name']
5258 ));
5259 } else {
5260
5261  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev');
5262
5263
5264  $requirement['name'] = $name;
5265 }
5266
5267 $result[] = $requirement['name'] . ' ' . $requirement['version'];
5268 }
5269
5270 return $result;
5271 }
5272
5273 $versionParser = new VersionParser();
5274 $io = $this->getIO();
5275 while (null !== $package = $io->ask('Search for a package: ')) {
5276 $matches = $this->findPackages($package);
5277
5278 if (count($matches)) {
5279 $exactMatch = null;
5280 $choices = array();
5281 foreach ($matches as $position => $foundPackage) {
5282 $abandoned = '';
5283 if (isset($foundPackage['abandoned'])) {
5284 if (is_string($foundPackage['abandoned'])) {
5285 $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
5286 } else {
5287 $replacement = 'No replacement was suggested';
5288 }
5289 $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
5290 }
5291
5292 $choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
5293 if ($foundPackage['name'] === $package) {
5294 $exactMatch = true;
5295 break;
5296 }
5297 }
5298
5299
5300  if (!$exactMatch) {
5301 $io->writeError(array(
5302 '',
5303 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
5304 '',
5305 ));
5306
5307 $io->writeError($choices);
5308 $io->writeError('');
5309
5310 $validator = function ($selection) use ($matches, $versionParser) {
5311 if ('' === $selection) {
5312 return false;
5313 }
5314
5315 if (is_numeric($selection) && isset($matches[(int) $selection])) {
5316 $package = $matches[(int) $selection];
5317
5318 return $package['name'];
5319 }
5320
5321 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
5322 if (isset($packageMatches['version'])) {
5323
5324
5325
5326  $versionParser->parseConstraints($packageMatches['version']);
5327
5328 return $packageMatches['name'].' '.$packageMatches['version'];
5329 }
5330
5331
5332  return $packageMatches['name'];
5333 }
5334
5335 throw new \Exception('Not a valid selection');
5336 };
5337
5338 $package = $io->askAndValidate(
5339 'Enter package # to add, or the complete package name if it is not listed: ',
5340 $validator,
5341 3,
5342 false
5343 );
5344 }
5345
5346
5347  if (false !== $package && false === strpos($package, ' ')) {
5348 $validator = function ($input) {
5349 $input = trim($input);
5350
5351 return $input ?: false;
5352 };
5353
5354 $constraint = $io->askAndValidate(
5355 'Enter the version constraint to require (or leave blank to use the latest version): ',
5356 $validator,
5357 3,
5358 false
5359 );
5360
5361 if (false === $constraint) {
5362 list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
5363
5364 $io->writeError(sprintf(
5365 'Using version <info>%s</info> for <info>%s</info>',
5366 $constraint,
5367 $package
5368 ));
5369 }
5370
5371 $package .= ' '.$constraint;
5372 }
5373
5374 if (false !== $package) {
5375 $requires[] = $package;
5376 }
5377 }
5378 }
5379
5380 return $requires;
5381 }
5382
5383 protected function formatAuthors($author)
5384 {
5385 return array($this->parseAuthorString($author));
5386 }
5387
5388 protected function formatRequirements(array $requirements)
5389 {
5390 $requires = array();
5391 $requirements = $this->normalizeRequirements($requirements);
5392 foreach ($requirements as $requirement) {
5393 $requires[$requirement['name']] = $requirement['version'];
5394 }
5395
5396 return $requires;
5397 }
5398
5399 protected function getGitConfig()
5400 {
5401 if (null !== $this->gitConfig) {
5402 return $this->gitConfig;
5403 }
5404
5405 $finder = new ExecutableFinder();
5406 $gitBin = $finder->find('git');
5407
5408
5409  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
5410 $cmd = new Process(array($gitBin, 'config', '-l'));
5411 } else {
5412 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
5413 }
5414 $cmd->run();
5415
5416 if ($cmd->isSuccessful()) {
5417 $this->gitConfig = array();
5418 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
5419 foreach ($matches as $match) {
5420 $this->gitConfig[$match[1]] = $match[2];
5421 }
5422
5423 return $this->gitConfig;
5424 }
5425
5426 return $this->gitConfig = array();
5427 }
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
5446 {
5447 if (!file_exists($ignoreFile)) {
5448 return false;
5449 }
5450
5451 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
5452
5453 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
5454 foreach ($lines as $line) {
5455 if (preg_match($pattern, $line)) {
5456 return true;
5457 }
5458 }
5459
5460 return false;
5461 }
5462
5463 protected function normalizeRequirements(array $requirements)
5464 {
5465 $parser = new VersionParser();
5466
5467 return $parser->parseNameVersionPairs($requirements);
5468 }
5469
5470 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
5471 {
5472 $contents = "";
5473 if (file_exists($ignoreFile)) {
5474 $contents = file_get_contents($ignoreFile);
5475
5476 if ("\n" !== substr($contents, 0, -1)) {
5477 $contents .= "\n";
5478 }
5479 }
5480
5481 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5482 }
5483
5484 protected function isValidEmail($email)
5485 {
5486
5487  if (!function_exists('filter_var')) {
5488 return true;
5489 }
5490
5491
5492  if (PHP_VERSION_ID < 50303) {
5493 return true;
5494 }
5495
5496 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5497 }
5498
5499 private function getPool(InputInterface $input, $minimumStability = null)
5500 {
5501 $key = $minimumStability ?: 'default';
5502
5503 if (!isset($this->pools[$key])) {
5504 $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5505 $pool->addRepository($this->getRepos());
5506 }
5507
5508 return $this->pools[$key];
5509 }
5510
5511 private function getMinimumStability(InputInterface $input)
5512 {
5513 if ($input->hasOption('stability')) {
5514 return $input->getOption('stability') ?: 'stable';
5515 }
5516
5517 $file = Factory::getComposerFile();
5518 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5519 if (!empty($composer['minimum-stability'])) {
5520 return $composer['minimum-stability'];
5521 }
5522 }
5523
5524 return 'stable';
5525 }
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541 private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null)
5542 {
5543
5544  $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5545 $ignorePlatformReqs = $input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs');
5546
5547
5548  if ($ignorePlatformReqs) {
5549 $phpVersion = null;
5550 }
5551
5552 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5553
5554 if (!$package) {
5555
5556  
5557  if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
5558 return array($name, $requiredVersion ?: '*');
5559 }
5560
5561
5562  if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
5563 throw new \InvalidArgumentException(sprintf(
5564 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)',
5565 $name,
5566 $requiredVersion,
5567 $phpVersion
5568 ));
5569 }
5570
5571  if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
5572 throw new \InvalidArgumentException(sprintf(
5573 'Could not find package %s in a version matching %s',
5574 $name,
5575 $requiredVersion
5576 ));
5577 }
5578
5579  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5580 throw new \InvalidArgumentException(sprintf(
5581 'Could not find package %s in any version matching your PHP version (%s)',
5582 $name,
5583 $phpVersion
5584 ));
5585 }
5586
5587
5588  $similar = $this->findSimilar($name);
5589 if ($similar) {
5590
5591  if ($requiredVersion === null && in_array($name, $similar, true)) {
5592 throw new \InvalidArgumentException(sprintf(
5593 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
5594 $name,
5595 $this->getMinimumStability($input)
5596 ));
5597 }
5598
5599 throw new \InvalidArgumentException(sprintf(
5600 "Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s",
5601 $name,
5602 implode("\n    ", $similar)
5603 ));
5604 }
5605
5606 throw new \InvalidArgumentException(sprintf(
5607 '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).',
5608 $name,
5609 $this->getMinimumStability($input)
5610 ));
5611 }
5612
5613 return array(
5614 $package->getPrettyName(),
5615 $versionSelector->findRecommendedRequireVersion($package),
5616 );
5617 }
5618
5619 private function findSimilar($package)
5620 {
5621 try {
5622 $results = $this->repos->search($package);
5623 } catch (\Exception $e) {
5624
5625  return array();
5626 }
5627 $similarPackages = array();
5628
5629 foreach ($results as $result) {
5630 $similarPackages[$result['name']] = levenshtein($package, $result['name']);
5631 }
5632 asort($similarPackages);
5633
5634 return array_keys(array_slice($similarPackages, 0, 5));
5635 }
5636
5637 private function installDependencies($output)
5638 {
5639 try {
5640 $installCommand = $this->getApplication()->find('install');
5641 $installCommand->run(new ArrayInput(array()), $output);
5642 } catch (\Exception $e) {
5643 $this->getIO()->writeError('Could not install dependencies. Run `composer install` to see more information.');
5644 }
5645
5646 }
5647
5648 private function hasDependencies($options)
5649 {
5650 $requires = (array) $options['require'];
5651 $devRequires = isset($options['require-dev']) ? (array) $options['require-dev'] : array();
5652
5653 return !empty($requires) || !empty($devRequires);
5654 }
5655 }
5656 <?php
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668 namespace Composer\Command;
5669
5670 use Composer\Installer;
5671 use Composer\Plugin\CommandEvent;
5672 use Composer\Plugin\PluginEvents;
5673 use Symfony\Component\Console\Input\InputInterface;
5674 use Symfony\Component\Console\Input\InputOption;
5675 use Symfony\Component\Console\Input\InputArgument;
5676 use Symfony\Component\Console\Output\OutputInterface;
5677
5678
5679
5680
5681
5682
5683
5684 class InstallCommand extends BaseCommand
5685 {
5686 protected function configure()
5687 {
5688 $this
5689 ->setName('install')
5690 ->setAliases(array('i'))
5691 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5692 ->setDefinition(array(
5693 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5694 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5695 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5696 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5697 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5698 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5699 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5700 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5701 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5702 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5703 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5704 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5705 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5706 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5707 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5708 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5709 ))
5710 ->setHelp(
5711 <<<EOT
5712 The <info>install</info> command reads the composer.lock file from
5713 the current directory, processes it, and downloads and installs all the
5714 libraries and dependencies outlined in that file. If the file does not
5715 exist it will look for composer.json and do the same.
5716
5717 <info>php composer.phar install</info>
5718
5719 Read more at https://getcomposer.org/doc/03-cli.md#install-i
5720 EOT
5721 )
5722 ;
5723 }
5724
5725 protected function execute(InputInterface $input, OutputInterface $output)
5726 {
5727 $io = $this->getIO();
5728 if ($args = $input->getArgument('packages')) {
5729 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5730
5731 return 1;
5732 }
5733
5734 if ($input->getOption('no-custom-installers')) {
5735 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5736 $input->setOption('no-plugins', true);
5737 }
5738
5739 if ($input->getOption('dev')) {
5740 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5741 }
5742
5743 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5744 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5745
5746 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5747 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5748
5749 $install = Installer::create($io, $composer);
5750
5751 $config = $composer->getConfig();
5752 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5753
5754 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5755 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5756 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5757
5758 $install
5759 ->setDryRun($input->getOption('dry-run'))
5760 ->setVerbose($input->getOption('verbose'))
5761 ->setPreferSource($preferSource)
5762 ->setPreferDist($preferDist)
5763 ->setDevMode(!$input->getOption('no-dev'))
5764 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5765 ->setRunScripts(!$input->getOption('no-scripts'))
5766 ->setSkipSuggest($input->getOption('no-suggest'))
5767 ->setOptimizeAutoloader($optimize)
5768 ->setClassMapAuthoritative($authoritative)
5769 ->setApcuAutoloader($apcu)
5770 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5771 ;
5772
5773 if ($input->getOption('no-plugins')) {
5774 $install->disablePlugins();
5775 }
5776
5777 return $install->run();
5778 }
5779 }
5780 <?php
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792 namespace Composer\Command;
5793
5794 use Composer\Json\JsonFile;
5795 use Composer\Plugin\CommandEvent;
5796 use Composer\Plugin\PluginEvents;
5797 use Composer\Package\PackageInterface;
5798 use Composer\Repository\RepositoryInterface;
5799 use Symfony\Component\Console\Helper\Table;
5800 use Symfony\Component\Console\Input\InputInterface;
5801 use Symfony\Component\Console\Input\InputOption;
5802 use Symfony\Component\Console\Output\OutputInterface;
5803
5804
5805
5806
5807 class LicensesCommand extends BaseCommand
5808 {
5809 protected function configure()
5810 {
5811 $this
5812 ->setName('licenses')
5813 ->setDescription('Shows information about licenses of dependencies.')
5814 ->setDefinition(array(
5815 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5816 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5817 ))
5818 ->setHelp(
5819 <<<EOT
5820 The license command displays detailed information about the licenses of
5821 the installed dependencies.
5822
5823 Read more at https://getcomposer.org/doc/03-cli.md#licenses
5824 EOT
5825 )
5826 ;
5827 }
5828
5829 protected function execute(InputInterface $input, OutputInterface $output)
5830 {
5831 $composer = $this->getComposer();
5832
5833 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5834 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5835
5836 $root = $composer->getPackage();
5837 $repo = $composer->getRepositoryManager()->getLocalRepository();
5838
5839 if ($input->getOption('no-dev')) {
5840 $packages = $this->filterRequiredPackages($repo, $root);
5841 } else {
5842 $packages = $this->appendPackages($repo->getPackages(), array());
5843 }
5844
5845 ksort($packages);
5846 $io = $this->getIO();
5847
5848 switch ($format = $input->getOption('format')) {
5849 case 'text':
5850 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5851 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5852 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5853 $io->write('Dependencies:');
5854 $io->write('');
5855
5856 $table = new Table($output);
5857 $table->setStyle('compact');
5858 $tableStyle = $table->getStyle();
5859 $tableStyle->setVerticalBorderChar('');
5860 $tableStyle->setCellRowContentFormat('%s  ');
5861 $table->setHeaders(array('Name', 'Version', 'License'));
5862 foreach ($packages as $package) {
5863 $table->addRow(array(
5864 $package->getPrettyName(),
5865 $package->getFullPrettyVersion(),
5866 implode(', ', $package->getLicense()) ?: 'none',
5867 ));
5868 }
5869 $table->render();
5870 break;
5871
5872 case 'json':
5873 $dependencies = array();
5874 foreach ($packages as $package) {
5875 $dependencies[$package->getPrettyName()] = array(
5876 'version' => $package->getFullPrettyVersion(),
5877 'license' => $package->getLicense(),
5878 );
5879 }
5880
5881 $io->write(JsonFile::encode(array(
5882 'name' => $root->getPrettyName(),
5883 'version' => $root->getFullPrettyVersion(),
5884 'license' => $root->getLicense(),
5885 'dependencies' => $dependencies,
5886 )));
5887 break;
5888
5889 default:
5890 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5891 }
5892
5893 return 0;
5894 }
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5905 {
5906 $requires = array_keys($package->getRequires());
5907
5908 $packageListNames = array_keys($bucket);
5909 $packages = array_filter(
5910 $repo->getPackages(),
5911 function ($package) use ($requires, $packageListNames) {
5912 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5913 }
5914 );
5915
5916 $bucket = $this->appendPackages($packages, $bucket);
5917
5918 foreach ($packages as $package) {
5919 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5920 }
5921
5922 return $bucket;
5923 }
5924
5925
5926
5927
5928
5929
5930
5931
5932 public function appendPackages(array $packages, array $bucket)
5933 {
5934 foreach ($packages as $package) {
5935 $bucket[$package->getName()] = $package;
5936 }
5937
5938 return $bucket;
5939 }
5940 }
5941 <?php
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953 namespace Composer\Command;
5954
5955 use Symfony\Component\Console\Input\InputInterface;
5956 use Symfony\Component\Console\Input\InputArgument;
5957 use Symfony\Component\Console\Input\ArrayInput;
5958 use Symfony\Component\Console\Input\InputOption;
5959 use Symfony\Component\Console\Output\OutputInterface;
5960
5961
5962
5963
5964 class OutdatedCommand extends ShowCommand
5965 {
5966 protected function configure()
5967 {
5968 $this
5969 ->setName('outdated')
5970 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5971 ->setDefinition(array(
5972 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5973 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5974 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5975 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5976 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5977 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5978 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5979 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.'),
5980 ))
5981 ->setHelp(
5982 <<<EOT
5983 The outdated command is just a proxy for `composer show -l`
5984
5985 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5986
5987 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5988 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5989   compatibility breaks according to semver, so upgrade when you can but it
5990   may involve work.
5991 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5992
5993 Read more at https://getcomposer.org/doc/03-cli.md#outdated
5994 EOT
5995 )
5996 ;
5997 }
5998
5999 protected function execute(InputInterface $input, OutputInterface $output)
6000 {
6001 $args = array(
6002 'command' => 'show',
6003 '--latest' => true,
6004 );
6005 if (!$input->getOption('all')) {
6006 $args['--outdated'] = true;
6007 }
6008 if ($input->getOption('direct')) {
6009 $args['--direct'] = true;
6010 }
6011 if ($input->getArgument('package')) {
6012 $args['package'] = $input->getArgument('package');
6013 }
6014 if ($input->getOption('strict')) {
6015 $args['--strict'] = true;
6016 }
6017 if ($input->getOption('minor-only')) {
6018 $args['--minor-only'] = true;
6019 }
6020 $args['--format'] = $input->getOption('format');
6021 $args['--ignore'] = $input->getOption('ignore');
6022
6023 $input = new ArrayInput($args);
6024
6025 return $this->getApplication()->run($input, $output);
6026 }
6027
6028
6029
6030
6031 public function isProxyCommand()
6032 {
6033 return true;
6034 }
6035 }
6036 <?php
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048 namespace Composer\Command;
6049
6050 use Symfony\Component\Console\Input\InputInterface;
6051 use Symfony\Component\Console\Output\OutputInterface;
6052
6053
6054
6055
6056 class ProhibitsCommand extends BaseDependencyCommand
6057 {
6058
6059
6060
6061 protected function configure()
6062 {
6063 parent::configure();
6064
6065 $this
6066 ->setName('prohibits')
6067 ->setAliases(array('why-not'))
6068 ->setDescription('Shows which packages prevent the given package from being installed.')
6069 ->setHelp(
6070 <<<EOT
6071 Displays detailed information about why a package cannot be installed.
6072
6073 <info>php composer.phar prohibits composer/composer</info>
6074
6075 Read more at https://getcomposer.org/doc/03-cli.md#prohibits-why-not-
6076 EOT
6077 )
6078 ;
6079 }
6080
6081
6082
6083
6084
6085
6086
6087
6088 protected function execute(InputInterface $input, OutputInterface $output)
6089 {
6090 return parent::doExecute($input, $output, true);
6091 }
6092 }
6093 <?php
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105 namespace Composer\Command;
6106
6107 use Composer\Config\JsonConfigSource;
6108 use Composer\Installer;
6109 use Composer\Plugin\CommandEvent;
6110 use Composer\Plugin\PluginEvents;
6111 use Composer\Json\JsonFile;
6112 use Composer\Factory;
6113 use Symfony\Component\Console\Input\InputInterface;
6114 use Symfony\Component\Console\Input\InputOption;
6115 use Symfony\Component\Console\Input\InputArgument;
6116 use Symfony\Component\Console\Output\OutputInterface;
6117 use Composer\Package\BasePackage;
6118
6119
6120
6121
6122
6123 class RemoveCommand extends BaseCommand
6124 {
6125 protected function configure()
6126 {
6127 $this
6128 ->setName('remove')
6129 ->setDescription('Removes a package from the require or require-dev.')
6130 ->setDefinition(array(
6131 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
6132 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
6133 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6134 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6135 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6136 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6137 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
6138 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
6139 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6140 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6141 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6142 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6143 ))
6144 ->setHelp(
6145 <<<EOT
6146 The <info>remove</info> command removes a package from the current
6147 list of installed packages
6148
6149 <info>php composer.phar remove</info>
6150
6151 Read more at https://getcomposer.org/doc/03-cli.md#remove
6152 EOT
6153 )
6154 ;
6155 }
6156
6157 protected function execute(InputInterface $input, OutputInterface $output)
6158 {
6159 $packages = $input->getArgument('packages');
6160 $packages = array_map('strtolower', $packages);
6161
6162 $file = Factory::getComposerFile();
6163
6164 $jsonFile = new JsonFile($file);
6165 $composer = $jsonFile->read();
6166 $composerBackup = file_get_contents($jsonFile->getPath());
6167
6168 $json = new JsonConfigSource($jsonFile);
6169
6170 $type = $input->getOption('dev') ? 'require-dev' : 'require';
6171 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
6172 $io = $this->getIO();
6173
6174 if ($input->getOption('update-with-dependencies')) {
6175 $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>');
6176 }
6177
6178
6179  foreach (array('require', 'require-dev') as $linkType) {
6180 if (isset($composer[$linkType])) {
6181 foreach ($composer[$linkType] as $name => $version) {
6182 $composer[$linkType][strtolower($name)] = $name;
6183 }
6184 }
6185 }
6186
6187 foreach ($packages as $package) {
6188 if (isset($composer[$type][$package])) {
6189 $json->removeLink($type, $composer[$type][$package]);
6190 } elseif (isset($composer[$altType][$package])) {
6191 $io->writeError('<warning>' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6192 if ($io->isInteractive()) {
6193 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6194 $json->removeLink($altType, $composer[$altType][$package]);
6195 }
6196 }
6197 } elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) {
6198 foreach ($matches as $matchedPackage) {
6199 $json->removeLink($type, $matchedPackage);
6200 }
6201 } elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) {
6202 foreach ($matches as $matchedPackage) {
6203 $io->writeError('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6204 if ($io->isInteractive()) {
6205 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6206 $json->removeLink($altType, $matchedPackage);
6207 }
6208 }
6209 }
6210 } else {
6211 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
6212 }
6213 }
6214
6215 if ($input->getOption('no-update')) {
6216 return 0;
6217 }
6218
6219
6220  $this->resetComposer();
6221 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6222 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6223
6224 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
6225 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6226
6227 $install = Installer::create($io, $composer);
6228
6229 $updateDevMode = !$input->getOption('update-no-dev');
6230 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6231 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6232 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6233
6234 $install
6235 ->setVerbose($input->getOption('verbose'))
6236 ->setDevMode($updateDevMode)
6237 ->setOptimizeAutoloader($optimize)
6238 ->setClassMapAuthoritative($authoritative)
6239 ->setApcuAutoloader($apcu)
6240 ->setUpdate(true)
6241 ->setUpdateWhitelist($packages)
6242 ->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
6243 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6244 ->setRunScripts(!$input->getOption('no-scripts'))
6245 ;
6246
6247 $status = $install->run();
6248 if ($status !== 0) {
6249 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
6250 file_put_contents($jsonFile->getPath(), $composerBackup);
6251 }
6252
6253 return $status;
6254 }
6255 }
6256 <?php
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268 namespace Composer\Command;
6269
6270 use Symfony\Component\Console\Input\InputInterface;
6271 use Symfony\Component\Console\Input\InputArgument;
6272 use Symfony\Component\Console\Input\InputOption;
6273 use Symfony\Component\Console\Output\OutputInterface;
6274 use Composer\Factory;
6275 use Composer\Installer;
6276 use Composer\Json\JsonFile;
6277 use Composer\Json\JsonManipulator;
6278 use Composer\Package\Version\VersionParser;
6279 use Composer\Plugin\CommandEvent;
6280 use Composer\Plugin\PluginEvents;
6281 use Composer\Repository\CompositeRepository;
6282 use Composer\Repository\PlatformRepository;
6283 use Composer\IO\IOInterface;
6284 use Composer\Util\Silencer;
6285
6286
6287
6288
6289
6290 class RequireCommand extends InitCommand
6291 {
6292 private $newlyCreated;
6293 private $json;
6294 private $file;
6295 private $composerBackup;
6296
6297 protected function configure()
6298 {
6299 $this
6300 ->setName('require')
6301 ->setDescription('Adds required packages to your composer.json and installs them.')
6302 ->setDefinition(array(
6303 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"'),
6304 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
6305 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
6306 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
6307 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6308 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
6309 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6310 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6311 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6312 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
6313 new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
6314 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6315 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
6316 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
6317 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
6318 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6319 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6320 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6321 ))
6322 ->setHelp(
6323 <<<EOT
6324 The require command adds required packages to your composer.json and installs them.
6325
6326 If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of
6327 matches to require.
6328
6329 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
6330
6331 If you do not want to install the new dependencies immediately you can call it with --no-update
6332
6333 Read more at https://getcomposer.org/doc/03-cli.md#require
6334 EOT
6335 )
6336 ;
6337 }
6338
6339 protected function execute(InputInterface $input, OutputInterface $output)
6340 {
6341 if (function_exists('pcntl_async_signals')) {
6342 pcntl_async_signals(true);
6343 pcntl_signal(SIGINT, array($this, 'revertComposerFile'));
6344 pcntl_signal(SIGTERM, array($this, 'revertComposerFile'));
6345 pcntl_signal(SIGHUP, array($this, 'revertComposerFile'));
6346 }
6347
6348 $this->file = Factory::getComposerFile();
6349 $io = $this->getIO();
6350
6351 $this->newlyCreated = !file_exists($this->file);
6352 if ($this->newlyCreated && !file_put_contents($this->file, "{\n}\n")) {
6353 $io->writeError('<error>'.$this->file.' could not be created.</error>');
6354
6355 return 1;
6356 }
6357
6358  
6359  if (!is_readable($this->file) && false === Silencer::call('file_get_contents', $this->file)) {
6360 $io->writeError('<error>'.$this->file.' is not readable.</error>');
6361
6362 return 1;
6363 }
6364
6365 if (filesize($this->file) === 0) {
6366 file_put_contents($this->file, "{\n}\n");
6367 }
6368
6369 $this->json = new JsonFile($this->file);
6370 $this->composerBackup = file_get_contents($this->json->getPath());
6371
6372
6373  
6374  if (!is_writable($this->file) && !Silencer::call('file_put_contents', $this->file, $this->composerBackup)) {
6375 $io->writeError('<error>'.$this->file.' is not writable.</error>');
6376
6377 return 1;
6378 }
6379
6380 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6381 $repos = $composer->getRepositoryManager()->getRepositories();
6382
6383 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6384
6385  $this->repos = new CompositeRepository(array_merge(
6386 array(new PlatformRepository(array(), $platformOverrides)),
6387 $repos
6388 ));
6389
6390 if ($composer->getPackage()->getPreferStable()) {
6391 $preferredStability = 'stable';
6392 } else {
6393 $preferredStability = $composer->getPackage()->getMinimumStability();
6394 }
6395
6396 $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
6397 try {
6398 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'));
6399 } catch (\Exception $e) {
6400 if ($this->newlyCreated) {
6401 throw new \RuntimeException('No composer.json present in the current directory, this may be the cause of the following exception.', 0, $e);
6402 }
6403
6404 throw $e;
6405 }
6406
6407 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
6408 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
6409 $requirements = $this->formatRequirements($requirements);
6410
6411
6412  $versionParser = new VersionParser();
6413 foreach ($requirements as $package => $constraint) {
6414 if (strtolower($package) === $composer->getPackage()->getName()) {
6415 $io->writeError(sprintf('<error>Root package \'%s\' cannot require itself in its composer.json</error>', $package));
6416
6417 return 1;
6418 }
6419 $versionParser->parseConstraints($constraint);
6420 }
6421
6422 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
6423
6424 if (!$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
6425 $composerDefinition = $this->json->read();
6426 foreach ($requirements as $package => $version) {
6427 $composerDefinition[$requireKey][$package] = $version;
6428 unset($composerDefinition[$removeKey][$package]);
6429 }
6430 $this->json->write($composerDefinition);
6431 }
6432
6433 $io->writeError('<info>'.$this->file.' has been '.($this->newlyCreated ? 'created' : 'updated').'</info>');
6434
6435 if ($input->getOption('no-update')) {
6436 return 0;
6437 }
6438
6439 try {
6440 return $this->doUpdate($input, $output, $io, $requirements);
6441 } catch (\Exception $e) {
6442 $this->revertComposerFile(false);
6443 throw $e;
6444 }
6445 }
6446
6447 private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
6448 {
6449
6450  $this->resetComposer();
6451 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6452 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6453
6454 $updateDevMode = !$input->getOption('update-no-dev');
6455 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6456 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6457 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6458
6459 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
6460 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6461
6462 $install = Installer::create($io, $composer);
6463
6464 $install
6465 ->setVerbose($input->getOption('verbose'))
6466 ->setPreferSource($input->getOption('prefer-source'))
6467 ->setPreferDist($input->getOption('prefer-dist'))
6468 ->setDevMode($updateDevMode)
6469 ->setRunScripts(!$input->getOption('no-scripts'))
6470 ->setSkipSuggest($input->getOption('no-suggest'))
6471 ->setOptimizeAutoloader($optimize)
6472 ->setClassMapAuthoritative($authoritative)
6473 ->setApcuAutoloader($apcu)
6474 ->setUpdate(true)
6475 ->setUpdateWhitelist(array_keys($requirements))
6476 ->setWhitelistTransitiveDependencies($input->getOption('update-with-dependencies'))
6477 ->setWhitelistAllDependencies($input->getOption('update-with-all-dependencies'))
6478 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6479 ->setPreferStable($input->getOption('prefer-stable'))
6480 ->setPreferLowest($input->getOption('prefer-lowest'))
6481 ;
6482
6483 $status = $install->run();
6484 if ($status !== 0) {
6485 $this->revertComposerFile(false);
6486 }
6487
6488 return $status;
6489 }
6490
6491 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
6492 {
6493 $contents = file_get_contents($json->getPath());
6494
6495 $manipulator = new JsonManipulator($contents);
6496
6497 foreach ($new as $package => $constraint) {
6498 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
6499 return false;
6500 }
6501 if (!$manipulator->removeSubNode($removeKey, $package)) {
6502 return false;
6503 }
6504 }
6505
6506 file_put_contents($json->getPath(), $manipulator->getContents());
6507
6508 return true;
6509 }
6510
6511 protected function interact(InputInterface $input, OutputInterface $output)
6512 {
6513 return;
6514 }
6515
6516 public function revertComposerFile($hardExit = true)
6517 {
6518 $io = $this->getIO();
6519
6520 if ($this->newlyCreated) {
6521 $io->writeError("\n".'<error>Installation failed, deleting '.$this->file.'.</error>');
6522 unlink($this->json->getPath());
6523 } else {
6524 $io->writeError("\n".'<error>Installation failed, reverting '.$this->file.' to its original content.</error>');
6525 file_put_contents($this->json->getPath(), $this->composerBackup);
6526 }
6527
6528 if ($hardExit) {
6529 exit(1);
6530 }
6531 }
6532 }
6533 <?php
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545 namespace Composer\Command;
6546
6547 use Composer\Script\Event as ScriptEvent;
6548 use Composer\Script\ScriptEvents;
6549 use Composer\Util\ProcessExecutor;
6550 use Symfony\Component\Console\Input\InputInterface;
6551 use Symfony\Component\Console\Input\InputOption;
6552 use Symfony\Component\Console\Input\InputArgument;
6553 use Symfony\Component\Console\Output\OutputInterface;
6554 use Symfony\Component\Console\Helper\Table;
6555
6556
6557
6558
6559 class RunScriptCommand extends BaseCommand
6560 {
6561
6562
6563
6564 protected $scriptEvents = array(
6565 ScriptEvents::PRE_INSTALL_CMD,
6566 ScriptEvents::POST_INSTALL_CMD,
6567 ScriptEvents::PRE_UPDATE_CMD,
6568 ScriptEvents::POST_UPDATE_CMD,
6569 ScriptEvents::PRE_STATUS_CMD,
6570 ScriptEvents::POST_STATUS_CMD,
6571 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
6572 ScriptEvents::POST_CREATE_PROJECT_CMD,
6573 ScriptEvents::PRE_ARCHIVE_CMD,
6574 ScriptEvents::POST_ARCHIVE_CMD,
6575 ScriptEvents::PRE_AUTOLOAD_DUMP,
6576 ScriptEvents::POST_AUTOLOAD_DUMP,
6577 );
6578
6579 protected function configure()
6580 {
6581 $this
6582 ->setName('run-script')
6583 ->setAliases(array('run'))
6584 ->setDescription('Runs the scripts defined in composer.json.')
6585 ->setDefinition(array(
6586 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
6587 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6588 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
6589 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6590 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6591 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
6592 ))
6593 ->setHelp(
6594 <<<EOT
6595 The <info>run-script</info> command runs scripts defined in composer.json:
6596
6597 <info>php composer.phar run-script post-update-cmd</info>
6598
6599 Read more at https://getcomposer.org/doc/03-cli.md#run-script
6600 EOT
6601 )
6602 ;
6603 }
6604
6605 protected function execute(InputInterface $input, OutputInterface $output)
6606 {
6607 if ($input->getOption('list')) {
6608 return $this->listScripts($output);
6609 } elseif (!$input->getArgument('script')) {
6610 throw new \RuntimeException('Missing required argument "script"');
6611 }
6612
6613 $script = $input->getArgument('script');
6614 if (!in_array($script, $this->scriptEvents)) {
6615 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
6616 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
6617 }
6618 }
6619
6620 $composer = $this->getComposer();
6621 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
6622 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
6623 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
6624 if (!$hasListeners) {
6625 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
6626 }
6627
6628 $args = $input->getArgument('args');
6629
6630 if (null !== $timeout = $input->getOption('timeout')) {
6631 if (!ctype_digit($timeout)) {
6632 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
6633 }
6634
6635  ProcessExecutor::setTimeout((int) $timeout);
6636 }
6637
6638 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
6639 }
6640
6641 protected function listScripts(OutputInterface $output)
6642 {
6643 $scripts = $this->getComposer()->getPackage()->getScripts();
6644
6645 if (!count($scripts)) {
6646 return 0;
6647 }
6648
6649 $io = $this->getIO();
6650 $io->writeError('<info>scripts:</info>');
6651 $table = array();
6652 foreach ($scripts as $name => $script) {
6653 $description = '';
6654 try {
6655 $cmd = $this->getApplication()->find($name);
6656 if ($cmd instanceof ScriptAliasCommand) {
6657 $description = $cmd->getDescription();
6658 }
6659 } catch (\Symfony\Component\Console\Exception\CommandNotFoundException $e) {
6660
6661  }
6662 $table[] = array('  '.$name, $description);
6663 }
6664
6665 $renderer = new Table($output);
6666 $renderer->setStyle('compact');
6667 $rendererStyle = $renderer->getStyle();
6668 $rendererStyle->setVerticalBorderChar('');
6669 $rendererStyle->setCellRowContentFormat('%s  ');
6670 $renderer->setRows($table)->render();
6671
6672 return 0;
6673 }
6674 }
6675 <?php
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687 namespace Composer\Command;
6688
6689 use Symfony\Component\Console\Input\InputInterface;
6690 use Symfony\Component\Console\Input\InputOption;
6691 use Symfony\Component\Console\Input\InputArgument;
6692 use Symfony\Component\Console\Output\OutputInterface;
6693
6694
6695
6696
6697 class ScriptAliasCommand extends BaseCommand
6698 {
6699 private $script;
6700 private $description;
6701
6702 public function __construct($script, $description)
6703 {
6704 $this->script = $script;
6705 $this->description = empty($description) ? 'Runs the '.$script.' script as defined in composer.json.' : $description;
6706
6707 parent::__construct();
6708 }
6709
6710 protected function configure()
6711 {
6712 $this
6713 ->setName($this->script)
6714 ->setDescription($this->description)
6715 ->setDefinition(array(
6716 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6717 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6718 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6719 ))
6720 ->setHelp(
6721 <<<EOT
6722 The <info>run-script</info> command runs scripts defined in composer.json:
6723
6724 <info>php composer.phar run-script post-update-cmd</info>
6725
6726 Read more at https://getcomposer.org/doc/03-cli.md#run-script
6727 EOT
6728 )
6729 ;
6730 }
6731
6732 protected function execute(InputInterface $input, OutputInterface $output)
6733 {
6734 $composer = $this->getComposer();
6735
6736 $args = $input->getArguments();
6737
6738 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6739 }
6740 }
6741 <?php
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753 namespace Composer\Command;
6754
6755 use Composer\Factory;
6756 use Symfony\Component\Console\Input\InputInterface;
6757 use Symfony\Component\Console\Input\InputArgument;
6758 use Symfony\Component\Console\Input\InputOption;
6759 use Symfony\Component\Console\Output\OutputInterface;
6760 use Composer\Repository\CompositeRepository;
6761 use Composer\Repository\PlatformRepository;
6762 use Composer\Repository\RepositoryInterface;
6763 use Composer\Plugin\CommandEvent;
6764 use Composer\Plugin\PluginEvents;
6765
6766
6767
6768
6769 class SearchCommand extends BaseCommand
6770 {
6771 protected $matches;
6772 protected $lowMatches = array();
6773 protected $tokens;
6774 protected $output;
6775 protected $onlyName;
6776
6777 protected function configure()
6778 {
6779 $this
6780 ->setName('search')
6781 ->setDescription('Searches for packages.')
6782 ->setDefinition(array(
6783 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6784 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6785 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6786 ))
6787 ->setHelp(
6788 <<<EOT
6789 The search command searches for packages by its name
6790 <info>php composer.phar search symfony composer</info>
6791
6792 Read more at https://getcomposer.org/doc/03-cli.md#search
6793 EOT
6794 )
6795 ;
6796 }
6797
6798 protected function execute(InputInterface $input, OutputInterface $output)
6799 {
6800
6801  $platformRepo = new PlatformRepository;
6802 $io = $this->getIO();
6803 if (!($composer = $this->getComposer(false))) {
6804 $composer = Factory::create($this->getIO(), array(), $input->hasParameterOption('--no-plugins'));
6805 }
6806 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6807 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6808 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6809
6810 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6811 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6812
6813 $onlyName = $input->getOption('only-name');
6814 $type = $input->getOption('type') ?: null;
6815
6816 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6817 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6818
6819 foreach ($results as $result) {
6820 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6821 }
6822
6823 return 0;
6824 }
6825 }
6826 <?php
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838 namespace Composer\Command;
6839
6840 use Composer\Composer;
6841 use Composer\Factory;
6842 use Composer\Config;
6843 use Composer\Util\Filesystem;
6844 use Composer\SelfUpdate\Keys;
6845 use Composer\SelfUpdate\Versions;
6846 use Composer\IO\IOInterface;
6847 use Composer\Downloader\FilesystemException;
6848 use Symfony\Component\Console\Input\InputInterface;
6849 use Symfony\Component\Console\Input\InputOption;
6850 use Symfony\Component\Console\Input\InputArgument;
6851 use Symfony\Component\Console\Output\OutputInterface;
6852 use Symfony\Component\Finder\Finder;
6853
6854
6855
6856
6857
6858
6859 class SelfUpdateCommand extends BaseCommand
6860 {
6861 const HOMEPAGE = 'getcomposer.org';
6862 const OLD_INSTALL_EXT = '-old.phar';
6863
6864 protected function configure()
6865 {
6866 $this
6867 ->setName('self-update')
6868 ->setAliases(array('selfupdate'))
6869 ->setDescription('Updates composer.phar to the latest version.')
6870 ->setDefinition(array(
6871 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6872 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'),
6873 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6874 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6875 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6876 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6877 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6878 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6879 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6880 ))
6881 ->setHelp(
6882 <<<EOT
6883 The <info>self-update</info> command checks getcomposer.org for newer
6884 versions of composer and if found, installs the latest.
6885
6886 <info>php composer.phar self-update</info>
6887
6888 Read more at https://getcomposer.org/doc/03-cli.md#self-update-selfupdate-
6889 EOT
6890 )
6891 ;
6892 }
6893
6894 protected function execute(InputInterface $input, OutputInterface $output)
6895 {
6896 $config = Factory::createConfig();
6897
6898 if ($config->get('disable-tls') === true) {
6899 $baseUrl = 'http://' . self::HOMEPAGE;
6900 } else {
6901 $baseUrl = 'https://' . self::HOMEPAGE;
6902 }
6903
6904 $io = $this->getIO();
6905 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6906
6907 $versionsUtil = new Versions($config, $remoteFilesystem);
6908
6909
6910  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6911 if ($input->getOption($channel)) {
6912 $versionsUtil->setChannel($channel);
6913 }
6914 }
6915
6916 if ($input->getOption('set-channel-only')) {
6917 return 0;
6918 }
6919
6920 $cacheDir = $config->get('cache-dir');
6921 $rollbackDir = $config->get('data-dir');
6922 $home = $config->get('home');
6923 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6924
6925 if ($input->getOption('update-keys')) {
6926 return $this->fetchKeys($io, $config);
6927 }
6928
6929
6930  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6931
6932
6933  if (!is_writable($tmpDir)) {
6934 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6935 }
6936
6937
6938  if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
6939 $composeUser = posix_getpwuid(posix_geteuid());
6940 $homeOwner = posix_getpwuid(fileowner($home));
6941 if (isset($composeUser['name']) && isset($homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
6942 $io->writeError('<warning>You are running composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'"</warning>');
6943 }
6944 }
6945
6946 if ($input->getOption('rollback')) {
6947 return $this->rollback($output, $rollbackDir, $localFilename);
6948 }
6949
6950 $latest = $versionsUtil->getLatest();
6951 $latestVersion = $latest['version'];
6952 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6953
6954 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6955 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6956
6957 return 1;
6958 }
6959
6960 if (Composer::VERSION === $updateVersion) {
6961 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6962
6963
6964  if ($input->getOption('clean-backups')) {
6965 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6966 }
6967
6968 return 0;
6969 }
6970
6971 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6972 $backupFile = sprintf(
6973 '%s/%s-%s%s',
6974 $rollbackDir,
6975 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6976 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6977 self::OLD_INSTALL_EXT
6978 );
6979
6980 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6981
6982 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6983 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6984 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6985 $io->writeError('   ', false);
6986 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6987 $io->writeError('');
6988
6989 if (!file_exists($tempFilename) || !$signature) {
6990 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6991
6992 return 1;
6993 }
6994
6995
6996  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6997 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6998 } else {
6999 if (!extension_loaded('openssl')) {
7000 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
7001 . '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.');
7002 }
7003
7004 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
7005 if (!file_exists($sigFile)) {
7006 file_put_contents(
7007 $home.'/keys.dev.pub',
7008 <<<DEVPUBKEY
7009 -----BEGIN PUBLIC KEY-----
7010 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
7011 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
7012 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
7013 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
7014 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
7015 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
7016 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
7017 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
7018 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
7019 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
7020 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
7021 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
7022 -----END PUBLIC KEY-----
7023 DEVPUBKEY
7024 );
7025
7026 file_put_contents(
7027 $home.'/keys.tags.pub',
7028 <<<TAGSPUBKEY
7029 -----BEGIN PUBLIC KEY-----
7030 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
7031 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
7032 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
7033 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
7034 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
7035 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
7036 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
7037 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
7038 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
7039 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
7040 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
7041 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
7042 -----END PUBLIC KEY-----
7043 TAGSPUBKEY
7044 );
7045 }
7046
7047 $pubkeyid = openssl_pkey_get_public($sigFile);
7048 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
7049 if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) {
7050 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
7051 }
7052 $signature = json_decode($signature, true);
7053 $signature = base64_decode($signature['sha384']);
7054 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
7055 openssl_free_key($pubkeyid);
7056 if (!$verified) {
7057 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');
7058 }
7059 }
7060
7061
7062  if ($input->getOption('clean-backups')) {
7063 $this->cleanBackups($rollbackDir);
7064 }
7065
7066 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
7067 @unlink($tempFilename);
7068 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
7069 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
7070
7071 return 1;
7072 }
7073
7074 if (file_exists($backupFile)) {
7075 $io->writeError(sprintf(
7076 'Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>',
7077 Composer::VERSION
7078 ));
7079 } else {
7080 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
7081 }
7082
7083 return 0;
7084 }
7085
7086 protected function fetchKeys(IOInterface $io, Config $config)
7087 {
7088 if (!$io->isInteractive()) {
7089 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
7090 }
7091
7092 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
7093
7094 $validator = function ($value) {
7095 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
7096 throw new \UnexpectedValueException('Invalid input');
7097 }
7098
7099 return trim($value)."\n";
7100 };
7101
7102 $devKey = '';
7103 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
7104 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
7105 while ($line = $io->ask('')) {
7106 $devKey .= trim($line)."\n";
7107 if (trim($line) === '-----END PUBLIC KEY-----') {
7108 break;
7109 }
7110 }
7111 }
7112 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
7113 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7114
7115 $tagsKey = '';
7116 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
7117 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
7118 while ($line = $io->ask('')) {
7119 $tagsKey .= trim($line)."\n";
7120 if (trim($line) === '-----END PUBLIC KEY-----') {
7121 break;
7122 }
7123 }
7124 }
7125 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
7126 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7127
7128 $io->write('Public keys stored in '.$config->get('home'));
7129 }
7130
7131 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
7132 {
7133 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
7134 if (!$rollbackVersion) {
7135 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
7136 }
7137
7138 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
7139
7140 if (!is_file($oldFile)) {
7141 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
7142 }
7143 if (!is_readable($oldFile)) {
7144 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
7145 }
7146
7147 $io = $this->getIO();
7148 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
7149 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
7150 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
7151
7152 return 1;
7153 }
7154
7155 return 0;
7156 }
7157
7158
7159
7160
7161
7162
7163
7164
7165 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
7166 {
7167 try {
7168 @chmod($newFilename, fileperms($localFilename));
7169 if (!ini_get('phar.readonly')) {
7170
7171  $phar = new \Phar($newFilename);
7172
7173  unset($phar);
7174 }
7175
7176
7177  if ($backupTarget && file_exists($localFilename)) {
7178 @copy($localFilename, $backupTarget);
7179 }
7180
7181 rename($newFilename, $localFilename);
7182
7183 return null;
7184 } catch (\Exception $e) {
7185 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
7186 throw $e;
7187 }
7188
7189 return $e;
7190 }
7191 }
7192
7193 protected function cleanBackups($rollbackDir, $except = null)
7194 {
7195 $finder = $this->getOldInstallationFinder($rollbackDir);
7196 $io = $this->getIO();
7197 $fs = new Filesystem;
7198
7199 foreach ($finder as $file) {
7200 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
7201 continue;
7202 }
7203 $file = (string) $file;
7204 $io->writeError('<info>Removing: '.$file.'</info>');
7205 $fs->remove($file);
7206 }
7207 }
7208
7209 protected function getLastBackupVersion($rollbackDir)
7210 {
7211 $finder = $this->getOldInstallationFinder($rollbackDir);
7212 $finder->sortByName();
7213 $files = iterator_to_array($finder);
7214
7215 if (count($files)) {
7216 return basename(end($files), self::OLD_INSTALL_EXT);
7217 }
7218
7219 return false;
7220 }
7221
7222 protected function getOldInstallationFinder($rollbackDir)
7223 {
7224 $finder = Finder::create()
7225 ->depth(0)
7226 ->files()
7227 ->name('*' . self::OLD_INSTALL_EXT)
7228 ->in($rollbackDir);
7229
7230 return $finder;
7231 }
7232 }
7233 <?php
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245 namespace Composer\Command;
7246
7247 use Composer\Composer;
7248 use Composer\DependencyResolver\DefaultPolicy;
7249 use Composer\DependencyResolver\Pool;
7250 use Composer\Json\JsonFile;
7251 use Composer\Package\BasePackage;
7252 use Composer\Package\CompletePackageInterface;
7253 use Composer\Package\PackageInterface;
7254 use Composer\Package\Version\VersionParser;
7255 use Composer\Package\Version\VersionSelector;
7256 use Composer\Plugin\CommandEvent;
7257 use Composer\Plugin\PluginEvents;
7258 use Composer\Repository\ArrayRepository;
7259 use Composer\Repository\ComposerRepository;
7260 use Composer\Repository\CompositeRepository;
7261 use Composer\Repository\PlatformRepository;
7262 use Composer\Repository\RepositoryFactory;
7263 use Composer\Repository\RepositoryInterface;
7264 use Composer\Semver\Constraint\ConstraintInterface;
7265 use Composer\Semver\Semver;
7266 use Composer\Spdx\SpdxLicenses;
7267 use Composer\Util\Platform;
7268 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
7269 use Symfony\Component\Console\Input\InputArgument;
7270 use Symfony\Component\Console\Input\InputInterface;
7271 use Symfony\Component\Console\Input\InputOption;
7272 use Symfony\Component\Console\Output\OutputInterface;
7273 use Symfony\Component\Console\Terminal;
7274
7275
7276
7277
7278
7279
7280
7281 class ShowCommand extends BaseCommand
7282 {
7283
7284 protected $versionParser;
7285 protected $colors;
7286
7287
7288 private $pool;
7289
7290 protected function configure()
7291 {
7292 $this
7293 ->setName('show')
7294 ->setAliases(array('info'))
7295 ->setDescription('Shows information about packages.')
7296 ->setDefinition(array(
7297 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
7298 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
7299 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
7300 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
7301 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
7302 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
7303 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
7304 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
7305 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
7306 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
7307 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
7308 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
7309 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.'),
7310 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
7311 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
7312 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
7313 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
7314 ))
7315 ->setHelp(
7316 <<<EOT
7317 The show command displays detailed information about a package, or
7318 lists all packages available.
7319
7320 Read more at https://getcomposer.org/doc/03-cli.md#show
7321 EOT
7322 )
7323 ;
7324 }
7325
7326 protected function execute(InputInterface $input, OutputInterface $output)
7327 {
7328 $this->versionParser = new VersionParser;
7329 if ($input->getOption('tree')) {
7330 $this->initStyles($output);
7331 }
7332
7333 $composer = $this->getComposer(false);
7334 $io = $this->getIO();
7335
7336 if ($input->getOption('installed')) {
7337 $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>');
7338 }
7339
7340 if ($input->getOption('outdated')) {
7341 $input->setOption('latest', true);
7342 } elseif ($input->getOption('ignore')) {
7343 $io->writeError('<warning>You are using the option "ignore" for action other than "outdated", it will be ignored.</warning>');
7344 }
7345
7346 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
7347 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
7348
7349 return 1;
7350 }
7351
7352 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
7353 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
7354
7355 return 1;
7356 }
7357
7358 if ($input->getOption('tree') && $input->getOption('latest')) {
7359 $io->writeError('The --tree (-t) option is not usable in combination with --latest (-l)');
7360
7361 return 1;
7362 }
7363
7364 $format = $input->getOption('format');
7365 if (!in_array($format, array('text', 'json'))) {
7366 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
7367
7368 return 1;
7369 }
7370
7371
7372  $platformOverrides = array();
7373 if ($composer) {
7374 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
7375 }
7376 $platformRepo = new PlatformRepository(array(), $platformOverrides);
7377 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
7378
7379 if ($input->getOption('self')) {
7380 $package = $this->getComposer()->getPackage();
7381 $repos = $installedRepo = new ArrayRepository(array($package));
7382 } elseif ($input->getOption('platform')) {
7383 $repos = $installedRepo = $platformRepo;
7384 } elseif ($input->getOption('available')) {
7385 $installedRepo = $platformRepo;
7386 if ($composer) {
7387 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
7388 } else {
7389 $defaultRepos = RepositoryFactory::defaultRepos($io);
7390 $repos = new CompositeRepository($defaultRepos);
7391 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7392 }
7393 } elseif ($input->getOption('all') && $composer) {
7394 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
7395 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
7396 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
7397 } elseif ($input->getOption('all')) {
7398 $defaultRepos = RepositoryFactory::defaultRepos($io);
7399 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7400 $installedRepo = $platformRepo;
7401 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
7402 } else {
7403 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
7404 $rootPkg = $this->getComposer()->getPackage();
7405 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
7406 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
7407 }
7408 }
7409
7410 if ($composer) {
7411 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
7412 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7413 }
7414
7415 if ($input->getOption('latest') && null === $composer) {
7416 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
7417 $input->setOption('latest', false);
7418 }
7419
7420 $packageFilter = $input->getArgument('package');
7421
7422
7423  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
7424 if (empty($package)) {
7425 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
7426
7427 if (empty($package)) {
7428 $options = $input->getOptions();
7429 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
7430 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
7431 }
7432
7433 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
7434
7435 return 1;
7436 }
7437 } else {
7438 $versions = array($package->getPrettyVersion() => $package->getVersion());
7439 }
7440
7441 $exitCode = 0;
7442 if ($input->getOption('tree')) {
7443 $arrayTree = $this->generatePackageTree($package, $installedRepo, $repos);
7444
7445 if ('json' === $format) {
7446 $io->write(JsonFile::encode(array('installed' => array($arrayTree))));
7447 } else {
7448 $this->displayPackageTree(array($arrayTree));
7449 }
7450 } else {
7451 $latestPackage = null;
7452 if ($input->getOption('latest')) {
7453 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
7454 }
7455 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7456 $exitCode = 1;
7457 }
7458 if ($input->getOption('path')) {
7459 $io->write($package->getName(), false);
7460 $io->write(' ' . strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n"));
7461
7462 return $exitCode;
7463 }
7464 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
7465 $this->printLinks($package, 'requires');
7466 $this->printLinks($package, 'devRequires', 'requires (dev)');
7467 if ($package->getSuggests()) {
7468 $io->write("\n<info>suggests</info>");
7469 foreach ($package->getSuggests() as $suggested => $reason) {
7470 $io->write($suggested . ' <comment>' . $reason . '</comment>');
7471 }
7472 }
7473 $this->printLinks($package, 'provides');
7474 $this->printLinks($package, 'conflicts');
7475 $this->printLinks($package, 'replaces');
7476 }
7477
7478 return $exitCode;
7479 }
7480
7481
7482  if ($input->getOption('tree')) {
7483 $rootRequires = $this->getRootRequires();
7484 $packages = $installedRepo->getPackages();
7485 usort($packages, 'strcmp');
7486 $arrayTree = array();
7487 foreach ($packages as $package) {
7488 if (in_array($package->getName(), $rootRequires, true)) {
7489 $arrayTree[] = $this->generatePackageTree($package, $installedRepo, $repos);
7490 }
7491 }
7492
7493 if ('json' === $format) {
7494 $io->write(JsonFile::encode(array('installed' => $arrayTree)));
7495 } else {
7496 $this->displayPackageTree($arrayTree);
7497 }
7498
7499 return 0;
7500 }
7501
7502 if ($repos instanceof CompositeRepository) {
7503 $repos = $repos->getRepositories();
7504 } elseif (!is_array($repos)) {
7505 $repos = array($repos);
7506 }
7507
7508
7509  $packages = array();
7510 if (null !== $packageFilter) {
7511 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
7512 }
7513
7514 $packageListFilter = array();
7515 if ($input->getOption('direct')) {
7516 $packageListFilter = $this->getRootRequires();
7517 }
7518
7519 if (class_exists('Symfony\Component\Console\Terminal')) {
7520 $terminal = new Terminal();
7521 $width = $terminal->getWidth();
7522 } else {
7523
7524  list($width) = $this->getApplication()->getTerminalDimensions();
7525 }
7526 if (null === $width) {
7527
7528  
7529  $width = PHP_INT_MAX;
7530 }
7531 if (Platform::isWindows()) {
7532 $width--;
7533 } else {
7534 $width = max(80, $width);
7535 }
7536
7537 if ($input->getOption('path') && null === $composer) {
7538 $io->writeError('No composer.json found in the current directory, disabling "path" option');
7539 $input->setOption('path', false);
7540 }
7541
7542 foreach ($repos as $repo) {
7543 if ($repo === $platformRepo) {
7544 $type = 'platform';
7545 } elseif (
7546 $repo === $installedRepo
7547 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
7548 ) {
7549 $type = 'installed';
7550 } else {
7551 $type = 'available';
7552 }
7553 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
7554 foreach ($repo->getProviderNames() as $name) {
7555 if (!$packageFilter || preg_match($packageFilter, $name)) {
7556 $packages[$type][$name] = $name;
7557 }
7558 }
7559 } else {
7560 foreach ($repo->getPackages() as $package) {
7561 if (!isset($packages[$type][$package->getName()])
7562 || !is_object($packages[$type][$package->getName()])
7563 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
7564 ) {
7565 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
7566 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
7567 $packages[$type][$package->getName()] = $package;
7568 }
7569 }
7570 }
7571 }
7572 }
7573 }
7574
7575 $showAllTypes = $input->getOption('all');
7576 $showLatest = $input->getOption('latest');
7577 $showMinorOnly = $input->getOption('minor-only');
7578 $ignoredPackages = array_map('strtolower', $input->getOption('ignore'));
7579 $indent = $showAllTypes ? '  ' : '';
7580 $latestPackages = array();
7581 $exitCode = 0;
7582 $viewData = array();
7583 $viewMetaData = array();
7584 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
7585 if (isset($packages[$type])) {
7586 ksort($packages[$type]);
7587
7588 $nameLength = $versionLength = $latestLength = 0;
7589
7590 if ($showLatest && $showVersion) {
7591 foreach ($packages[$type] as $package) {
7592 if (is_object($package)) {
7593 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
7594 if ($latestPackage === false) {
7595 continue;
7596 }
7597
7598 $latestPackages[$package->getPrettyName()] = $latestPackage;
7599 }
7600 }
7601 }
7602
7603 $writePath = !$input->getOption('name-only') && $input->getOption('path');
7604 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
7605 $writeLatest = $writeVersion && $showLatest;
7606 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
7607
7608 $hasOutdatedPackages = false;
7609
7610 $viewData[$type] = array();
7611 foreach ($packages[$type] as $package) {
7612 $packageViewData = array();
7613 if (is_object($package)) {
7614 $latestPackage = null;
7615 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
7616 $latestPackage = $latestPackages[$package->getPrettyName()];
7617 }
7618
7619
7620  $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned();
7621 $packageIsIgnored = \in_array($package->getPrettyName(), $ignoredPackages, true);
7622 if ($input->getOption('outdated') && ($packageIsUpToDate || $packageIsIgnored)) {
7623 continue;
7624 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
7625 $hasOutdatedPackages = true;
7626 }
7627
7628 $packageViewData['name'] = $package->getPrettyName();
7629 $nameLength = max($nameLength, strlen($package->getPrettyName()));
7630 if ($writeVersion) {
7631 $packageViewData['version'] = $package->getFullPrettyVersion();
7632 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
7633 }
7634 if ($writeLatest && $latestPackage) {
7635 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
7636 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
7637 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
7638 }
7639 if ($writeDescription) {
7640 $packageViewData['description'] = $package->getDescription();
7641 }
7642 if ($writePath) {
7643 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
7644 }
7645
7646 if ($latestPackage && $latestPackage->isAbandoned()) {
7647 $replacement = is_string($latestPackage->getReplacementPackage())
7648 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
7649 : 'No replacement was suggested';
7650 $packageWarning = sprintf(
7651 'Package %s is abandoned, you should avoid using it. %s.',
7652 $package->getPrettyName(),
7653 $replacement
7654 );
7655 $packageViewData['warning'] = $packageWarning;
7656 }
7657 } else {
7658 $packageViewData['name'] = $package;
7659 $nameLength = max($nameLength, strlen($package));
7660 }
7661 $viewData[$type][] = $packageViewData;
7662 }
7663 $viewMetaData[$type] = array(
7664 'nameLength' => $nameLength,
7665 'versionLength' => $versionLength,
7666 'latestLength' => $latestLength,
7667 );
7668 if ($input->getOption('strict') && $hasOutdatedPackages) {
7669 $exitCode = 1;
7670 break;
7671 }
7672 }
7673 }
7674
7675 if ('json' === $format) {
7676 $io->write(JsonFile::encode($viewData));
7677 } else {
7678 foreach ($viewData as $type => $packages) {
7679 $nameLength = $viewMetaData[$type]['nameLength'];
7680 $versionLength = $viewMetaData[$type]['versionLength'];
7681 $latestLength = $viewMetaData[$type]['latestLength'];
7682
7683 $writeVersion = $nameLength + $versionLength + 3 <= $width;
7684 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
7685 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
7686
7687 if ($writeLatest && !$io->isDecorated()) {
7688 $latestLength += 2;
7689 }
7690
7691 if ($showAllTypes) {
7692 if ('available' === $type) {
7693 $io->write('<comment>' . $type . '</comment>:');
7694 } else {
7695 $io->write('<info>' . $type . '</info>:');
7696 }
7697 }
7698
7699 foreach ($packages as $package) {
7700 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
7701 if (isset($package['version']) && $writeVersion) {
7702 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
7703 }
7704 if (isset($package['latest']) && $writeLatest) {
7705 $latestVersion = $package['latest'];
7706 $updateStatus = $package['latest-status'];
7707 $style = $this->updateStatusToVersionStyle($updateStatus);
7708 if (!$io->isDecorated()) {
7709 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
7710 }
7711 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
7712 }
7713 if (isset($package['description']) && $writeDescription) {
7714 $description = strtok($package['description'], "\r\n");
7715 $remaining = $width - $nameLength - $versionLength - 4;
7716 if ($writeLatest) {
7717 $remaining -= $latestLength;
7718 }
7719 if (strlen($description) > $remaining) {
7720 $description = substr($description, 0, $remaining - 3) . '...';
7721 }
7722 $io->write(' ' . $description, false);
7723 }
7724 if (isset($package['path'])) {
7725 $io->write(' ' . $package['path'], false);
7726 }
7727 $io->write('');
7728 if (isset($package['warning'])) {
7729 $io->writeError('<warning>' . $package['warning'] . '</warning>');
7730 }
7731 }
7732
7733 if ($showAllTypes) {
7734 $io->write('');
7735 }
7736 }
7737 }
7738
7739 return $exitCode;
7740 }
7741
7742 protected function getRootRequires()
7743 {
7744 $rootPackage = $this->getComposer()->getPackage();
7745
7746 return array_map(
7747 'strtolower',
7748 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
7749 );
7750 }
7751
7752 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
7753 {
7754 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7755 }
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7768 {
7769 $name = strtolower($name);
7770 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7771
7772 $policy = new DefaultPolicy();
7773 $pool = new Pool('dev');
7774 $pool->addRepository($repos);
7775
7776 $matchedPackage = null;
7777 $versions = array();
7778 $matches = $pool->whatProvides($name, $constraint);
7779 foreach ($matches as $index => $package) {
7780
7781  if ($package->getName() !== $name) {
7782 unset($matches[$index]);
7783 continue;
7784 }
7785
7786
7787  if (null === $version && $installedRepo->hasPackage($package)) {
7788 $matchedPackage = $package;
7789 }
7790
7791 $versions[$package->getPrettyVersion()] = $package->getVersion();
7792 $matches[$index] = $package->getId();
7793 }
7794
7795
7796  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7797 $matchedPackage = $pool->literalToPackage($preferred[0]);
7798 }
7799
7800 return array($matchedPackage, $versions);
7801 }
7802
7803
7804
7805
7806
7807
7808
7809
7810 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7811 {
7812 $io = $this->getIO();
7813 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7814 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7815 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7816 $this->printVersions($package, $versions, $installedRepo);
7817 if ($latestPackage) {
7818 $style = $this->getVersionStyle($latestPackage, $package);
7819 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7820 } else {
7821 $latestPackage = $package;
7822 }
7823 $io->write('<info>type</info>     : ' . $package->getType());
7824 $this->printLicenses($package);
7825 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7826 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7827 if ($installedRepo->hasPackage($package)) {
7828 $io->write('<info>path</info>     : ' . sprintf('%s', realpath($this->getComposer()->getInstallationManager()->getInstallPath($package))));
7829 }
7830 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7831
7832 if ($latestPackage->isAbandoned()) {
7833 $replacement = ($latestPackage->getReplacementPackage() !== null)
7834 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7835 : null;
7836
7837 $io->writeError(
7838 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7839 );
7840 }
7841
7842 if ($package->getSupport()) {
7843 $io->write("\n<info>support</info>");
7844 foreach ($package->getSupport() as $type => $value) {
7845 $io->write('<comment>' . $type . '</comment> : '.$value);
7846 }
7847 }
7848
7849 if ($package->getAutoload()) {
7850 $io->write("\n<info>autoload</info>");
7851 foreach ($package->getAutoload() as $type => $autoloads) {
7852 $io->write('<comment>' . $type . '</comment>');
7853
7854 if ($type === 'psr-0') {
7855 foreach ($autoloads as $name => $path) {
7856 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7857 }
7858 } elseif ($type === 'psr-4') {
7859 foreach ($autoloads as $name => $path) {
7860 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7861 }
7862 } elseif ($type === 'classmap') {
7863 $io->write(implode(', ', $autoloads));
7864 }
7865 }
7866 if ($package->getIncludePaths()) {
7867 $io->write('<comment>include-path</comment>');
7868 $io->write(implode(', ', $package->getIncludePaths()));
7869 }
7870 }
7871 }
7872
7873
7874
7875
7876
7877
7878
7879
7880 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7881 {
7882 uasort($versions, 'version_compare');
7883 $versions = array_keys(array_reverse($versions));
7884
7885
7886  if ($installedRepo->hasPackage($package)) {
7887 $installedVersion = $package->getPrettyVersion();
7888 $key = array_search($installedVersion, $versions);
7889 if (false !== $key) {
7890 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7891 }
7892 }
7893
7894 $versions = implode(', ', $versions);
7895
7896 $this->getIO()->write('<info>versions</info> : ' . $versions);
7897 }
7898
7899
7900
7901
7902
7903
7904
7905
7906 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7907 {
7908 $title = $title ?: $linkType;
7909 $io = $this->getIO();
7910 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7911 $io->write("\n<info>" . $title . "</info>");
7912
7913 foreach ($links as $link) {
7914 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7915 }
7916 }
7917 }
7918
7919
7920
7921
7922
7923
7924 protected function printLicenses(CompletePackageInterface $package)
7925 {
7926 $spdxLicenses = new SpdxLicenses();
7927
7928 $licenses = $package->getLicense();
7929 $io = $this->getIO();
7930
7931 foreach ($licenses as $licenseId) {
7932 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7933
7934 if (!$license) {
7935 $out = $licenseId;
7936 } else {
7937
7938  if ($license[1] === true) {
7939 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7940 } else {
7941 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7942 }
7943 }
7944
7945 $io->write('<info>license</info>  : ' . $out);
7946 }
7947 }
7948
7949
7950
7951
7952
7953
7954 protected function initStyles(OutputInterface $output)
7955 {
7956 $this->colors = array(
7957 'green',
7958 'yellow',
7959 'cyan',
7960 'magenta',
7961 'blue',
7962 );
7963
7964 foreach ($this->colors as $color) {
7965 $style = new OutputFormatterStyle($color);
7966 $output->getFormatter()->setStyle($color, $style);
7967 }
7968 }
7969
7970
7971
7972
7973
7974
7975 protected function displayPackageTree(array $arrayTree)
7976 {
7977 $io = $this->getIO();
7978 foreach ($arrayTree as $package) {
7979 $io->write(sprintf('<info>%s</info>', $package['name']), false);
7980 $io->write(' ' . $package['version'], false);
7981 $io->write(' ' . strtok($package['description'], "\r\n"));
7982
7983 if (isset($package['requires'])) {
7984 $requires = $package['requires'];
7985 $treeBar = '├';
7986 $j = 0;
7987 $total = count($requires);
7988 foreach ($requires as $require) {
7989 $requireName = $require['name'];
7990 $j++;
7991 if ($j === $total) {
7992 $treeBar = '└';
7993 }
7994 $level = 1;
7995 $color = $this->colors[$level];
7996 $info = sprintf(
7997 '%s──<%s>%s</%s> %s',
7998 $treeBar,
7999 $color,
8000 $requireName,
8001 $color,
8002 $require['version']
8003 );
8004 $this->writeTreeLine($info);
8005
8006 $treeBar = str_replace('└', ' ', $treeBar);
8007 $packagesInTree = array($package['name'], $requireName);
8008
8009 $this->displayTree($require, $packagesInTree, $treeBar, $level + 1);
8010 }
8011 }
8012 }
8013 }
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023 protected function generatePackageTree(
8024 PackageInterface $package,
8025 RepositoryInterface $installedRepo,
8026 RepositoryInterface $distantRepos
8027 ) {
8028 $requires = $package->getRequires();
8029 ksort($requires);
8030 $children = array();
8031 foreach ($requires as $requireName => $require) {
8032 $packagesInTree = array($package->getName(), $requireName);
8033
8034 $treeChildDesc = array(
8035 'name' => $requireName,
8036 'version' => $require->getPrettyConstraint(),
8037 );
8038
8039 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree);
8040
8041 if ($deepChildren) {
8042 $treeChildDesc['requires'] = $deepChildren;
8043 }
8044
8045 $children[] = $treeChildDesc;
8046 }
8047 $tree = array(
8048 'name' => $package->getPrettyName(),
8049 'version' => $package->getPrettyVersion(),
8050 'description' => $package->getDescription(),
8051 );
8052
8053 if ($children) {
8054 $tree['requires'] = $children;
8055 }
8056
8057 return $tree;
8058 }
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068 protected function displayTree(
8069 $package,
8070 array $packagesInTree,
8071 $previousTreeBar = '├',
8072 $level = 1
8073 ) {
8074 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
8075 if (isset($package['requires'])) {
8076 $requires = $package['requires'];
8077 $treeBar = $previousTreeBar . '  ├';
8078 $i = 0;
8079 $total = count($requires);
8080 foreach ($requires as $require) {
8081 $currentTree = $packagesInTree;
8082 $i++;
8083 if ($i === $total) {
8084 $treeBar = $previousTreeBar . '  └';
8085 }
8086 $colorIdent = $level % count($this->colors);
8087 $color = $this->colors[$colorIdent];
8088
8089 $circularWarn = in_array(
8090 $require['name'],
8091 $currentTree,
8092 true
8093 ) ? '(circular dependency aborted here)' : '';
8094 $info = rtrim(sprintf(
8095 '%s──<%s>%s</%s> %s %s',
8096 $treeBar,
8097 $color,
8098 $require['name'],
8099 $color,
8100 $require['version'],
8101 $circularWarn
8102 ));
8103 $this->writeTreeLine($info);
8104
8105 $treeBar = str_replace('└', ' ', $treeBar);
8106
8107 $currentTree[] = $require['name'];
8108 $this->displayTree($require, $currentTree, $treeBar, $level + 1);
8109 }
8110 }
8111 }
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123 protected function addTree(
8124 $name,
8125 $package,
8126 RepositoryInterface $installedRepo,
8127 RepositoryInterface $distantRepos,
8128 array $packagesInTree
8129 ) {
8130 $children = array();
8131 list($package, $versions) = $this->getPackage(
8132 $installedRepo,
8133 $distantRepos,
8134 $name,
8135 $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint()
8136 );
8137 if (is_object($package)) {
8138 $requires = $package->getRequires();
8139 ksort($requires);
8140 foreach ($requires as $requireName => $require) {
8141 $currentTree = $packagesInTree;
8142
8143 $treeChildDesc = array(
8144 'name' => $requireName,
8145 'version' => $require->getPrettyConstraint(),
8146 );
8147
8148 if (!in_array($requireName, $currentTree, true)) {
8149 $currentTree[] = $requireName;
8150 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $currentTree);
8151 if ($deepChildren) {
8152 $treeChildDesc['requires'] = $deepChildren;
8153 }
8154 }
8155
8156 $children[] = $treeChildDesc;
8157 }
8158 }
8159
8160 return $children;
8161 }
8162
8163 private function updateStatusToVersionStyle($updateStatus)
8164 {
8165
8166  
8167  
8168  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
8169 }
8170
8171 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
8172 {
8173 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
8174 return 'up-to-date';
8175 }
8176
8177 $constraint = $package->getVersion();
8178 if (0 !== strpos($constraint, 'dev-')) {
8179 $constraint = '^'.$constraint;
8180 }
8181 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
8182
8183  return 'semver-safe-update';
8184 }
8185
8186
8187  return 'update-possible';
8188 }
8189
8190 private function writeTreeLine($line)
8191 {
8192 $io = $this->getIO();
8193 if (!$io->isDecorated()) {
8194 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
8195 }
8196
8197 $io->write($line);
8198 }
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
8211 {
8212
8213  $name = $package->getName();
8214 $versionSelector = new VersionSelector($this->getPool($composer));
8215 $stability = $composer->getPackage()->getMinimumStability();
8216 $flags = $composer->getPackage()->getStabilityFlags();
8217 if (isset($flags[$name])) {
8218 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
8219 }
8220
8221 $bestStability = $stability;
8222 if ($composer->getPackage()->getPreferStable()) {
8223 $bestStability = $package->getStability();
8224 }
8225
8226 $targetVersion = null;
8227 if (0 === strpos($package->getVersion(), 'dev-')) {
8228 $targetVersion = $package->getVersion();
8229 }
8230
8231 if ($targetVersion === null && $minorOnly) {
8232 $targetVersion = '^' . $package->getVersion();
8233 }
8234
8235 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
8236 }
8237
8238 private function getPool(Composer $composer)
8239 {
8240 if (!$this->pool) {
8241 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
8242 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
8243 }
8244
8245 return $this->pool;
8246 }
8247 }
8248 <?php
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260 namespace Composer\Command;
8261
8262 use Symfony\Component\Console\Input\InputInterface;
8263 use Symfony\Component\Console\Input\InputOption;
8264 use Symfony\Component\Console\Output\OutputInterface;
8265 use Composer\Downloader\ChangeReportInterface;
8266 use Composer\Downloader\DvcsDownloaderInterface;
8267 use Composer\Downloader\VcsCapableDownloaderInterface;
8268 use Composer\Package\Dumper\ArrayDumper;
8269 use Composer\Package\Version\VersionGuesser;
8270 use Composer\Package\Version\VersionParser;
8271 use Composer\Plugin\CommandEvent;
8272 use Composer\Plugin\PluginEvents;
8273 use Composer\Script\ScriptEvents;
8274 use Composer\Util\ProcessExecutor;
8275
8276
8277
8278
8279
8280 class StatusCommand extends BaseCommand
8281 {
8282 const EXIT_CODE_ERRORS = 1;
8283 const EXIT_CODE_UNPUSHED_CHANGES = 2;
8284 const EXIT_CODE_VERSION_CHANGES = 4;
8285
8286
8287
8288
8289 protected function configure()
8290 {
8291 $this
8292 ->setName('status')
8293 ->setDescription('Shows a list of locally modified packages, for packages installed from source.')
8294 ->setDefinition(array(
8295 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
8296 ))
8297 ->setHelp(
8298 <<<EOT
8299 The status command displays a list of dependencies that have
8300 been modified locally.
8301
8302 Read more at https://getcomposer.org/doc/03-cli.md#status
8303 EOT
8304 )
8305 ;
8306 }
8307
8308
8309
8310
8311
8312
8313 protected function execute(InputInterface $input, OutputInterface $output)
8314 {
8315
8316  $composer = $this->getComposer();
8317
8318 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
8319 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8320
8321 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
8322
8323 $dm = $composer->getDownloadManager();
8324 $im = $composer->getInstallationManager();
8325
8326
8327  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
8328
8329 $errors = array();
8330 $io = $this->getIO();
8331 $unpushedChanges = array();
8332 $vcsVersionChanges = array();
8333
8334 $parser = new VersionParser;
8335 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
8336 $dumper = new ArrayDumper;
8337
8338
8339  foreach ($installedRepo->getCanonicalPackages() as $package) {
8340 $downloader = $dm->getDownloaderForInstalledPackage($package);
8341 $targetDir = $im->getInstallPath($package);
8342
8343 if ($downloader instanceof ChangeReportInterface) {
8344 if (is_link($targetDir)) {
8345 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
8346 }
8347
8348 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
8349 $errors[$targetDir] = $changes;
8350 }
8351 }
8352
8353 if ($downloader instanceof VcsCapableDownloaderInterface) {
8354 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
8355 switch ($package->getInstallationSource()) {
8356 case 'source':
8357 $previousRef = $package->getSourceReference();
8358 break;
8359 case 'dist':
8360 $previousRef = $package->getDistReference();
8361 break;
8362 default:
8363 $previousRef = null;
8364 }
8365
8366 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
8367
8368 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
8369 $vcsVersionChanges[$targetDir] = array(
8370 'previous' => array(
8371 'version' => $package->getPrettyVersion(),
8372 'ref' => $previousRef,
8373 ),
8374 'current' => array(
8375 'version' => $currentVersion['pretty_version'],
8376 'ref' => $currentVersion['commit'],
8377 ),
8378 );
8379 }
8380 }
8381 }
8382
8383 if ($downloader instanceof DvcsDownloaderInterface) {
8384 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
8385 $unpushedChanges[$targetDir] = $unpushed;
8386 }
8387 }
8388 }
8389
8390
8391  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
8392 $io->writeError('<info>No local changes</info>');
8393
8394 return 0;
8395 }
8396
8397 if ($errors) {
8398 $io->writeError('<error>You have changes in the following dependencies:</error>');
8399
8400 foreach ($errors as $path => $changes) {
8401 if ($input->getOption('verbose')) {
8402 $indentedChanges = implode("\n", array_map(function ($line) {
8403 return '    ' . ltrim($line);
8404 }, explode("\n", $changes)));
8405 $io->write('<info>'.$path.'</info>:');
8406 $io->write($indentedChanges);
8407 } else {
8408 $io->write($path);
8409 }
8410 }
8411 }
8412
8413 if ($unpushedChanges) {
8414 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
8415
8416 foreach ($unpushedChanges as $path => $changes) {
8417 if ($input->getOption('verbose')) {
8418 $indentedChanges = implode("\n", array_map(function ($line) {
8419 return '    ' . ltrim($line);
8420 }, explode("\n", $changes)));
8421 $io->write('<info>'.$path.'</info>:');
8422 $io->write($indentedChanges);
8423 } else {
8424 $io->write($path);
8425 }
8426 }
8427 }
8428
8429 if ($vcsVersionChanges) {
8430 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
8431
8432 foreach ($vcsVersionChanges as $path => $changes) {
8433 if ($input->getOption('verbose')) {
8434
8435  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
8436 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
8437
8438 if ($io->isVeryVerbose()) {
8439
8440  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
8441 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
8442 }
8443
8444 $io->write('<info>'.$path.'</info>:');
8445 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
8446 } else {
8447 $io->write($path);
8448 }
8449 }
8450 }
8451
8452 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
8453 $io->writeError('Use --verbose (-v) to see a list of files');
8454 }
8455
8456
8457  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
8458
8459 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
8460 }
8461 }
8462 <?php
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474 namespace Composer\Command;
8475
8476 use Composer\Repository\PlatformRepository;
8477 use Symfony\Component\Console\Input\InputArgument;
8478 use Symfony\Component\Console\Input\InputInterface;
8479 use Symfony\Component\Console\Input\InputOption;
8480 use Symfony\Component\Console\Output\OutputInterface;
8481
8482 class SuggestsCommand extends BaseCommand
8483 {
8484 protected function configure()
8485 {
8486 $this
8487 ->setName('suggests')
8488 ->setDescription('Shows package suggestions.')
8489 ->setDefinition(array(
8490 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
8491 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
8492 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
8493 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
8494 ))
8495 ->setHelp(
8496 <<<EOT
8497
8498 The <info>%command.name%</info> command shows a sorted list of suggested packages.
8499
8500 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
8501
8502 Read more at https://getcomposer.org/doc/03-cli.md#suggests
8503 EOT
8504 )
8505 ;
8506 }
8507
8508 protected function execute(InputInterface $input, OutputInterface $output)
8509 {
8510 $lock = $this->getComposer()->getLocker()->getLockData();
8511
8512 if (empty($lock)) {
8513 throw new \RuntimeException('Lockfile seems to be empty?');
8514 }
8515
8516 $packages = $lock['packages'];
8517
8518 if (!$input->getOption('no-dev')) {
8519 $packages += $lock['packages-dev'];
8520 }
8521
8522 $filter = $input->getArgument('packages');
8523
8524
8525  $installed = array();
8526 foreach ($packages as $package) {
8527 $installed[] = $package['name'];
8528
8529 if (!empty($package['provide'])) {
8530 $installed = array_merge($installed, array_keys($package['provide']));
8531 }
8532
8533 if (!empty($package['replace'])) {
8534 $installed = array_merge($installed, array_keys($package['replace']));
8535 }
8536 }
8537
8538
8539  $installed = array_flip($installed);
8540 ksort($installed);
8541
8542
8543  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
8544
8545
8546  $suggesters = array();
8547 $suggested = array();
8548 foreach ($packages as $package) {
8549 $packageName = $package['name'];
8550 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
8551 continue;
8552 }
8553 foreach ($package['suggest'] as $suggestion => $reason) {
8554 if (false === strpos('/', $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
8555 continue;
8556 }
8557 if (!isset($installed[$suggestion])) {
8558 $suggesters[$packageName][$suggestion] = $reason;
8559 $suggested[$suggestion][$packageName] = $reason;
8560 }
8561 }
8562 }
8563 ksort($suggesters);
8564 ksort($suggested);
8565
8566
8567  $mode = 0;
8568 $io = $this->getIO();
8569 if ($input->getOption('by-package') || $io->isVerbose()) {
8570 $mode |= 1;
8571 }
8572 if ($input->getOption('by-suggestion')) {
8573 $mode |= 2;
8574 }
8575
8576
8577  if ($mode === 0) {
8578 foreach (array_keys($suggested) as $suggestion) {
8579 $io->write(sprintf('<info>%s</info>', $suggestion));
8580 }
8581
8582 return 0;
8583 }
8584
8585
8586  if ($mode & 1) {
8587 foreach ($suggesters as $suggester => $suggestions) {
8588 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
8589
8590 foreach ($suggestions as $suggestion => $reason) {
8591 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
8592 }
8593 $io->write('');
8594 }
8595 }
8596
8597
8598  if ($mode & 2) {
8599
8600  if ($mode & 1) {
8601 $io->write(str_repeat('-', 78));
8602 }
8603 foreach ($suggested as $suggestion => $suggesters) {
8604 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
8605
8606 foreach ($suggesters as $suggester => $reason) {
8607 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
8608 }
8609 $io->write('');
8610 }
8611 }
8612
8613 return 0;
8614 }
8615 }
8616 <?php
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628 namespace Composer\Command;
8629
8630 use Composer\Composer;
8631 use Composer\Installer;
8632 use Composer\IO\IOInterface;
8633 use Composer\Plugin\CommandEvent;
8634 use Composer\Plugin\PluginEvents;
8635 use Symfony\Component\Console\Helper\Table;
8636 use Symfony\Component\Console\Input\InputInterface;
8637 use Symfony\Component\Console\Input\InputOption;
8638 use Symfony\Component\Console\Input\InputArgument;
8639 use Symfony\Component\Console\Output\OutputInterface;
8640 use Symfony\Component\Console\Question\Question;
8641
8642
8643
8644
8645
8646 class UpdateCommand extends BaseCommand
8647 {
8648 protected function configure()
8649 {
8650 $this
8651 ->setName('update')
8652 ->setAliases(array('u', 'upgrade'))
8653 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
8654 ->setDefinition(array(
8655 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
8656 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
8657 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
8658 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
8659 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
8660 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
8661 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
8662 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
8663 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
8664 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
8665 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
8666 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
8667 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, except those defined in root package.'),
8668 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.'),
8669 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
8670 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
8671 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
8672 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
8673 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
8674 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
8675 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
8676 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
8677 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
8678 ))
8679 ->setHelp(
8680 <<<EOT
8681 The <info>update</info> command reads the composer.json file from the
8682 current directory, processes it, and updates, removes or installs all the
8683 dependencies.
8684
8685 <info>php composer.phar update</info>
8686
8687 To limit the update operation to a few packages, you can list the package(s)
8688 you want to update as such:
8689
8690 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
8691
8692 You may also use an asterisk (*) pattern to limit the update operation to package(s)
8693 from a specific vendor:
8694
8695 <info>php composer.phar update vendor/package1 foo/* [...]</info>
8696
8697 To select packages names interactively with auto-completion use <info>-i</info>.
8698
8699 Read more at https://getcomposer.org/doc/03-cli.md#update-u
8700 EOT
8701 )
8702 ;
8703 }
8704
8705 protected function execute(InputInterface $input, OutputInterface $output)
8706 {
8707 $io = $this->getIO();
8708 if ($input->getOption('no-custom-installers')) {
8709 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
8710 $input->setOption('no-plugins', true);
8711 }
8712
8713 if ($input->getOption('dev')) {
8714 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
8715 }
8716
8717 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
8718
8719 $packages = $input->getArgument('packages');
8720
8721 if ($input->getOption('interactive')) {
8722 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
8723 }
8724
8725 if ($input->getOption('root-reqs')) {
8726 $require = array_keys($composer->getPackage()->getRequires());
8727 if (!$input->getOption('no-dev')) {
8728 $requireDev = array_keys($composer->getPackage()->getDevRequires());
8729 $require = array_merge($require, $requireDev);
8730 }
8731
8732 if (!empty($packages)) {
8733 $packages = array_intersect($packages, $require);
8734 } else {
8735 $packages = $require;
8736 }
8737 }
8738
8739 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
8740
8741 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
8742 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8743
8744 $install = Installer::create($io, $composer);
8745
8746 $config = $composer->getConfig();
8747 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
8748
8749 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
8750 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
8751 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
8752
8753 $install
8754 ->setDryRun($input->getOption('dry-run'))
8755 ->setVerbose($input->getOption('verbose'))
8756 ->setPreferSource($preferSource)
8757 ->setPreferDist($preferDist)
8758 ->setDevMode(!$input->getOption('no-dev'))
8759 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
8760 ->setRunScripts(!$input->getOption('no-scripts'))
8761 ->setSkipSuggest($input->getOption('no-suggest'))
8762 ->setOptimizeAutoloader($optimize)
8763 ->setClassMapAuthoritative($authoritative)
8764 ->setApcuAutoloader($apcu)
8765 ->setUpdate(true)
8766 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
8767 ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies'))
8768 ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
8769 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
8770 ->setPreferStable($input->getOption('prefer-stable'))
8771 ->setPreferLowest($input->getOption('prefer-lowest'))
8772 ;
8773
8774 if ($input->getOption('no-plugins')) {
8775 $install->disablePlugins();
8776 }
8777
8778 return $install->run();
8779 }
8780
8781 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
8782 {
8783 if (!$input->isInteractive()) {
8784 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
8785 }
8786
8787 $requires = array_merge(
8788 $composer->getPackage()->getRequires(),
8789 $composer->getPackage()->getDevRequires()
8790 );
8791 $autocompleterValues = array();
8792 foreach ($requires as $require) {
8793 $target = $require->getTarget();
8794 $autocompleterValues[strtolower($target)] = $target;
8795 }
8796
8797 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
8798 foreach ($installedPackages as $package) {
8799 $autocompleterValues[$package->getName()] = $package->getPrettyName();
8800 }
8801
8802 $helper = $this->getHelper('question');
8803 $question = new Question('<comment>Enter package name: </comment>', null);
8804
8805 $io->writeError('<info>Press enter without value to end submission</info>');
8806
8807 do {
8808 $autocompleterValues = array_diff($autocompleterValues, $packages);
8809 $question->setAutocompleterValues($autocompleterValues);
8810 $addedPackage = $helper->ask($input, $output, $question);
8811
8812 if (!is_string($addedPackage) || empty($addedPackage)) {
8813 break;
8814 }
8815
8816 $addedPackage = strtolower($addedPackage);
8817 if (!in_array($addedPackage, $packages)) {
8818 $packages[] = $addedPackage;
8819 }
8820 } while (true);
8821
8822 $packages = array_filter($packages);
8823 if (!$packages) {
8824 throw new \InvalidArgumentException('You must enter minimum one package.');
8825 }
8826
8827 $table = new Table($output);
8828 $table->setHeaders(array('Selected packages'));
8829 foreach ($packages as $package) {
8830 $table->addRow(array($package));
8831 }
8832 $table->render();
8833
8834 if ($io->askConfirmation(sprintf(
8835 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
8836 1 === count($packages) ? '' : 's'
8837 ), true)) {
8838 return $packages;
8839 }
8840
8841 throw new \RuntimeException('Installation aborted.');
8842 }
8843 }
8844 <?php
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856 namespace Composer\Command;
8857
8858 use Composer\Factory;
8859 use Composer\Package\Loader\ValidatingArrayLoader;
8860 use Composer\Plugin\CommandEvent;
8861 use Composer\Plugin\PluginEvents;
8862 use Composer\Util\ConfigValidator;
8863 use Symfony\Component\Console\Input\InputArgument;
8864 use Symfony\Component\Console\Input\InputInterface;
8865 use Symfony\Component\Console\Input\InputOption;
8866 use Symfony\Component\Console\Output\OutputInterface;
8867
8868
8869
8870
8871
8872
8873
8874 class ValidateCommand extends BaseCommand
8875 {
8876
8877
8878
8879 protected function configure()
8880 {
8881 $this
8882 ->setName('validate')
8883 ->setDescription('Validates a composer.json and composer.lock.')
8884 ->setDefinition(array(
8885 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not validate requires for overly strict/loose constraints'),
8886 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
8887 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8888 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8889 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8890 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
8891 ))
8892 ->setHelp(
8893 <<<EOT
8894 The validate command validates a given composer.json and composer.lock
8895
8896 Exit codes in case of errors are:
8897 1 validation warning(s), only when --strict is given
8898 2 validation error(s)
8899 3 file unreadable or missing
8900
8901 Read more at https://getcomposer.org/doc/03-cli.md#validate
8902 EOT
8903 );
8904 }
8905
8906
8907
8908
8909
8910
8911
8912 protected function execute(InputInterface $input, OutputInterface $output)
8913 {
8914 $file = $input->getArgument('file') ?: Factory::getComposerFile();
8915 $io = $this->getIO();
8916
8917 if (!file_exists($file)) {
8918 $io->writeError('<error>' . $file . ' not found.</error>');
8919
8920 return 3;
8921 }
8922 if (!is_readable($file)) {
8923 $io->writeError('<error>' . $file . ' is not readable.</error>');
8924
8925 return 3;
8926 }
8927
8928 $validator = new ConfigValidator($io);
8929 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8930 $checkPublish = !$input->getOption('no-check-publish');
8931 $checkLock = !$input->getOption('no-check-lock');
8932 $isStrict = $input->getOption('strict');
8933 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8934
8935 $lockErrors = array();
8936 $composer = Factory::create($io, $file, $input->hasParameterOption('--no-plugins'));
8937 $locker = $composer->getLocker();
8938 if ($locker->isLocked() && !$locker->isFresh()) {
8939 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update`.';
8940 }
8941
8942 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true, $isStrict);
8943
8944
8945  $exitCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
8946
8947 if ($input->getOption('with-dependencies')) {
8948 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8949 foreach ($localRepo->getPackages() as $package) {
8950 $path = $composer->getInstallationManager()->getInstallPath($package);
8951 $file = $path . '/composer.json';
8952 if (is_dir($path) && file_exists($file)) {
8953 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8954 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8955
8956 $depCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
8957 $exitCode = max($depCode, $exitCode);
8958 }
8959 }
8960 }
8961
8962 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8963 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8964 $exitCode = max($eventCode, $exitCode);
8965
8966 return $exitCode;
8967 }
8968
8969 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false, $isStrict = false)
8970 {
8971 if (!$errors && !$publishErrors && !$warnings) {
8972 $io->write('<info>' . $name . ' is valid</info>');
8973 } elseif (!$errors && !$publishErrors) {
8974 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8975 if ($printSchemaUrl) {
8976 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8977 }
8978 } elseif (!$errors) {
8979 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8980 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8981 if ($printSchemaUrl) {
8982 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8983 }
8984 } else {
8985 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8986 }
8987
8988
8989  
8990  if ($checkPublish) {
8991 $errors = array_merge($errors, $publishErrors);
8992 } elseif (!$isStrict) {
8993 $warnings = array_merge($warnings, $publishErrors);
8994 }
8995
8996
8997  
8998  if ($checkLock) {
8999 $errors = array_merge($errors, $lockErrors);
9000 } elseif (!$isStrict) {
9001 $warnings = array_merge($warnings, $lockErrors);
9002 }
9003
9004 $messages = array(
9005 'error' => $errors,
9006 'warning' => $warnings,
9007 );
9008
9009 foreach ($messages as $style => $msgs) {
9010 foreach ($msgs as $msg) {
9011 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
9012 }
9013 }
9014 }
9015 }
9016 <?php
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028 namespace Composer;
9029
9030 use Composer\Package\RootPackageInterface;
9031 use Composer\Package\Locker;
9032 use Composer\Repository\RepositoryManager;
9033 use Composer\Installer\InstallationManager;
9034 use Composer\Plugin\PluginManager;
9035 use Composer\Downloader\DownloadManager;
9036 use Composer\EventDispatcher\EventDispatcher;
9037 use Composer\Autoload\AutoloadGenerator;
9038 use Composer\Package\Archiver\ArchiveManager;
9039
9040
9041
9042
9043
9044
9045 class Composer
9046 {
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
9067
9068 const VERSION = '1.9.1';
9069 const BRANCH_ALIAS_VERSION = '';
9070 const RELEASE_DATE = '2019-11-01 17:20:17';
9071 const SOURCE_VERSION = '';
9072
9073 public static function getVersion()
9074 {
9075
9076  if (self::VERSION === '@package_version'.'@') {
9077 return self::SOURCE_VERSION;
9078 }
9079
9080
9081  if (self::BRANCH_ALIAS_VERSION !== '' && preg_match('{^[a-f0-9]{40}$}', self::VERSION)) {
9082 return self::BRANCH_ALIAS_VERSION.'+'.self::VERSION;
9083 }
9084
9085 return self::VERSION;
9086 }
9087
9088
9089
9090
9091 private $package;
9092
9093
9094
9095
9096 private $locker;
9097
9098
9099
9100
9101 private $repositoryManager;
9102
9103
9104
9105
9106 private $downloadManager;
9107
9108
9109
9110
9111 private $installationManager;
9112
9113
9114
9115
9116 private $pluginManager;
9117
9118
9119
9120
9121 private $config;
9122
9123
9124
9125
9126 private $eventDispatcher;
9127
9128
9129
9130
9131 private $autoloadGenerator;
9132
9133
9134
9135
9136 private $archiveManager;
9137
9138
9139
9140
9141
9142 public function setPackage(RootPackageInterface $package)
9143 {
9144 $this->package = $package;
9145 }
9146
9147
9148
9149
9150 public function getPackage()
9151 {
9152 return $this->package;
9153 }
9154
9155
9156
9157
9158 public function setConfig(Config $config)
9159 {
9160 $this->config = $config;
9161 }
9162
9163
9164
9165
9166 public function getConfig()
9167 {
9168 return $this->config;
9169 }
9170
9171
9172
9173
9174 public function setLocker(Locker $locker)
9175 {
9176 $this->locker = $locker;
9177 }
9178
9179
9180
9181
9182 public function getLocker()
9183 {
9184 return $this->locker;
9185 }
9186
9187
9188
9189
9190 public function setRepositoryManager(RepositoryManager $manager)
9191 {
9192 $this->repositoryManager = $manager;
9193 }
9194
9195
9196
9197
9198 public function getRepositoryManager()
9199 {
9200 return $this->repositoryManager;
9201 }
9202
9203
9204
9205
9206 public function setDownloadManager(DownloadManager $manager)
9207 {
9208 $this->downloadManager = $manager;
9209 }
9210
9211
9212
9213
9214 public function getDownloadManager()
9215 {
9216 return $this->downloadManager;
9217 }
9218
9219
9220
9221
9222 public function setArchiveManager(ArchiveManager $manager)
9223 {
9224 $this->archiveManager = $manager;
9225 }
9226
9227
9228
9229
9230 public function getArchiveManager()
9231 {
9232 return $this->archiveManager;
9233 }
9234
9235
9236
9237
9238 public function setInstallationManager(InstallationManager $manager)
9239 {
9240 $this->installationManager = $manager;
9241 }
9242
9243
9244
9245
9246 public function getInstallationManager()
9247 {
9248 return $this->installationManager;
9249 }
9250
9251
9252
9253
9254 public function setPluginManager(PluginManager $manager)
9255 {
9256 $this->pluginManager = $manager;
9257 }
9258
9259
9260
9261
9262 public function getPluginManager()
9263 {
9264 return $this->pluginManager;
9265 }
9266
9267
9268
9269
9270 public function setEventDispatcher(EventDispatcher $eventDispatcher)
9271 {
9272 $this->eventDispatcher = $eventDispatcher;
9273 }
9274
9275
9276
9277
9278 public function getEventDispatcher()
9279 {
9280 return $this->eventDispatcher;
9281 }
9282
9283
9284
9285
9286 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
9287 {
9288 $this->autoloadGenerator = $autoloadGenerator;
9289 }
9290
9291
9292
9293
9294 public function getAutoloadGenerator()
9295 {
9296 return $this->autoloadGenerator;
9297 }
9298 }
9299 <?php
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311 namespace Composer;
9312
9313 use Composer\Config\ConfigSourceInterface;
9314 use Composer\Downloader\TransportException;
9315 use Composer\IO\IOInterface;
9316 use Composer\Util\Platform;
9317 use Composer\Util\ProcessExecutor;
9318
9319
9320
9321
9322 class Config
9323 {
9324 const RELATIVE_PATHS = 1;
9325
9326 public static $defaultConfig = array(
9327 'process-timeout' => 300,
9328 'use-include-path' => false,
9329 'preferred-install' => 'auto',
9330 'notify-on-install' => true,
9331 'github-protocols' => array('https', 'ssh', 'git'),
9332 'vendor-dir' => 'vendor',
9333 'bin-dir' => '{$vendor-dir}/bin',
9334 'cache-dir' => '{$home}/cache',
9335 'data-dir' => '{$home}',
9336 'cache-files-dir' => '{$cache-dir}/files',
9337 'cache-repo-dir' => '{$cache-dir}/repo',
9338 'cache-vcs-dir' => '{$cache-dir}/vcs',
9339 'cache-ttl' => 15552000, 
9340  'cache-files-ttl' => null, 
9341  'cache-files-maxsize' => '300MiB',
9342 'bin-compat' => 'auto',
9343 'discard-changes' => false,
9344 'autoloader-suffix' => null,
9345 'sort-packages' => false,
9346 'optimize-autoloader' => false,
9347 'classmap-authoritative' => false,
9348 'apcu-autoloader' => false,
9349 'prepend-autoloader' => true,
9350 'github-domains' => array('github.com'),
9351 'bitbucket-expose-hostname' => true,
9352 'disable-tls' => false,
9353 'secure-http' => true,
9354 'cafile' => null,
9355 'capath' => null,
9356 'github-expose-hostname' => true,
9357 'gitlab-domains' => array('gitlab.com'),
9358 'store-auths' => 'prompt',
9359 'platform' => array(),
9360 'archive-format' => 'tar',
9361 'archive-dir' => '.',
9362 'htaccess-protect' => true,
9363 'use-github-api' => true,
9364
9365  
9366  
9367  
9368  
9369  
9370  );
9371
9372 public static $defaultRepositories = array(
9373 'packagist.org' => array(
9374 'type' => 'composer',
9375 'url' => 'https?://repo.packagist.org',
9376 'allow_ssl_downgrade' => true,
9377 ),
9378 );
9379
9380 private $config;
9381 private $baseDir;
9382 private $repositories;
9383
9384 private $configSource;
9385
9386 private $authConfigSource;
9387 private $useEnvironment;
9388 private $warnedHosts = array();
9389
9390
9391
9392
9393
9394 public function __construct($useEnvironment = true, $baseDir = null)
9395 {
9396
9397  $this->config = static::$defaultConfig;
9398 $this->repositories = static::$defaultRepositories;
9399 $this->useEnvironment = (bool) $useEnvironment;
9400 $this->baseDir = $baseDir;
9401 }
9402
9403 public function setConfigSource(ConfigSourceInterface $source)
9404 {
9405 $this->configSource = $source;
9406 }
9407
9408 public function getConfigSource()
9409 {
9410 return $this->configSource;
9411 }
9412
9413 public function setAuthConfigSource(ConfigSourceInterface $source)
9414 {
9415 $this->authConfigSource = $source;
9416 }
9417
9418 public function getAuthConfigSource()
9419 {
9420 return $this->authConfigSource;
9421 }
9422
9423
9424
9425
9426
9427
9428 public function merge($config)
9429 {
9430
9431  if (!empty($config['config']) && is_array($config['config'])) {
9432 foreach ($config['config'] as $key => $val) {
9433 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
9434 $this->config[$key] = array_merge($this->config[$key], $val);
9435 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
9436 if (is_array($val) || is_array($this->config[$key])) {
9437 if (is_string($val)) {
9438 $val = array('*' => $val);
9439 }
9440 if (is_string($this->config[$key])) {
9441 $this->config[$key] = array('*' => $this->config[$key]);
9442 }
9443 $this->config[$key] = array_merge($this->config[$key], $val);
9444
9445  if (isset($this->config[$key]['*'])) {
9446 $wildcard = $this->config[$key]['*'];
9447 unset($this->config[$key]['*']);
9448 $this->config[$key]['*'] = $wildcard;
9449 }
9450 } else {
9451 $this->config[$key] = $val;
9452 }
9453 } else {
9454 $this->config[$key] = $val;
9455 }
9456 }
9457 }
9458
9459 if (!empty($config['repositories']) && is_array($config['repositories'])) {
9460 $this->repositories = array_reverse($this->repositories, true);
9461 $newRepos = array_reverse($config['repositories'], true);
9462 foreach ($newRepos as $name => $repository) {
9463
9464  if (false === $repository) {
9465 $this->disableRepoByName($name);
9466 continue;
9467 }
9468
9469
9470  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
9471 $this->disableRepoByName(key($repository));
9472 continue;
9473 }
9474
9475
9476  if (is_int($name)) {
9477 $this->repositories[] = $repository;
9478 } else {
9479 if ($name === 'packagist') { 
9480  $this->repositories[$name . '.org'] = $repository;
9481 } else {
9482 $this->repositories[$name] = $repository;
9483 }
9484 }
9485 }
9486 $this->repositories = array_reverse($this->repositories, true);
9487 }
9488 }
9489
9490
9491
9492
9493 public function getRepositories()
9494 {
9495 return $this->repositories;
9496 }
9497
9498
9499
9500
9501
9502
9503
9504
9505
9506 public function get($key, $flags = 0)
9507 {
9508 switch ($key) {
9509 case 'vendor-dir':
9510 case 'bin-dir':
9511 case 'process-timeout':
9512 case 'data-dir':
9513 case 'cache-dir':
9514 case 'cache-files-dir':
9515 case 'cache-repo-dir':
9516 case 'cache-vcs-dir':
9517 case 'cafile':
9518 case 'capath':
9519
9520  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
9521
9522 $val = $this->getComposerEnv($env);
9523 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
9524 $val = Platform::expandPath($val);
9525
9526 if (substr($key, -4) !== '-dir') {
9527 return $val;
9528 }
9529
9530 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
9531
9532 case 'htaccess-protect':
9533 $value = $this->getComposerEnv('COMPOSER_HTACCESS_PROTECT');
9534 if (false === $value) {
9535 $value = $this->config[$key];
9536 }
9537 return $value !== 'false' && (bool) $value;
9538
9539 case 'cache-ttl':
9540 return (int) $this->config[$key];
9541
9542 case 'cache-files-maxsize':
9543 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
9544 throw new \RuntimeException(
9545 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
9546 );
9547 }
9548 $size = $matches[1];
9549 if (isset($matches[2])) {
9550 switch (strtolower($matches[2])) {
9551 case 'g':
9552 $size *= 1024;
9553
9554  
9555  case 'm':
9556 $size *= 1024;
9557
9558  
9559  case 'k':
9560 $size *= 1024;
9561 break;
9562 }
9563 }
9564
9565 return $size;
9566
9567 case 'cache-files-ttl':
9568 if (isset($this->config[$key])) {
9569 return (int) $this->config[$key];
9570 }
9571
9572 return (int) $this->config['cache-ttl'];
9573
9574 case 'home':
9575 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
9576
9577 return rtrim($this->process($val, $flags), '/\\');
9578
9579 case 'bin-compat':
9580 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
9581
9582 if (!in_array($value, array('auto', 'full'))) {
9583 throw new \RuntimeException(
9584 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
9585 );
9586 }
9587
9588 return $value;
9589
9590 case 'discard-changes':
9591 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
9592 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
9593 throw new \RuntimeException(
9594 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
9595 );
9596 }
9597 if ('stash' === $env) {
9598 return 'stash';
9599 }
9600
9601
9602  return $env !== 'false' && (bool) $env;
9603 }
9604
9605 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
9606 throw new \RuntimeException(
9607 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
9608 );
9609 }
9610
9611 return $this->config[$key];
9612
9613 case 'github-protocols':
9614 $protos = $this->config['github-protocols'];
9615 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
9616 unset($protos[$index]);
9617 }
9618 if (reset($protos) === 'http') {
9619 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
9620 }
9621
9622 return $protos;
9623
9624 case 'disable-tls':
9625 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9626 case 'secure-http':
9627 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9628 case 'use-github-api':
9629 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
9630 default:
9631 if (!isset($this->config[$key])) {
9632 return null;
9633 }
9634
9635 return $this->process($this->config[$key], $flags);
9636 }
9637 }
9638
9639 public function all($flags = 0)
9640 {
9641 $all = array(
9642 'repositories' => $this->getRepositories(),
9643 );
9644 foreach (array_keys($this->config) as $key) {
9645 $all['config'][$key] = $this->get($key, $flags);
9646 }
9647
9648 return $all;
9649 }
9650
9651 public function raw()
9652 {
9653 return array(
9654 'repositories' => $this->getRepositories(),
9655 'config' => $this->config,
9656 );
9657 }
9658
9659
9660
9661
9662
9663
9664
9665 public function has($key)
9666 {
9667 return array_key_exists($key, $this->config);
9668 }
9669
9670
9671
9672
9673
9674
9675
9676
9677 private function process($value, $flags)
9678 {
9679 $config = $this;
9680
9681 if (!is_string($value)) {
9682 return $value;
9683 }
9684
9685 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
9686 return $config->get($match[1], $flags);
9687 }, $value);
9688 }
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698 private function realpath($path)
9699 {
9700 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
9701 return $path;
9702 }
9703
9704 return $this->baseDir . '/' . $path;
9705 }
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716 private function getComposerEnv($var)
9717 {
9718 if ($this->useEnvironment) {
9719 return getenv($var);
9720 }
9721
9722 return false;
9723 }
9724
9725 private function disableRepoByName($name)
9726 {
9727 if (isset($this->repositories[$name])) {
9728 unset($this->repositories[$name]);
9729 } elseif ($name === 'packagist') { 
9730  unset($this->repositories['packagist.org']);
9731 }
9732 }
9733
9734
9735
9736
9737
9738
9739
9740 public function prohibitUrlByConfig($url, IOInterface $io = null)
9741 {
9742
9743  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
9744 return;
9745 }
9746
9747
9748  $scheme = parse_url($url, PHP_URL_SCHEME);
9749 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
9750 if ($this->get('secure-http')) {
9751 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
9752 } elseif ($io) {
9753 $host = parse_url($url, PHP_URL_HOST);
9754 if (!isset($this->warnedHosts[$host])) {
9755 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
9756 }
9757 $this->warnedHosts[$host] = true;
9758 }
9759 }
9760 }
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772 public static function disableProcessTimeout()
9773 {
9774
9775  ProcessExecutor::setTimeout(0);
9776 }
9777 }
9778 <?php
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790 namespace Composer\Config;
9791
9792
9793
9794
9795
9796
9797
9798 interface ConfigSourceInterface
9799 {
9800
9801
9802
9803
9804
9805
9806 public function addRepository($name, $config);
9807
9808
9809
9810
9811
9812
9813 public function removeRepository($name);
9814
9815
9816
9817
9818
9819
9820
9821 public function addConfigSetting($name, $value);
9822
9823
9824
9825
9826
9827
9828 public function removeConfigSetting($name);
9829
9830
9831
9832
9833
9834
9835
9836 public function addProperty($name, $value);
9837
9838
9839
9840
9841
9842
9843 public function removeProperty($name);
9844
9845
9846
9847
9848
9849
9850
9851
9852 public function addLink($type, $name, $value);
9853
9854
9855
9856
9857
9858
9859
9860 public function removeLink($type, $name);
9861
9862
9863
9864
9865
9866
9867 public function getName();
9868 }
9869 <?php
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881 namespace Composer\Config;
9882
9883 use Composer\Json\JsonFile;
9884 use Composer\Json\JsonManipulator;
9885 use Composer\Util\Silencer;
9886
9887
9888
9889
9890
9891
9892
9893 class JsonConfigSource implements ConfigSourceInterface
9894 {
9895
9896
9897
9898 private $file;
9899
9900
9901
9902
9903 private $authConfig;
9904
9905
9906
9907
9908
9909
9910
9911 public function __construct(JsonFile $file, $authConfig = false)
9912 {
9913 $this->file = $file;
9914 $this->authConfig = $authConfig;
9915 }
9916
9917
9918
9919
9920 public function getName()
9921 {
9922 return $this->file->getPath();
9923 }
9924
9925
9926
9927
9928 public function addRepository($name, $config)
9929 {
9930 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
9931
9932  
9933  if (isset($config['repositories'])) {
9934 foreach ($config['repositories'] as $index => $val) {
9935 if ($index === $repo) {
9936 continue;
9937 }
9938 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
9939 unset($config['repositories'][$index]);
9940 $config['repositories']['packagist.org'] = false;
9941 break;
9942 }
9943 }
9944 }
9945
9946 $config['repositories'][$repo] = $repoConfig;
9947 });
9948 }
9949
9950
9951
9952
9953 public function removeRepository($name)
9954 {
9955 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9956 unset($config['repositories'][$repo]);
9957 });
9958 }
9959
9960
9961
9962
9963 public function addConfigSetting($name, $value)
9964 {
9965 $authConfig = $this->authConfig;
9966 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9967 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9968 list($key, $host) = explode('.', $key, 2);
9969 if ($authConfig) {
9970 $config[$key][$host] = $val;
9971 } else {
9972 $config['config'][$key][$host] = $val;
9973 }
9974 } else {
9975 $config['config'][$key] = $val;
9976 }
9977 });
9978 }
9979
9980
9981
9982
9983 public function removeConfigSetting($name)
9984 {
9985 $authConfig = $this->authConfig;
9986 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9987 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9988 list($key, $host) = explode('.', $key, 2);
9989 if ($authConfig) {
9990 unset($config[$key][$host]);
9991 } else {
9992 unset($config['config'][$key][$host]);
9993 }
9994 } else {
9995 unset($config['config'][$key]);
9996 }
9997 });
9998 }
9999
10000
10001
10002
10003 public function addProperty($name, $value)
10004 {
10005 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
10006 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10007 $bits = explode('.', $key);
10008 $last = array_pop($bits);
10009 $arr = &$config[reset($bits)];
10010 foreach ($bits as $bit) {
10011 if (!isset($arr[$bit])) {
10012 $arr[$bit] = array();
10013 }
10014 $arr = &$arr[$bit];
10015 }
10016 $arr[$last] = $val;
10017 } else {
10018 $config[$key] = $val;
10019 }
10020 });
10021 }
10022
10023
10024
10025
10026 public function removeProperty($name)
10027 {
10028 $authConfig = $this->authConfig;
10029 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
10030 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10031 $bits = explode('.', $key);
10032 $last = array_pop($bits);
10033 $arr = &$config[reset($bits)];
10034 foreach ($bits as $bit) {
10035 if (!isset($arr[$bit])) {
10036 return;
10037 }
10038 $arr = &$arr[$bit];
10039 }
10040 unset($arr[$last]);
10041 } else {
10042 unset($config[$key]);
10043 }
10044 });
10045 }
10046
10047
10048
10049
10050 public function addLink($type, $name, $value)
10051 {
10052 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
10053 $config[$type][$name] = $value;
10054 });
10055 }
10056
10057
10058
10059
10060 public function removeLink($type, $name)
10061 {
10062 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
10063 unset($config[$type][$name]);
10064
10065 if (0 === count($config[$type])) {
10066 unset($config[$type]);
10067 }
10068 });
10069 }
10070
10071 protected function manipulateJson($method, $args, $fallback)
10072 {
10073 $args = func_get_args();
10074
10075  array_shift($args);
10076 $fallback = array_pop($args);
10077
10078 if ($this->file->exists()) {
10079 if (!is_writable($this->file->getPath())) {
10080 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
10081 }
10082
10083 if (!is_readable($this->file->getPath())) {
10084 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
10085 }
10086
10087 $contents = file_get_contents($this->file->getPath());
10088 } elseif ($this->authConfig) {
10089 $contents = "{\n}\n";
10090 } else {
10091 $contents = "{\n    \"config\": {\n    }\n}\n";
10092 }
10093
10094 $manipulator = new JsonManipulator($contents);
10095
10096 $newFile = !$this->file->exists();
10097
10098
10099  if ($this->authConfig && $method === 'addConfigSetting') {
10100 $method = 'addSubNode';
10101 list($mainNode, $name) = explode('.', $args[0], 2);
10102 $args = array($mainNode, $name, $args[1]);
10103 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
10104 $method = 'removeSubNode';
10105 list($mainNode, $name) = explode('.', $args[0], 2);
10106 $args = array($mainNode, $name);
10107 }
10108
10109
10110  if (call_user_func_array(array($manipulator, $method), $args)) {
10111 file_put_contents($this->file->getPath(), $manipulator->getContents());
10112 } else {
10113
10114  $config = $this->file->read();
10115 $this->arrayUnshiftRef($args, $config);
10116 call_user_func_array($fallback, $args);
10117 $this->file->write($config);
10118 }
10119
10120 if ($newFile) {
10121 Silencer::call('chmod', $this->file->getPath(), 0600);
10122 }
10123 }
10124
10125
10126
10127
10128
10129
10130
10131
10132 private function arrayUnshiftRef(&$array, &$value)
10133 {
10134 $return = array_unshift($array, '');
10135 $array[0] = &$value;
10136
10137 return $return;
10138 }
10139 }
10140 <?php
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152 namespace Composer\Console;
10153
10154 use Composer\IO\NullIO;
10155 use Composer\Util\Platform;
10156 use Composer\Util\Silencer;
10157 use Symfony\Component\Console\Application as BaseApplication;
10158 use Symfony\Component\Console\Exception\CommandNotFoundException;
10159 use Symfony\Component\Console\Helper\HelperSet;
10160 use Symfony\Component\Console\Helper\QuestionHelper;
10161 use Symfony\Component\Console\Input\InputInterface;
10162 use Symfony\Component\Console\Input\InputOption;
10163 use Symfony\Component\Console\Output\OutputInterface;
10164 use Composer\Command;
10165 use Composer\Composer;
10166 use Composer\Factory;
10167 use Composer\IO\IOInterface;
10168 use Composer\IO\ConsoleIO;
10169 use Composer\Json\JsonValidationException;
10170 use Composer\Util\ErrorHandler;
10171 use Composer\EventDispatcher\ScriptExecutionException;
10172 use Composer\Exception\NoSslException;
10173
10174
10175
10176
10177
10178
10179
10180
10181 class Application extends BaseApplication
10182 {
10183
10184
10185
10186 protected $composer;
10187
10188
10189
10190
10191 protected $io;
10192
10193 private static $logo = '   ______
10194   / ____/___  ____ ___  ____  ____  ________  _____
10195  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
10196 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
10197 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
10198                     /_/
10199 ';
10200
10201 private $hasPluginCommands = false;
10202 private $disablePluginsByDefault = false;
10203
10204 public function __construct()
10205 {
10206 static $shutdownRegistered = false;
10207
10208 if (function_exists('ini_set') && extension_loaded('xdebug')) {
10209 ini_set('xdebug.show_exception_trace', false);
10210 ini_set('xdebug.scream', false);
10211 }
10212
10213 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
10214 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
10215 }
10216
10217 if (!$shutdownRegistered) {
10218 $shutdownRegistered = true;
10219
10220 register_shutdown_function(function () {
10221 $lastError = error_get_last();
10222
10223 if ($lastError && $lastError['message'] &&
10224 (strpos($lastError['message'], 'Allowed memory') !== false  ||
10225 strpos($lastError['message'], 'exceeded memory') !== false )) {
10226 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
10227 }
10228 });
10229 }
10230
10231 $this->io = new NullIO();
10232
10233 parent::__construct('Composer', Composer::getVersion());
10234 }
10235
10236
10237
10238
10239 public function run(InputInterface $input = null, OutputInterface $output = null)
10240 {
10241 if (null === $output) {
10242 $output = Factory::createOutput();
10243 }
10244
10245 return parent::run($input, $output);
10246 }
10247
10248
10249
10250
10251 public function doRun(InputInterface $input, OutputInterface $output)
10252 {
10253 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
10254
10255 if (getenv('COMPOSER_NO_INTERACTION')) {
10256 $input->setInteractive(false);
10257 }
10258
10259 $io = $this->io = new ConsoleIO($input, $output, new HelperSet(array(
10260 new QuestionHelper(),
10261 )));
10262 ErrorHandler::register($io);
10263
10264 if ($input->hasParameterOption('--no-cache')) {
10265 $io->writeError('Disabling cache usage', true, IOInterface::DEBUG);
10266 putenv('COMPOSER_CACHE_DIR='.(Platform::isWindows() ? 'nul' : '/dev/null'));
10267 }
10268
10269
10270  if ($newWorkDir = $this->getNewWorkingDir($input)) {
10271 $oldWorkingDir = getcwd();
10272 chdir($newWorkDir);
10273 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
10274 }
10275
10276
10277  $commandName = '';
10278 if ($name = $this->getCommandName($input)) {
10279 try {
10280 $commandName = $this->find($name)->getName();
10281 } catch (CommandNotFoundException $e) {
10282
10283  $commandName = false;
10284 } catch (\InvalidArgumentException $e) {
10285 }
10286 }
10287
10288
10289  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
10290 $dir = dirname(getcwd());
10291 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
10292
10293
10294  while (dirname($dir) !== $dir && $dir !== $home) {
10295 if (file_exists($dir.'/'.Factory::getComposerFile())) {
10296 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)) {
10297 $oldWorkingDir = getcwd();
10298 chdir($dir);
10299 }
10300 break;
10301 }
10302 $dir = dirname($dir);
10303 }
10304 }
10305
10306 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
10307 try {
10308 foreach ($this->getPluginCommands() as $command) {
10309 if ($this->has($command->getName())) {
10310 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
10311 } else {
10312 $this->add($command);
10313 }
10314 }
10315 } catch (NoSslException $e) {
10316
10317  }
10318
10319 $this->hasPluginCommands = true;
10320 }
10321
10322
10323  $isProxyCommand = false;
10324 if ($name = $this->getCommandName($input)) {
10325 try {
10326 $command = $this->find($name);
10327 $commandName = $command->getName();
10328 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
10329 } catch (\InvalidArgumentException $e) {
10330 }
10331 }
10332
10333 if (!$isProxyCommand) {
10334 $io->writeError(sprintf(
10335 'Running %s (%s) with %s on %s',
10336 Composer::getVersion(),
10337 Composer::RELEASE_DATE,
10338 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
10339 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
10340 ), true, IOInterface::DEBUG);
10341
10342 if (PHP_VERSION_ID < 50302) {
10343 $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>');
10344 }
10345
10346 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
10347 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
10348 }
10349
10350 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
10351 $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']));
10352 }
10353
10354 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER') && !file_exists('/.dockerenv')) {
10355 if (function_exists('posix_getuid') && posix_getuid() === 0) {
10356 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
10357 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
10358 }
10359 if ($uid = (int) getenv('SUDO_UID')) {
10360
10361  
10362  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
10363 }
10364 }
10365
10366  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
10367 }
10368
10369
10370  Silencer::call(function () use ($io) {
10371 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
10372 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
10373 $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()));
10374 }
10375 });
10376
10377
10378  $file = Factory::getComposerFile();
10379 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
10380 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
10381 foreach ($composer['scripts'] as $script => $dummy) {
10382 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
10383 if ($this->has($script)) {
10384 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
10385 } else {
10386 $description = null;
10387
10388 if (isset($composer['scripts-descriptions'][$script])) {
10389 $description = $composer['scripts-descriptions'][$script];
10390 }
10391
10392 $this->add(new Command\ScriptAliasCommand($script, $description));
10393 }
10394 }
10395 }
10396 }
10397 }
10398 }
10399
10400 try {
10401 if ($input->hasParameterOption('--profile')) {
10402 $startTime = microtime(true);
10403 $this->io->enableDebugging($startTime);
10404 }
10405
10406 $result = parent::doRun($input, $output);
10407
10408 if (isset($oldWorkingDir)) {
10409 chdir($oldWorkingDir);
10410 }
10411
10412 if (isset($startTime)) {
10413 $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');
10414 }
10415
10416 restore_error_handler();
10417
10418 return $result;
10419 } catch (ScriptExecutionException $e) {
10420 return $e->getCode();
10421 } catch (\Exception $e) {
10422 $this->hintCommonErrors($e);
10423 restore_error_handler();
10424 throw $e;
10425 }
10426 }
10427
10428
10429
10430
10431
10432
10433 private function getNewWorkingDir(InputInterface $input)
10434 {
10435 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
10436 if (false !== $workingDir && !is_dir($workingDir)) {
10437 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
10438 }
10439
10440 return $workingDir;
10441 }
10442
10443
10444
10445
10446 private function hintCommonErrors($exception)
10447 {
10448 $io = $this->getIO();
10449
10450 Silencer::suppress();
10451 try {
10452 $composer = $this->getComposer(false, true);
10453 if ($composer) {
10454 $config = $composer->getConfig();
10455
10456 $minSpaceFree = 1024 * 1024;
10457 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
10458 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
10459 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
10460 ) {
10461 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
10462 }
10463 }
10464 } catch (\Exception $e) {
10465 }
10466 Silencer::restore();
10467
10468 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
10469 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
10470 $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);
10471 }
10472
10473 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
10474 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
10475 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
10476 }
10477 }
10478
10479
10480
10481
10482
10483
10484
10485 public function getComposer($required = true, $disablePlugins = null)
10486 {
10487 if (null === $disablePlugins) {
10488 $disablePlugins = $this->disablePluginsByDefault;
10489 }
10490
10491 if (null === $this->composer) {
10492 try {
10493 $this->composer = Factory::create($this->io, null, $disablePlugins);
10494 } catch (\InvalidArgumentException $e) {
10495 if ($required) {
10496 $this->io->writeError($e->getMessage());
10497 exit(1);
10498 }
10499 } catch (JsonValidationException $e) {
10500 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
10501 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
10502 throw new JsonValidationException($message);
10503 }
10504 }
10505
10506 return $this->composer;
10507 }
10508
10509
10510
10511
10512 public function resetComposer()
10513 {
10514 $this->composer = null;
10515 if ($this->getIO() && method_exists($this->getIO(), 'resetAuthentications')) {
10516 $this->getIO()->resetAuthentications();
10517 }
10518 }
10519
10520
10521
10522
10523 public function getIO()
10524 {
10525 return $this->io;
10526 }
10527
10528 public function getHelp()
10529 {
10530 return self::$logo . parent::getHelp();
10531 }
10532
10533
10534
10535
10536 protected function getDefaultCommands()
10537 {
10538 $commands = array_merge(parent::getDefaultCommands(), array(
10539 new Command\AboutCommand(),
10540 new Command\ConfigCommand(),
10541 new Command\DependsCommand(),
10542 new Command\ProhibitsCommand(),
10543 new Command\InitCommand(),
10544 new Command\InstallCommand(),
10545 new Command\CreateProjectCommand(),
10546 new Command\UpdateCommand(),
10547 new Command\SearchCommand(),
10548 new Command\ValidateCommand(),
10549 new Command\ShowCommand(),
10550 new Command\SuggestsCommand(),
10551 new Command\RequireCommand(),
10552 new Command\DumpAutoloadCommand(),
10553 new Command\StatusCommand(),
10554 new Command\ArchiveCommand(),
10555 new Command\DiagnoseCommand(),
10556 new Command\RunScriptCommand(),
10557 new Command\LicensesCommand(),
10558 new Command\GlobalCommand(),
10559 new Command\ClearCacheCommand(),
10560 new Command\RemoveCommand(),
10561 new Command\HomeCommand(),
10562 new Command\ExecCommand(),
10563 new Command\OutdatedCommand(),
10564 new Command\CheckPlatformReqsCommand(),
10565 ));
10566
10567 if ('phar:' === substr(__FILE__, 0, 5)) {
10568 $commands[] = new Command\SelfUpdateCommand();
10569 }
10570
10571 return $commands;
10572 }
10573
10574
10575
10576
10577 public function getLongVersion()
10578 {
10579 if (Composer::BRANCH_ALIAS_VERSION && Composer::BRANCH_ALIAS_VERSION !== '@package_branch_alias_version'.'@') {
10580 return sprintf(
10581 '<info>%s</info> version <comment>%s (%s)</comment> %s',
10582 $this->getName(),
10583 Composer::BRANCH_ALIAS_VERSION,
10584 $this->getVersion(),
10585 Composer::RELEASE_DATE
10586 );
10587 }
10588
10589 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
10590 }
10591
10592
10593
10594
10595 protected function getDefaultInputDefinition()
10596 {
10597 $definition = parent::getDefaultInputDefinition();
10598 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
10599 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
10600 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
10601 $definition->addOption(new InputOption('--no-cache', null, InputOption::VALUE_NONE, 'Prevent use of the cache'));
10602
10603 return $definition;
10604 }
10605
10606 private function getPluginCommands()
10607 {
10608 $commands = array();
10609
10610 $composer = $this->getComposer(false, false);
10611 if (null === $composer) {
10612 $composer = Factory::createGlobal($this->io, false);
10613 }
10614
10615 if (null !== $composer) {
10616 $pm = $composer->getPluginManager();
10617 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
10618 $newCommands = $capability->getCommands();
10619 if (!is_array($newCommands)) {
10620 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
10621 }
10622 foreach ($newCommands as $command) {
10623 if (!$command instanceof Command\BaseCommand) {
10624 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
10625 }
10626 }
10627 $commands = array_merge($commands, $newCommands);
10628 }
10629 }
10630
10631 return $commands;
10632 }
10633 }
10634 <?php
10635
10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646 namespace Composer\Console;
10647
10648 use Symfony\Component\Console\Formatter\OutputFormatter;
10649
10650
10651
10652
10653 class HtmlOutputFormatter extends OutputFormatter
10654 {
10655 private static $availableForegroundColors = array(
10656 30 => 'black',
10657 31 => 'red',
10658 32 => 'green',
10659 33 => 'yellow',
10660 34 => 'blue',
10661 35 => 'magenta',
10662 36 => 'cyan',
10663 37 => 'white',
10664 );
10665 private static $availableBackgroundColors = array(
10666 40 => 'black',
10667 41 => 'red',
10668 42 => 'green',
10669 43 => 'yellow',
10670 44 => 'blue',
10671 45 => 'magenta',
10672 46 => 'cyan',
10673 47 => 'white',
10674 );
10675 private static $availableOptions = array(
10676 1 => 'bold',
10677 4 => 'underscore',
10678
10679  
10680  
10681  );
10682
10683
10684
10685
10686 public function __construct(array $styles = array())
10687 {
10688 parent::__construct(true, $styles);
10689 }
10690
10691 public function format($message)
10692 {
10693 $formatted = parent::format($message);
10694
10695 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
10696
10697 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
10698 }
10699
10700 private function formatHtml($matches)
10701 {
10702 $out = '<span style="';
10703 foreach (explode(';', $matches[1]) as $code) {
10704 if (isset(self::$availableForegroundColors[$code])) {
10705 $out .= 'color:'.self::$availableForegroundColors[$code].';';
10706 } elseif (isset(self::$availableBackgroundColors[$code])) {
10707 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
10708 } elseif (isset(self::$availableOptions[$code])) {
10709 switch (self::$availableOptions[$code]) {
10710 case 'bold':
10711 $out .= 'font-weight:bold;';
10712 break;
10713
10714 case 'underscore':
10715 $out .= 'text-decoration:underline;';
10716 break;
10717 }
10718 }
10719 }
10720
10721 return $out.'">'.$matches[2].'</span>';
10722 }
10723 }
10724 <?php
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736 namespace Composer\DependencyResolver;
10737
10738
10739
10740
10741
10742
10743 class Decisions implements \Iterator, \Countable
10744 {
10745 const DECISION_LITERAL = 0;
10746 const DECISION_REASON = 1;
10747
10748 protected $pool;
10749 protected $decisionMap;
10750 protected $decisionQueue = array();
10751
10752 public function __construct($pool)
10753 {
10754 $this->pool = $pool;
10755 $this->decisionMap = array();
10756 }
10757
10758 public function decide($literal, $level, $why)
10759 {
10760 $this->addDecision($literal, $level);
10761 $this->decisionQueue[] = array(
10762 self::DECISION_LITERAL => $literal,
10763 self::DECISION_REASON => $why,
10764 );
10765 }
10766
10767 public function satisfy($literal)
10768 {
10769 $packageId = abs($literal);
10770
10771 return (
10772 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
10773 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
10774 );
10775 }
10776
10777 public function conflict($literal)
10778 {
10779 $packageId = abs($literal);
10780
10781 return (
10782 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
10783 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
10784 );
10785 }
10786
10787 public function decided($literalOrPackageId)
10788 {
10789 return !empty($this->decisionMap[abs($literalOrPackageId)]);
10790 }
10791
10792 public function undecided($literalOrPackageId)
10793 {
10794 return empty($this->decisionMap[abs($literalOrPackageId)]);
10795 }
10796
10797 public function decidedInstall($literalOrPackageId)
10798 {
10799 $packageId = abs($literalOrPackageId);
10800
10801 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
10802 }
10803
10804 public function decisionLevel($literalOrPackageId)
10805 {
10806 $packageId = abs($literalOrPackageId);
10807 if (isset($this->decisionMap[$packageId])) {
10808 return abs($this->decisionMap[$packageId]);
10809 }
10810
10811 return 0;
10812 }
10813
10814 public function decisionRule($literalOrPackageId)
10815 {
10816 $packageId = abs($literalOrPackageId);
10817
10818 foreach ($this->decisionQueue as $i => $decision) {
10819 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
10820 return $decision[self::DECISION_REASON];
10821 }
10822 }
10823
10824 return null;
10825 }
10826
10827 public function atOffset($queueOffset)
10828 {
10829 return $this->decisionQueue[$queueOffset];
10830 }
10831
10832 public function validOffset($queueOffset)
10833 {
10834 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
10835 }
10836
10837 public function lastReason()
10838 {
10839 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
10840 }
10841
10842 public function lastLiteral()
10843 {
10844 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
10845 }
10846
10847 public function reset()
10848 {
10849 while ($decision = array_pop($this->decisionQueue)) {
10850 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10851 }
10852 }
10853
10854 public function resetToOffset($offset)
10855 {
10856 while (count($this->decisionQueue) > $offset + 1) {
10857 $decision = array_pop($this->decisionQueue);
10858 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
10859 }
10860 }
10861
10862 public function revertLast()
10863 {
10864 $this->decisionMap[abs($this->lastLiteral())] = 0;
10865 array_pop($this->decisionQueue);
10866 }
10867
10868 public function count()
10869 {
10870 return count($this->decisionQueue);
10871 }
10872
10873 public function rewind()
10874 {
10875 end($this->decisionQueue);
10876 }
10877
10878 public function current()
10879 {
10880 return current($this->decisionQueue);
10881 }
10882
10883 public function key()
10884 {
10885 return key($this->decisionQueue);
10886 }
10887
10888 public function next()
10889 {
10890 return prev($this->decisionQueue);
10891 }
10892
10893 public function valid()
10894 {
10895 return false !== current($this->decisionQueue);
10896 }
10897
10898 public function isEmpty()
10899 {
10900 return count($this->decisionQueue) === 0;
10901 }
10902
10903 protected function addDecision($literal, $level)
10904 {
10905 $packageId = abs($literal);
10906
10907 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
10908 if ($previousDecision != 0) {
10909 $literalString = $this->pool->literalToString($literal);
10910 $package = $this->pool->literalToPackage($literal);
10911 throw new SolverBugException(
10912 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
10913 );
10914 }
10915
10916 if ($literal > 0) {
10917 $this->decisionMap[$packageId] = $level;
10918 } else {
10919 $this->decisionMap[$packageId] = -$level;
10920 }
10921 }
10922
10923 public function __toString()
10924 {
10925 $decisionMap = $this->decisionMap;
10926 ksort($decisionMap);
10927 $str = '[';
10928 foreach ($decisionMap as $packageId => $level) {
10929 $str .= $packageId.':'.$level.',';
10930 }
10931 $str .= ']';
10932 return $str;
10933 }
10934 }
10935 <?php
10936
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947 namespace Composer\DependencyResolver;
10948
10949 use Composer\Package\PackageInterface;
10950 use Composer\Package\AliasPackage;
10951 use Composer\Package\BasePackage;
10952 use Composer\Semver\Constraint\Constraint;
10953
10954
10955
10956
10957
10958 class DefaultPolicy implements PolicyInterface
10959 {
10960 private $preferStable;
10961 private $preferLowest;
10962
10963 public function __construct($preferStable = false, $preferLowest = false)
10964 {
10965 $this->preferStable = $preferStable;
10966 $this->preferLowest = $preferLowest;
10967 }
10968
10969 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
10970 {
10971 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
10972 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
10973 }
10974
10975 $constraint = new Constraint($operator, $b->getVersion());
10976 $version = new Constraint('==', $a->getVersion());
10977
10978 return $constraint->matchSpecific($version, true);
10979 }
10980
10981 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
10982 {
10983 $packages = array();
10984
10985 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
10986 if ($candidate !== $package) {
10987 $packages[] = $candidate;
10988 }
10989 }
10990
10991 return $packages;
10992 }
10993
10994 public function getPriority(Pool $pool, PackageInterface $package)
10995 {
10996 return $pool->getPriority($package->getRepository());
10997 }
10998
10999 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
11000 {
11001 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
11002
11003 foreach ($packages as &$literals) {
11004 $policy = $this;
11005 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11006 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
11007 });
11008 }
11009
11010 foreach ($packages as &$literals) {
11011 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
11012
11013 $literals = $this->pruneToBestVersion($pool, $literals);
11014
11015 $literals = $this->pruneRemoteAliases($pool, $literals);
11016 }
11017
11018 $selected = call_user_func_array('array_merge', $packages);
11019
11020
11021  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11022 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
11023 });
11024
11025 return $selected;
11026 }
11027
11028 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
11029 {
11030 $packages = array();
11031 foreach ($literals as $literal) {
11032 $packageName = $pool->literalToPackage($literal)->getName();
11033
11034 if (!isset($packages[$packageName])) {
11035 $packages[$packageName] = array();
11036 }
11037
11038 if (isset($installedMap[abs($literal)])) {
11039 array_unshift($packages[$packageName], $literal);
11040 } else {
11041 $packages[$packageName][] = $literal;
11042 }
11043 }
11044
11045 return $packages;
11046 }
11047
11048
11049
11050
11051 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
11052 {
11053 if ($a->getRepository() === $b->getRepository()) {
11054
11055  if ($a->getName() === $b->getName()) {
11056 $aAliased = $a instanceof AliasPackage;
11057 $bAliased = $b instanceof AliasPackage;
11058 if ($aAliased && !$bAliased) {
11059 return -1; 
11060  }
11061 if (!$aAliased && $bAliased) {
11062 return 1; 
11063  }
11064 }
11065
11066 if (!$ignoreReplace) {
11067
11068  if ($this->replaces($a, $b)) {
11069 return 1; 
11070  }
11071 if ($this->replaces($b, $a)) {
11072 return -1; 
11073  }
11074
11075
11076  
11077  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
11078 $requiredVendor = substr($requiredPackage, 0, $pos);
11079
11080 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
11081 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
11082
11083 if ($bIsSameVendor !== $aIsSameVendor) {
11084 return $aIsSameVendor ? -1 : 1;
11085 }
11086 }
11087 }
11088
11089
11090  if ($a->id === $b->id) {
11091 return 0;
11092 }
11093
11094 return ($a->id < $b->id) ? -1 : 1;
11095 }
11096
11097 if (isset($installedMap[$a->id])) {
11098 return -1;
11099 }
11100
11101 if (isset($installedMap[$b->id])) {
11102 return 1;
11103 }
11104
11105 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
11106 }
11107
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118 protected function replaces(PackageInterface $source, PackageInterface $target)
11119 {
11120 foreach ($source->getReplaces() as $link) {
11121 if ($link->getTarget() === $target->getName()
11122
11123
11124  ) {
11125 return true;
11126 }
11127 }
11128
11129 return false;
11130 }
11131
11132 protected function pruneToBestVersion(Pool $pool, $literals)
11133 {
11134 $operator = $this->preferLowest ? '<' : '>';
11135 $bestLiterals = array($literals[0]);
11136 $bestPackage = $pool->literalToPackage($literals[0]);
11137 foreach ($literals as $i => $literal) {
11138 if (0 === $i) {
11139 continue;
11140 }
11141
11142 $package = $pool->literalToPackage($literal);
11143
11144 if ($this->versionCompare($package, $bestPackage, $operator)) {
11145 $bestPackage = $package;
11146 $bestLiterals = array($literal);
11147 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
11148 $bestLiterals[] = $literal;
11149 }
11150 }
11151
11152 return $bestLiterals;
11153 }
11154
11155
11156
11157
11158 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
11159 {
11160 $selected = array();
11161
11162 $priority = null;
11163
11164 foreach ($literals as $literal) {
11165 $package = $pool->literalToPackage($literal);
11166
11167 if (isset($installedMap[$package->id])) {
11168 $selected[] = $literal;
11169 continue;
11170 }
11171
11172 if (null === $priority) {
11173 $priority = $this->getPriority($pool, $package);
11174 }
11175
11176 if ($this->getPriority($pool, $package) != $priority) {
11177 break;
11178 }
11179
11180 $selected[] = $literal;
11181 }
11182
11183 return $selected;
11184 }
11185
11186
11187
11188
11189
11190
11191 protected function pruneRemoteAliases(Pool $pool, array $literals)
11192 {
11193 $hasLocalAlias = false;
11194
11195 foreach ($literals as $literal) {
11196 $package = $pool->literalToPackage($literal);
11197
11198 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
11199 $hasLocalAlias = true;
11200 break;
11201 }
11202 }
11203
11204 if (!$hasLocalAlias) {
11205 return $literals;
11206 }
11207
11208 $selected = array();
11209 foreach ($literals as $literal) {
11210 $package = $pool->literalToPackage($literal);
11211
11212 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
11213 $selected[] = $literal;
11214 }
11215 }
11216
11217 return $selected;
11218 }
11219 }
11220 <?php
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232 namespace Composer\DependencyResolver;
11233
11234 use Composer\Package\PackageInterface;
11235 use Composer\Package\Link;
11236
11237
11238
11239
11240 class GenericRule extends Rule
11241 {
11242 protected $literals;
11243
11244
11245
11246
11247
11248
11249
11250 public function __construct(array $literals, $reason, $reasonData, $job = null)
11251 {
11252 parent::__construct($reason, $reasonData, $job);
11253
11254
11255  sort($literals);
11256
11257 $this->literals = $literals;
11258 }
11259
11260 public function getLiterals()
11261 {
11262 return $this->literals;
11263 }
11264
11265 public function getHash()
11266 {
11267 $data = unpack('ihash', md5(implode(',', $this->literals), true));
11268
11269 return $data['hash'];
11270 }
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280 public function equals(Rule $rule)
11281 {
11282 return $this->literals === $rule->getLiterals();
11283 }
11284
11285 public function isAssertion()
11286 {
11287 return 1 === count($this->literals);
11288 }
11289
11290
11291
11292
11293
11294
11295 public function __toString()
11296 {
11297 $result = $this->isDisabled() ? 'disabled(' : '(';
11298
11299 foreach ($this->literals as $i => $literal) {
11300 if ($i != 0) {
11301 $result .= '|';
11302 }
11303 $result .= $literal;
11304 }
11305
11306 $result .= ')';
11307
11308 return $result;
11309 }
11310 }
11311 <?php
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323 namespace Composer\DependencyResolver\Operation;
11324
11325 use Composer\Package\PackageInterface;
11326
11327
11328
11329
11330
11331
11332 class InstallOperation extends SolverOperation
11333 {
11334 protected $package;
11335
11336
11337
11338
11339
11340
11341
11342 public function __construct(PackageInterface $package, $reason = null)
11343 {
11344 parent::__construct($reason);
11345
11346 $this->package = $package;
11347 }
11348
11349
11350
11351
11352
11353
11354 public function getPackage()
11355 {
11356 return $this->package;
11357 }
11358
11359
11360
11361
11362
11363
11364 public function getJobType()
11365 {
11366 return 'install';
11367 }
11368
11369
11370
11371
11372 public function __toString()
11373 {
11374 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
11375 }
11376 }
11377 <?php
11378
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389 namespace Composer\DependencyResolver\Operation;
11390
11391 use Composer\Package\AliasPackage;
11392 use Composer\Package\PackageInterface;
11393
11394
11395
11396
11397
11398
11399 class MarkAliasInstalledOperation extends SolverOperation
11400 {
11401 protected $package;
11402
11403
11404
11405
11406
11407
11408
11409 public function __construct(AliasPackage $package, $reason = null)
11410 {
11411 parent::__construct($reason);
11412
11413 $this->package = $package;
11414 }
11415
11416
11417
11418
11419
11420
11421 public function getPackage()
11422 {
11423 return $this->package;
11424 }
11425
11426
11427
11428
11429
11430
11431 public function getJobType()
11432 {
11433 return 'markAliasInstalled';
11434 }
11435
11436
11437
11438
11439 public function __toString()
11440 {
11441 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
11442 }
11443 }
11444 <?php
11445
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456 namespace Composer\DependencyResolver\Operation;
11457
11458 use Composer\Package\AliasPackage;
11459 use Composer\Package\PackageInterface;
11460
11461
11462
11463
11464
11465
11466 class MarkAliasUninstalledOperation extends SolverOperation
11467 {
11468 protected $package;
11469
11470
11471
11472
11473
11474
11475
11476 public function __construct(AliasPackage $package, $reason = null)
11477 {
11478 parent::__construct($reason);
11479
11480 $this->package = $package;
11481 }
11482
11483
11484
11485
11486
11487
11488 public function getPackage()
11489 {
11490 return $this->package;
11491 }
11492
11493
11494
11495
11496
11497
11498 public function getJobType()
11499 {
11500 return 'markAliasUninstalled';
11501 }
11502
11503
11504
11505
11506 public function __toString()
11507 {
11508 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
11509 }
11510 }
11511 <?php
11512
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523 namespace Composer\DependencyResolver\Operation;
11524
11525
11526
11527
11528
11529
11530 interface OperationInterface
11531 {
11532
11533
11534
11535
11536
11537 public function getJobType();
11538
11539
11540
11541
11542
11543
11544 public function getReason();
11545
11546
11547
11548
11549
11550
11551 public function __toString();
11552 }
11553 <?php
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565 namespace Composer\DependencyResolver\Operation;
11566
11567 use Composer\Package\PackageInterface;
11568
11569
11570
11571
11572
11573
11574 abstract class SolverOperation implements OperationInterface
11575 {
11576 protected $reason;
11577
11578
11579
11580
11581
11582
11583 public function __construct($reason = null)
11584 {
11585 $this->reason = $reason;
11586 }
11587
11588
11589
11590
11591
11592
11593 public function getReason()
11594 {
11595 return $this->reason;
11596 }
11597
11598 protected function formatVersion(PackageInterface $package)
11599 {
11600 return $package->getFullPrettyVersion();
11601 }
11602 }
11603 <?php
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615 namespace Composer\DependencyResolver\Operation;
11616
11617 use Composer\Package\PackageInterface;
11618
11619
11620
11621
11622
11623
11624 class UninstallOperation extends SolverOperation
11625 {
11626 protected $package;
11627
11628
11629
11630
11631
11632
11633
11634 public function __construct(PackageInterface $package, $reason = null)
11635 {
11636 parent::__construct($reason);
11637
11638 $this->package = $package;
11639 }
11640
11641
11642
11643
11644
11645
11646 public function getPackage()
11647 {
11648 return $this->package;
11649 }
11650
11651
11652
11653
11654
11655
11656 public function getJobType()
11657 {
11658 return 'uninstall';
11659 }
11660
11661
11662
11663
11664 public function __toString()
11665 {
11666 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
11667 }
11668 }
11669 <?php
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681 namespace Composer\DependencyResolver\Operation;
11682
11683 use Composer\Package\PackageInterface;
11684
11685
11686
11687
11688
11689
11690 class UpdateOperation extends SolverOperation
11691 {
11692 protected $initialPackage;
11693 protected $targetPackage;
11694
11695
11696
11697
11698
11699
11700
11701
11702 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
11703 {
11704 parent::__construct($reason);
11705
11706 $this->initialPackage = $initial;
11707 $this->targetPackage = $target;
11708 }
11709
11710
11711
11712
11713
11714
11715 public function getInitialPackage()
11716 {
11717 return $this->initialPackage;
11718 }
11719
11720
11721
11722
11723
11724
11725 public function getTargetPackage()
11726 {
11727 return $this->targetPackage;
11728 }
11729
11730
11731
11732
11733
11734
11735 public function getJobType()
11736 {
11737 return 'update';
11738 }
11739
11740
11741
11742
11743 public function __toString()
11744 {
11745 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
11746 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
11747 }
11748 }
11749 <?php
11750
11751
11752
11753
11754
11755
11756
11757
11758
11759
11760
11761 namespace Composer\DependencyResolver;
11762
11763 use Composer\Package\PackageInterface;
11764
11765
11766
11767
11768 interface PolicyInterface
11769 {
11770 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
11771
11772 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
11773
11774 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
11775 }
11776 <?php
11777
11778
11779
11780
11781
11782
11783
11784
11785
11786
11787
11788 namespace Composer\DependencyResolver;
11789
11790 use Composer\Package\BasePackage;
11791 use Composer\Package\AliasPackage;
11792 use Composer\Package\Version\VersionParser;
11793 use Composer\Semver\Constraint\ConstraintInterface;
11794 use Composer\Semver\Constraint\Constraint;
11795 use Composer\Semver\Constraint\EmptyConstraint;
11796 use Composer\Repository\RepositoryInterface;
11797 use Composer\Repository\CompositeRepository;
11798 use Composer\Repository\ComposerRepository;
11799 use Composer\Repository\InstalledRepositoryInterface;
11800 use Composer\Repository\PlatformRepository;
11801 use Composer\Package\PackageInterface;
11802
11803
11804
11805
11806
11807
11808
11809 class Pool implements \Countable
11810 {
11811 const MATCH_NAME = -1;
11812 const MATCH_NONE = 0;
11813 const MATCH = 1;
11814 const MATCH_PROVIDE = 2;
11815 const MATCH_REPLACE = 3;
11816 const MATCH_FILTERED = 4;
11817
11818 protected $repositories = array();
11819 protected $providerRepos = array();
11820 protected $packages = array();
11821 protected $packageByName = array();
11822 protected $packageByExactName = array();
11823 protected $acceptableStabilities;
11824 protected $stabilityFlags;
11825 protected $versionParser;
11826 protected $providerCache = array();
11827 protected $filterRequires;
11828 protected $whitelist = null;
11829 protected $id = 1;
11830
11831 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
11832 {
11833 $this->versionParser = new VersionParser;
11834 $this->acceptableStabilities = array();
11835 foreach (BasePackage::$stabilities as $stability => $value) {
11836 if ($value <= BasePackage::$stabilities[$minimumStability]) {
11837 $this->acceptableStabilities[$stability] = $value;
11838 }
11839 }
11840 $this->stabilityFlags = $stabilityFlags;
11841 $this->filterRequires = $filterRequires;
11842 foreach ($filterRequires as $name => $constraint) {
11843 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
11844 unset($this->filterRequires[$name]);
11845 }
11846 }
11847 }
11848
11849 public function setWhitelist($whitelist)
11850 {
11851 $this->whitelist = $whitelist;
11852 $this->providerCache = array();
11853 }
11854
11855
11856
11857
11858
11859
11860
11861 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
11862 {
11863 if ($repo instanceof CompositeRepository) {
11864 $repos = $repo->getRepositories();
11865 } else {
11866 $repos = array($repo);
11867 }
11868
11869 foreach ($repos as $repo) {
11870 $this->repositories[] = $repo;
11871
11872 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
11873
11874 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
11875 $this->providerRepos[] = $repo;
11876 $repo->setRootAliases($rootAliases);
11877 $repo->resetPackageIds();
11878 } else {
11879 foreach ($repo->getPackages() as $package) {
11880 $names = $package->getNames();
11881 $stability = $package->getStability();
11882 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
11883 $package->setId($this->id++);
11884 $this->packages[] = $package;
11885 $this->packageByExactName[$package->getName()][$package->id] = $package;
11886
11887 foreach ($names as $provided) {
11888 $this->packageByName[$provided][] = $package;
11889 }
11890
11891
11892  $name = $package->getName();
11893 if (isset($rootAliases[$name][$package->getVersion()])) {
11894 $alias = $rootAliases[$name][$package->getVersion()];
11895 if ($package instanceof AliasPackage) {
11896 $package = $package->getAliasOf();
11897 }
11898 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
11899 $aliasPackage->setRootPackageAlias(true);
11900 $aliasPackage->setId($this->id++);
11901
11902 $package->getRepository()->addPackage($aliasPackage);
11903 $this->packages[] = $aliasPackage;
11904 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
11905
11906 foreach ($aliasPackage->getNames() as $name) {
11907 $this->packageByName[$name][] = $aliasPackage;
11908 }
11909 }
11910 }
11911 }
11912 }
11913 }
11914 }
11915
11916 public function getPriority(RepositoryInterface $repo)
11917 {
11918 $priority = array_search($repo, $this->repositories, true);
11919
11920 if (false === $priority) {
11921 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
11922 }
11923
11924 return -$priority;
11925 }
11926
11927
11928
11929
11930
11931
11932
11933 public function packageById($id)
11934 {
11935 return $this->packages[$id - 1];
11936 }
11937
11938
11939
11940
11941 public function count()
11942 {
11943 return count($this->packages);
11944 }
11945
11946
11947
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
11958 {
11959 if ($bypassFilters) {
11960 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
11961 }
11962
11963 $key = ((int) $mustMatchName).$constraint;
11964 if (isset($this->providerCache[$name][$key])) {
11965 return $this->providerCache[$name][$key];
11966 }
11967
11968 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
11969 }
11970
11971
11972
11973
11974 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
11975 {
11976 $candidates = array();
11977
11978 foreach ($this->providerRepos as $repo) {
11979 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
11980 $candidates[] = $candidate;
11981 if ($candidate->id < 1) {
11982 $candidate->setId($this->id++);
11983 $this->packages[$this->id - 2] = $candidate;
11984 }
11985 }
11986 }
11987
11988 if ($mustMatchName) {
11989 $candidates = array_filter($candidates, function ($candidate) use ($name) {
11990 return $candidate->getName() == $name;
11991 });
11992 if (isset($this->packageByExactName[$name])) {
11993 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
11994 }
11995 } elseif (isset($this->packageByName[$name])) {
11996 $candidates = array_merge($candidates, $this->packageByName[$name]);
11997 }
11998
11999 $matches = $provideMatches = array();
12000 $nameMatch = false;
12001
12002 foreach ($candidates as $candidate) {
12003 $aliasOfCandidate = null;
12004
12005
12006  
12007  if ($candidate instanceof AliasPackage) {
12008 $aliasOfCandidate = $candidate->getAliasOf();
12009 }
12010
12011 if ($this->whitelist !== null && !$bypassFilters && (
12012 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
12013 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
12014 )) {
12015 continue;
12016 }
12017 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
12018 case self::MATCH_NONE:
12019 break;
12020
12021 case self::MATCH_NAME:
12022 $nameMatch = true;
12023 break;
12024
12025 case self::MATCH:
12026 $nameMatch = true;
12027 $matches[] = $candidate;
12028 break;
12029
12030 case self::MATCH_PROVIDE:
12031 $provideMatches[] = $candidate;
12032 break;
12033
12034 case self::MATCH_REPLACE:
12035 $matches[] = $candidate;
12036 break;
12037
12038 case self::MATCH_FILTERED:
12039 break;
12040
12041 default:
12042 throw new \UnexpectedValueException('Unexpected match type');
12043 }
12044 }
12045
12046
12047  if ($nameMatch) {
12048 return $matches;
12049 }
12050
12051 return array_merge($matches, $provideMatches);
12052 }
12053
12054 public function literalToPackage($literal)
12055 {
12056 $packageId = abs($literal);
12057
12058 return $this->packageById($packageId);
12059 }
12060
12061 public function literalToPrettyString($literal, $installedMap)
12062 {
12063 $package = $this->literalToPackage($literal);
12064
12065 if (isset($installedMap[$package->id])) {
12066 $prefix = ($literal > 0 ? 'keep' : 'remove');
12067 } else {
12068 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
12069 }
12070
12071 return $prefix.' '.$package->getPrettyString();
12072 }
12073
12074 public function isPackageAcceptable($name, $stability)
12075 {
12076 foreach ((array) $name as $n) {
12077
12078  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
12079 return true;
12080 }
12081
12082
12083  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
12084 return true;
12085 }
12086 }
12087
12088 return false;
12089 }
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100 public function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
12101 {
12102 $candidateName = $candidate->getName();
12103 $candidateVersion = $candidate->getVersion();
12104 $isDev = $candidate->getStability() === 'dev';
12105 $isAlias = $candidate instanceof AliasPackage;
12106
12107 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
12108 $requireFilter = $this->filterRequires[$name];
12109 } else {
12110 $requireFilter = new EmptyConstraint;
12111 }
12112
12113 if ($candidateName === $name) {
12114 $pkgConstraint = new Constraint('==', $candidateVersion);
12115
12116 if ($constraint === null || $constraint->matches($pkgConstraint)) {
12117 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
12118 }
12119
12120 return self::MATCH_NAME;
12121 }
12122
12123 $provides = $candidate->getProvides();
12124 $replaces = $candidate->getReplaces();
12125
12126
12127  if (isset($replaces[0]) || isset($provides[0])) {
12128 foreach ($provides as $link) {
12129 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
12130 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
12131 }
12132 }
12133
12134 foreach ($replaces as $link) {
12135 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
12136 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
12137 }
12138 }
12139
12140 return self::MATCH_NONE;
12141 }
12142
12143 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
12144 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
12145 }
12146
12147 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
12148 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
12149 }
12150
12151 return self::MATCH_NONE;
12152 }
12153 }
12154 <?php
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166 namespace Composer\DependencyResolver;
12167
12168 use Composer\Package\CompletePackageInterface;
12169
12170
12171
12172
12173
12174
12175 class Problem
12176 {
12177
12178
12179
12180
12181 protected $reasonSeen;
12182
12183
12184
12185
12186
12187 protected $reasons = array();
12188
12189 protected $section = 0;
12190
12191 protected $pool;
12192
12193 public function __construct(Pool $pool)
12194 {
12195 $this->pool = $pool;
12196 }
12197
12198
12199
12200
12201
12202
12203 public function addRule(Rule $rule)
12204 {
12205 $this->addReason(spl_object_hash($rule), array(
12206 'rule' => $rule,
12207 'job' => $rule->getJob(),
12208 ));
12209 }
12210
12211
12212
12213
12214
12215
12216 public function getReasons()
12217 {
12218 return $this->reasons;
12219 }
12220
12221
12222
12223
12224
12225
12226
12227 public function getPrettyString(array $installedMap = array())
12228 {
12229 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
12230
12231 if (count($reasons) === 1) {
12232 reset($reasons);
12233 $reason = current($reasons);
12234
12235 $job = $reason['job'];
12236
12237 $packageName = $job['packageName'];
12238 $constraint = $job['constraint'];
12239
12240 if (isset($constraint)) {
12241 $packages = $this->pool->whatProvides($packageName, $constraint);
12242 } else {
12243 $packages = array();
12244 }
12245
12246 if ($job && $job['cmd'] === 'install' && empty($packages)) {
12247
12248
12249  if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
12250 $version = phpversion();
12251 $available = $this->pool->whatProvides($packageName);
12252
12253 if (count($available)) {
12254 $firstAvailable = reset($available);
12255 $version = $firstAvailable->getPrettyVersion();
12256 $extra = $firstAvailable->getExtra();
12257 if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
12258 $version .= '; ' . $firstAvailable->getDescription();
12259 }
12260 }
12261
12262 $msg = "\n    - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
12263
12264 if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
12265 return $msg . 'your HHVM version does not satisfy that requirement.';
12266 }
12267
12268 if ($packageName === 'hhvm') {
12269 return $msg . 'you are running this with PHP and not HHVM.';
12270 }
12271
12272 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
12273 }
12274
12275
12276  if (0 === stripos($packageName, 'ext-')) {
12277 if (false !== strpos($packageName, ' ')) {
12278 return "\n    - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
12279 }
12280
12281 $ext = substr($packageName, 4);
12282 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
12283
12284 return "\n    - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
12285 }
12286
12287
12288  if (0 === stripos($packageName, 'lib-')) {
12289 if (strtolower($packageName) === 'lib-icu') {
12290 $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.';
12291
12292 return "\n    - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
12293 }
12294
12295 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.';
12296 }
12297
12298 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
12299 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
12300
12301 return "\n    - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
12302 }
12303
12304 if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
12305 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
12306 }
12307
12308 if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
12309 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
12310 }
12311
12312 return "\n    - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
12313 }
12314 }
12315
12316 $messages = array();
12317
12318 foreach ($reasons as $reason) {
12319 $rule = $reason['rule'];
12320 $job = $reason['job'];
12321
12322 if ($job) {
12323 $messages[] = $this->jobToText($job);
12324 } elseif ($rule) {
12325 if ($rule instanceof Rule) {
12326 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
12327 }
12328 }
12329 }
12330
12331 return "\n    - ".implode("\n    - ", $messages);
12332 }
12333
12334
12335
12336
12337
12338
12339
12340 protected function addReason($id, $reason)
12341 {
12342 if (!isset($this->reasonSeen[$id])) {
12343 $this->reasonSeen[$id] = true;
12344 $this->reasons[$this->section][] = $reason;
12345 }
12346 }
12347
12348 public function nextSection()
12349 {
12350 $this->section++;
12351 }
12352
12353
12354
12355
12356
12357
12358
12359 protected function jobToText($job)
12360 {
12361 $packageName = $job['packageName'];
12362 $constraint = $job['constraint'];
12363 switch ($job['cmd']) {
12364 case 'install':
12365 $packages = $this->pool->whatProvides($packageName, $constraint);
12366 if (!$packages) {
12367 return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
12368 }
12369
12370 return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
12371 case 'update':
12372 return 'Update request for '.$packageName.$this->constraintToText($constraint).'.';
12373 case 'remove':
12374 return 'Removal request for '.$packageName.$this->constraintToText($constraint).'';
12375 }
12376
12377 if (isset($constraint)) {
12378 $packages = $this->pool->whatProvides($packageName, $constraint);
12379 } else {
12380 $packages = array();
12381 }
12382
12383 return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
12384 }
12385
12386 protected function getPackageList($packages)
12387 {
12388 $prepared = array();
12389 foreach ($packages as $package) {
12390 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12391 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12392 }
12393 foreach ($prepared as $name => $package) {
12394 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12395 }
12396
12397 return implode(', ', $prepared);
12398 }
12399
12400
12401
12402
12403
12404
12405
12406 protected function constraintToText($constraint)
12407 {
12408 return $constraint ? ' '.$constraint->getPrettyString() : '';
12409 }
12410 }
12411 <?php
12412
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
12423 namespace Composer\DependencyResolver;
12424
12425 use Composer\Semver\Constraint\ConstraintInterface;
12426
12427
12428
12429
12430 class Request
12431 {
12432 protected $jobs;
12433
12434 public function __construct()
12435 {
12436 $this->jobs = array();
12437 }
12438
12439 public function install($packageName, ConstraintInterface $constraint = null)
12440 {
12441 $this->addJob($packageName, 'install', $constraint);
12442 }
12443
12444 public function update($packageName, ConstraintInterface $constraint = null)
12445 {
12446 $this->addJob($packageName, 'update', $constraint);
12447 }
12448
12449 public function remove($packageName, ConstraintInterface $constraint = null)
12450 {
12451 $this->addJob($packageName, 'remove', $constraint);
12452 }
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462 public function fix($packageName, ConstraintInterface $constraint = null)
12463 {
12464 $this->addJob($packageName, 'install', $constraint, true);
12465 }
12466
12467 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
12468 {
12469 $packageName = strtolower($packageName);
12470
12471 $this->jobs[] = array(
12472 'cmd' => $cmd,
12473 'packageName' => $packageName,
12474 'constraint' => $constraint,
12475 'fixed' => $fixed,
12476 );
12477 }
12478
12479 public function updateAll()
12480 {
12481 $this->jobs[] = array('cmd' => 'update-all');
12482 }
12483
12484 public function getJobs()
12485 {
12486 return $this->jobs;
12487 }
12488 }
12489 <?php
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501 namespace Composer\DependencyResolver;
12502
12503 use Composer\Package\CompletePackage;
12504 use Composer\Package\Link;
12505 use Composer\Package\PackageInterface;
12506
12507
12508
12509
12510
12511 abstract class Rule
12512 {
12513
12514  const RULE_INTERNAL_ALLOW_UPDATE = 1;
12515 const RULE_JOB_INSTALL = 2;
12516 const RULE_JOB_REMOVE = 3;
12517 const RULE_PACKAGE_CONFLICT = 6;
12518 const RULE_PACKAGE_REQUIRES = 7;
12519 const RULE_PACKAGE_OBSOLETES = 8;
12520 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
12521 const RULE_PACKAGE_SAME_NAME = 10;
12522 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
12523 const RULE_LEARNED = 12;
12524 const RULE_PACKAGE_ALIAS = 13;
12525
12526
12527  const BITFIELD_TYPE = 0;
12528 const BITFIELD_REASON = 8;
12529 const BITFIELD_DISABLED = 16;
12530
12531 protected $bitfield;
12532 protected $job;
12533 protected $reasonData;
12534
12535
12536
12537
12538
12539
12540 public function __construct($reason, $reasonData, $job = null)
12541 {
12542 $this->reasonData = $reasonData;
12543
12544 if ($job) {
12545 $this->job = $job;
12546 }
12547
12548 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
12549 ($reason << self::BITFIELD_REASON) |
12550 (255 << self::BITFIELD_TYPE);
12551 }
12552
12553 abstract public function getLiterals();
12554
12555 abstract public function getHash();
12556
12557 public function getJob()
12558 {
12559 return $this->job;
12560 }
12561
12562 abstract public function equals(Rule $rule);
12563
12564 public function getReason()
12565 {
12566 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
12567 }
12568
12569 public function getReasonData()
12570 {
12571 return $this->reasonData;
12572 }
12573
12574 public function getRequiredPackage()
12575 {
12576 if ($this->getReason() === self::RULE_JOB_INSTALL) {
12577 return $this->reasonData;
12578 }
12579
12580 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
12581 return $this->reasonData->getTarget();
12582 }
12583 }
12584
12585 public function setType($type)
12586 {
12587 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
12588 }
12589
12590 public function getType()
12591 {
12592 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
12593 }
12594
12595 public function disable()
12596 {
12597 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
12598 }
12599
12600 public function enable()
12601 {
12602 $this->bitfield &= ~(255 << self::BITFIELD_DISABLED);
12603 }
12604
12605 public function isDisabled()
12606 {
12607 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
12608 }
12609
12610 public function isEnabled()
12611 {
12612 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
12613 }
12614
12615 abstract public function isAssertion();
12616
12617 public function getPrettyString(Pool $pool, array $installedMap = array())
12618 {
12619 $literals = $this->getLiterals();
12620
12621 $ruleText = '';
12622 foreach ($literals as $i => $literal) {
12623 if ($i != 0) {
12624 $ruleText .= '|';
12625 }
12626 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
12627 }
12628
12629 switch ($this->getReason()) {
12630 case self::RULE_INTERNAL_ALLOW_UPDATE:
12631 return $ruleText;
12632
12633 case self::RULE_JOB_INSTALL:
12634 return "Install command rule ($ruleText)";
12635
12636 case self::RULE_JOB_REMOVE:
12637 return "Remove command rule ($ruleText)";
12638
12639 case self::RULE_PACKAGE_CONFLICT:
12640 $package1 = $pool->literalToPackage($literals[0]);
12641 $package2 = $pool->literalToPackage($literals[1]);
12642
12643 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
12644
12645 case self::RULE_PACKAGE_REQUIRES:
12646 $sourceLiteral = array_shift($literals);
12647 $sourcePackage = $pool->literalToPackage($sourceLiteral);
12648
12649 $requires = array();
12650 foreach ($literals as $literal) {
12651 $requires[] = $pool->literalToPackage($literal);
12652 }
12653
12654 $text = $this->reasonData->getPrettyString($sourcePackage);
12655 if ($requires) {
12656 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
12657 } else {
12658 $targetName = $this->reasonData->getTarget();
12659
12660 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
12661
12662  if (defined('HHVM_VERSION')) {
12663 return $text . ' -> your HHVM version does not satisfy that requirement.';
12664 }
12665
12666 $packages = $pool->whatProvides($targetName);
12667 $package = count($packages) ? current($packages) : phpversion();
12668
12669 if ($targetName === 'hhvm') {
12670 if ($package instanceof CompletePackage) {
12671 return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12672 } else {
12673 return $text . ' -> you are running this with PHP and not HHVM.';
12674 }
12675 }
12676
12677
12678 if (!($package instanceof CompletePackage)) {
12679 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
12680 }
12681
12682 $extra = $package->getExtra();
12683
12684 if (!empty($extra['config.platform'])) {
12685 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12686 } else {
12687 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
12688 }
12689
12690 return $text;
12691 }
12692
12693 if (0 === strpos($targetName, 'ext-')) {
12694
12695  $ext = substr($targetName, 4);
12696 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
12697
12698 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
12699 }
12700
12701 if (0 === strpos($targetName, 'lib-')) {
12702
12703  $lib = substr($targetName, 4);
12704
12705 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.';
12706 }
12707
12708 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
12709 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
12710 }
12711
12712 return $text . ' -> no matching package found.';
12713 }
12714
12715 return $text;
12716
12717 case self::RULE_PACKAGE_OBSOLETES:
12718 return $ruleText;
12719 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
12720 return $ruleText;
12721 case self::RULE_PACKAGE_SAME_NAME:
12722 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
12723 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
12724 return $ruleText;
12725 case self::RULE_LEARNED:
12726 return 'Conclusion: '.$ruleText;
12727 case self::RULE_PACKAGE_ALIAS:
12728 return $ruleText;
12729 default:
12730 return '('.$ruleText.')';
12731 }
12732 }
12733
12734
12735
12736
12737
12738
12739
12740 protected function formatPackagesUnique($pool, array $packages)
12741 {
12742 $prepared = array();
12743 foreach ($packages as $package) {
12744 if (!is_object($package)) {
12745 $package = $pool->literalToPackage($package);
12746 }
12747 $prepared[$package->getName()]['name'] = $package->getPrettyName();
12748 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
12749 }
12750 foreach ($prepared as $name => $package) {
12751 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
12752 }
12753
12754 return implode(', ', $prepared);
12755 }
12756 }
12757 <?php
12758
12759
12760
12761
12762
12763
12764
12765
12766
12767
12768
12769 namespace Composer\DependencyResolver;
12770
12771 use Composer\Package\PackageInterface;
12772 use Composer\Package\Link;
12773
12774
12775
12776
12777 class Rule2Literals extends Rule
12778 {
12779 protected $literal1;
12780 protected $literal2;
12781
12782
12783
12784
12785
12786
12787
12788
12789 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
12790 {
12791 parent::__construct($reason, $reasonData, $job);
12792
12793 if ($literal1 < $literal2) {
12794 $this->literal1 = $literal1;
12795 $this->literal2 = $literal2;
12796 } else {
12797 $this->literal1 = $literal2;
12798 $this->literal2 = $literal1;
12799 }
12800 }
12801
12802 public function getLiterals()
12803 {
12804 return array($this->literal1, $this->literal2);
12805 }
12806
12807 public function getHash()
12808 {
12809 return $this->literal1.','.$this->literal2;
12810 }
12811
12812
12813
12814
12815
12816
12817
12818
12819
12820 public function equals(Rule $rule)
12821 {
12822
12823  if ($rule instanceof self) {
12824 if ($this->literal1 !== $rule->literal1) {
12825 return false;
12826 }
12827
12828 if ($this->literal2 !== $rule->literal2) {
12829 return false;
12830 }
12831
12832 return true;
12833 }
12834
12835 $literals = $rule->getLiterals();
12836 if (2 != count($literals)) {
12837 return false;
12838 }
12839
12840 if ($this->literal1 !== $literals[0]) {
12841 return false;
12842 }
12843
12844 if ($this->literal2 !== $literals[1]) {
12845 return false;
12846 }
12847
12848 return true;
12849 }
12850
12851 public function isAssertion()
12852 {
12853 return false;
12854 }
12855
12856
12857
12858
12859
12860
12861 public function __toString()
12862 {
12863 $result = $this->isDisabled() ? 'disabled(' : '(';
12864
12865 $result .= $this->literal1 . '|' . $this->literal2 . ')';
12866
12867 return $result;
12868 }
12869 }
12870 <?php
12871
12872
12873
12874
12875
12876
12877
12878
12879
12880
12881
12882 namespace Composer\DependencyResolver;
12883
12884
12885
12886
12887 class RuleSet implements \IteratorAggregate, \Countable
12888 {
12889
12890  const TYPE_PACKAGE = 0;
12891 const TYPE_JOB = 1;
12892 const TYPE_LEARNED = 4;
12893
12894
12895
12896
12897
12898
12899 public $ruleById;
12900
12901 protected static $types = array(
12902 255 => 'UNKNOWN',
12903 self::TYPE_PACKAGE => 'PACKAGE',
12904 self::TYPE_JOB => 'JOB',
12905 self::TYPE_LEARNED => 'LEARNED',
12906 );
12907
12908 protected $rules;
12909 protected $nextRuleId;
12910
12911 protected $rulesByHash;
12912
12913 public function __construct()
12914 {
12915 $this->nextRuleId = 0;
12916
12917 foreach ($this->getTypes() as $type) {
12918 $this->rules[$type] = array();
12919 }
12920
12921 $this->rulesByHash = array();
12922 }
12923
12924 public function add(Rule $rule, $type)
12925 {
12926 if (!isset(self::$types[$type])) {
12927 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
12928 }
12929
12930 $hash = $rule->getHash();
12931
12932
12933  if (isset($this->rulesByHash[$hash])) {
12934 $potentialDuplicates = $this->rulesByHash[$hash];
12935 if (is_array($potentialDuplicates)) {
12936 foreach ($potentialDuplicates as $potentialDuplicate) {
12937 if ($rule->equals($potentialDuplicate)) {
12938 return;
12939 }
12940 }
12941 } else {
12942 if ($rule->equals($potentialDuplicates)) {
12943 return;
12944 }
12945 }
12946 }
12947
12948 if (!isset($this->rules[$type])) {
12949 $this->rules[$type] = array();
12950 }
12951
12952 $this->rules[$type][] = $rule;
12953 $this->ruleById[$this->nextRuleId] = $rule;
12954 $rule->setType($type);
12955
12956 $this->nextRuleId++;
12957
12958 if (!isset($this->rulesByHash[$hash])) {
12959 $this->rulesByHash[$hash] = $rule;
12960 } elseif (is_array($this->rulesByHash[$hash])) {
12961 $this->rulesByHash[$hash][] = $rule;
12962 } else {
12963 $originalRule = $this->rulesByHash[$hash];
12964 $this->rulesByHash[$hash] = array($originalRule, $rule);
12965 }
12966 }
12967
12968 public function count()
12969 {
12970 return $this->nextRuleId;
12971 }
12972
12973 public function ruleById($id)
12974 {
12975 return $this->ruleById[$id];
12976 }
12977
12978 public function getRules()
12979 {
12980 return $this->rules;
12981 }
12982
12983 public function getIterator()
12984 {
12985 return new RuleSetIterator($this->getRules());
12986 }
12987
12988 public function getIteratorFor($types)
12989 {
12990 if (!is_array($types)) {
12991 $types = array($types);
12992 }
12993
12994 $allRules = $this->getRules();
12995 $rules = array();
12996
12997 foreach ($types as $type) {
12998 $rules[$type] = $allRules[$type];
12999 }
13000
13001 return new RuleSetIterator($rules);
13002 }
13003
13004 public function getIteratorWithout($types)
13005 {
13006 if (!is_array($types)) {
13007 $types = array($types);
13008 }
13009
13010 $rules = $this->getRules();
13011
13012 foreach ($types as $type) {
13013 unset($rules[$type]);
13014 }
13015
13016 return new RuleSetIterator($rules);
13017 }
13018
13019 public function getTypes()
13020 {
13021 $types = self::$types;
13022 unset($types[255]);
13023
13024 return array_keys($types);
13025 }
13026
13027 public function getPrettyString(Pool $pool = null)
13028 {
13029 $string = "\n";
13030 foreach ($this->rules as $type => $rules) {
13031 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
13032 foreach ($rules as $rule) {
13033 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
13034 }
13035 $string .= "\n\n";
13036 }
13037
13038 return $string;
13039 }
13040
13041 public function __toString()
13042 {
13043 return $this->getPrettyString(null);
13044 }
13045 }
13046 <?php
13047
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058 namespace Composer\DependencyResolver;
13059
13060 use Composer\Package\PackageInterface;
13061 use Composer\Package\AliasPackage;
13062 use Composer\Repository\PlatformRepository;
13063
13064
13065
13066
13067 class RuleSetGenerator
13068 {
13069 protected $policy;
13070 protected $pool;
13071 protected $rules;
13072 protected $jobs;
13073 protected $installedMap;
13074 protected $whitelistedMap;
13075 protected $addedMap;
13076 protected $conflictAddedMap;
13077 protected $addedPackages;
13078 protected $addedPackagesByNames;
13079
13080 public function __construct(PolicyInterface $policy, Pool $pool)
13081 {
13082 $this->policy = $policy;
13083 $this->pool = $pool;
13084 }
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
13101 {
13102 $literals = array(-$package->id);
13103
13104 foreach ($providers as $provider) {
13105
13106  if ($provider === $package) {
13107 return null;
13108 }
13109 $literals[] = $provider->id;
13110 }
13111
13112 return new GenericRule($literals, $reason, $reasonData);
13113 }
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125
13126
13127 protected function createInstallOneOfRule(array $packages, $reason, $job)
13128 {
13129 $literals = array();
13130 foreach ($packages as $package) {
13131 $literals[] = $package->id;
13132 }
13133
13134 return new GenericRule($literals, $reason, $job['packageName'], $job);
13135 }
13136
13137
13138
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148 protected function createRemoveRule(PackageInterface $package, $reason, $job)
13149 {
13150 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
13151 }
13152
13153
13154
13155
13156
13157
13158
13159
13160
13161
13162
13163
13164
13165
13166
13167 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
13168 {
13169
13170  if ($issuer === $provider) {
13171 return null;
13172 }
13173
13174 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
13175 }
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186 private function addRule($type, Rule $newRule = null)
13187 {
13188 if (!$newRule) {
13189 return;
13190 }
13191
13192 $this->rules->add($newRule, $type);
13193 }
13194
13195 protected function whitelistFromPackage(PackageInterface $package)
13196 {
13197 $workQueue = new \SplQueue;
13198 $workQueue->enqueue($package);
13199
13200 while (!$workQueue->isEmpty()) {
13201 $package = $workQueue->dequeue();
13202 if (isset($this->whitelistedMap[$package->id])) {
13203 continue;
13204 }
13205
13206 $this->whitelistedMap[$package->id] = true;
13207
13208 foreach ($package->getRequires() as $link) {
13209 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
13210
13211 foreach ($possibleRequires as $require) {
13212 $workQueue->enqueue($require);
13213 }
13214 }
13215
13216 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
13217
13218 foreach ($obsoleteProviders as $provider) {
13219 if ($provider === $package) {
13220 continue;
13221 }
13222
13223 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
13224 $workQueue->enqueue($provider);
13225 }
13226 }
13227 }
13228 }
13229
13230 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
13231 {
13232 $workQueue = new \SplQueue;
13233 $workQueue->enqueue($package);
13234
13235 while (!$workQueue->isEmpty()) {
13236
13237 $package = $workQueue->dequeue();
13238 if (isset($this->addedMap[$package->id])) {
13239 continue;
13240 }
13241
13242 $this->addedMap[$package->id] = true;
13243
13244 $this->addedPackages[] = $package;
13245 foreach ($package->getNames() as $name) {
13246 $this->addedPackagesByNames[$name][] = $package;
13247 }
13248
13249 foreach ($package->getRequires() as $link) {
13250 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
13251 continue;
13252 }
13253
13254 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13255
13256 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
13257
13258 foreach ($possibleRequires as $require) {
13259 $workQueue->enqueue($require);
13260 }
13261 }
13262
13263 $packageName = $package->getName();
13264 $obsoleteProviders = $this->pool->whatProvides($packageName, null);
13265
13266 foreach ($obsoleteProviders as $provider) {
13267 if ($provider === $package) {
13268 continue;
13269 }
13270
13271 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
13272 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
13273 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
13274 $reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
13275 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
13276 }
13277 }
13278 }
13279 }
13280
13281 protected function addConflictRules($ignorePlatformReqs = false)
13282 {
13283
13284 foreach ($this->addedPackages as $package) {
13285 foreach ($package->getConflicts() as $link) {
13286 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
13287 continue;
13288 }
13289
13290 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
13291 continue;
13292 }
13293
13294
13295 foreach ($this->addedPackagesByNames[$link->getTarget()] as $possibleConflict) {
13296 $conflictMatch = $this->pool->match($possibleConflict, $link->getTarget(), $link->getConstraint(), true);
13297
13298 if ($conflictMatch === Pool::MATCH || $conflictMatch === Pool::MATCH_REPLACE) {
13299 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $possibleConflict, Rule::RULE_PACKAGE_CONFLICT, $link));
13300 }
13301
13302 }
13303 }
13304
13305
13306  $isInstalled = isset($this->installedMap[$package->id]);
13307
13308 foreach ($package->getReplaces() as $link) {
13309 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
13310 continue;
13311 }
13312
13313
13314 foreach ($this->addedPackagesByNames[$link->getTarget()] as $provider) {
13315 if ($provider === $package) {
13316 continue;
13317 }
13318
13319 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
13320 $reason = $isInstalled ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
13321 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
13322 }
13323 }
13324 }
13325 }
13326 }
13327
13328 protected function obsoleteImpossibleForAlias($package, $provider)
13329 {
13330 $packageIsAlias = $package instanceof AliasPackage;
13331 $providerIsAlias = $provider instanceof AliasPackage;
13332
13333 $impossible = (
13334 ($packageIsAlias && $package->getAliasOf() === $provider) ||
13335 ($providerIsAlias && $provider->getAliasOf() === $package) ||
13336 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
13337 );
13338
13339 return $impossible;
13340 }
13341
13342 protected function whitelistFromJobs()
13343 {
13344 foreach ($this->jobs as $job) {
13345 switch ($job['cmd']) {
13346 case 'install':
13347 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
13348 foreach ($packages as $package) {
13349 $this->whitelistFromPackage($package);
13350 }
13351 break;
13352 }
13353 }
13354 }
13355
13356 protected function addRulesForJobs($ignorePlatformReqs)
13357 {
13358 foreach ($this->jobs as $job) {
13359 switch ($job['cmd']) {
13360 case 'install':
13361 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
13362 break;
13363 }
13364
13365 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
13366 if ($packages) {
13367 foreach ($packages as $package) {
13368 if (!isset($this->installedMap[$package->id])) {
13369 $this->addRulesForPackage($package, $ignorePlatformReqs);
13370 }
13371 }
13372
13373 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
13374 $this->addRule(RuleSet::TYPE_JOB, $rule);
13375 }
13376 break;
13377 case 'remove':
13378
13379  
13380  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
13381 foreach ($packages as $package) {
13382 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
13383 $this->addRule(RuleSet::TYPE_JOB, $rule);
13384 }
13385 break;
13386 }
13387 }
13388 }
13389
13390 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
13391 {
13392 $this->jobs = $jobs;
13393 $this->rules = new RuleSet;
13394 $this->installedMap = $installedMap;
13395
13396 $this->whitelistedMap = array();
13397 foreach ($this->installedMap as $package) {
13398 $this->whitelistFromPackage($package);
13399 }
13400 $this->whitelistFromJobs();
13401
13402 $this->pool->setWhitelist($this->whitelistedMap);
13403
13404 $this->addedMap = array();
13405 $this->conflictAddedMap = array();
13406 $this->addedPackages = array();
13407 $this->addedPackagesByNames = array();
13408 foreach ($this->installedMap as $package) {
13409 $this->addRulesForPackage($package, $ignorePlatformReqs);
13410 }
13411
13412 $this->addRulesForJobs($ignorePlatformReqs);
13413
13414 $this->addConflictRules($ignorePlatformReqs);
13415
13416
13417  $this->addedPackages = $this->addedPackagesByNames = null;
13418
13419 return $this->rules;
13420 }
13421 }
13422 <?php
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434 namespace Composer\DependencyResolver;
13435
13436
13437
13438
13439 class RuleSetIterator implements \Iterator
13440 {
13441 protected $rules;
13442 protected $types;
13443
13444 protected $currentOffset;
13445 protected $currentType;
13446 protected $currentTypeOffset;
13447
13448 public function __construct(array $rules)
13449 {
13450 $this->rules = $rules;
13451 $this->types = array_keys($rules);
13452 sort($this->types);
13453
13454 $this->rewind();
13455 }
13456
13457 public function current()
13458 {
13459 return $this->rules[$this->currentType][$this->currentOffset];
13460 }
13461
13462 public function key()
13463 {
13464 return $this->currentType;
13465 }
13466
13467 public function next()
13468 {
13469 $this->currentOffset++;
13470
13471 if (!isset($this->rules[$this->currentType])) {
13472 return;
13473 }
13474
13475 if ($this->currentOffset >= count($this->rules[$this->currentType])) {
13476 $this->currentOffset = 0;
13477
13478 do {
13479 $this->currentTypeOffset++;
13480
13481 if (!isset($this->types[$this->currentTypeOffset])) {
13482 $this->currentType = -1;
13483 break;
13484 }
13485
13486 $this->currentType = $this->types[$this->currentTypeOffset];
13487 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
13488 }
13489 }
13490
13491 public function rewind()
13492 {
13493 $this->currentOffset = 0;
13494
13495 $this->currentTypeOffset = -1;
13496 $this->currentType = -1;
13497
13498 do {
13499 $this->currentTypeOffset++;
13500
13501 if (!isset($this->types[$this->currentTypeOffset])) {
13502 $this->currentType = -1;
13503 break;
13504 }
13505
13506 $this->currentType = $this->types[$this->currentTypeOffset];
13507 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
13508 }
13509
13510 public function valid()
13511 {
13512 return isset($this->rules[$this->currentType])
13513 && isset($this->rules[$this->currentType][$this->currentOffset]);
13514 }
13515 }
13516 <?php
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528 namespace Composer\DependencyResolver;
13529
13530
13531
13532
13533
13534
13535
13536
13537
13538 class RuleWatchChain extends \SplDoublyLinkedList
13539 {
13540 protected $offset = 0;
13541
13542
13543
13544
13545
13546
13547 public function seek($offset)
13548 {
13549 $this->rewind();
13550 for ($i = 0; $i < $offset; $i++, $this->next());
13551 }
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561 public function remove()
13562 {
13563 $offset = $this->key();
13564 $this->offsetUnset($offset);
13565 $this->seek($offset);
13566 }
13567 }
13568 <?php
13569
13570
13571
13572
13573
13574
13575
13576
13577
13578
13579
13580 namespace Composer\DependencyResolver;
13581
13582
13583
13584
13585
13586
13587
13588
13589
13590
13591
13592 class RuleWatchGraph
13593 {
13594 protected $watchChains = array();
13595
13596
13597
13598
13599
13600
13601
13602
13603
13604
13605
13606
13607
13608 public function insert(RuleWatchNode $node)
13609 {
13610 if ($node->getRule()->isAssertion()) {
13611 return;
13612 }
13613
13614 foreach (array($node->watch1, $node->watch2) as $literal) {
13615 if (!isset($this->watchChains[$literal])) {
13616 $this->watchChains[$literal] = new RuleWatchChain;
13617 }
13618
13619 $this->watchChains[$literal]->unshift($node);
13620 }
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 public function propagateLiteral($decidedLiteral, $level, $decisions)
13647 {
13648
13649  
13650  
13651  $literal = -$decidedLiteral;
13652
13653 if (!isset($this->watchChains[$literal])) {
13654 return null;
13655 }
13656
13657 $chain = $this->watchChains[$literal];
13658
13659 $chain->rewind();
13660 while ($chain->valid()) {
13661 $node = $chain->current();
13662 $otherWatch = $node->getOtherWatch($literal);
13663
13664 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
13665 $ruleLiterals = $node->getRule()->getLiterals();
13666
13667 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
13668 return $literal !== $ruleLiteral &&
13669 $otherWatch !== $ruleLiteral &&
13670 !$decisions->conflict($ruleLiteral);
13671 });
13672
13673 if ($alternativeLiterals) {
13674 reset($alternativeLiterals);
13675 $this->moveWatch($literal, current($alternativeLiterals), $node);
13676 continue;
13677 }
13678
13679 if ($decisions->conflict($otherWatch)) {
13680 return $node->getRule();
13681 }
13682
13683 $decisions->decide($otherWatch, $level, $node->getRule());
13684 }
13685
13686 $chain->next();
13687 }
13688
13689 return null;
13690 }
13691
13692
13693
13694
13695
13696
13697
13698
13699
13700
13701 protected function moveWatch($fromLiteral, $toLiteral, $node)
13702 {
13703 if (!isset($this->watchChains[$toLiteral])) {
13704 $this->watchChains[$toLiteral] = new RuleWatchChain;
13705 }
13706
13707 $node->moveWatch($fromLiteral, $toLiteral);
13708 $this->watchChains[$fromLiteral]->remove();
13709 $this->watchChains[$toLiteral]->unshift($node);
13710 }
13711 }
13712 <?php
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724 namespace Composer\DependencyResolver;
13725
13726
13727
13728
13729
13730
13731
13732
13733 class RuleWatchNode
13734 {
13735 public $watch1;
13736 public $watch2;
13737
13738 protected $rule;
13739
13740
13741
13742
13743
13744
13745 public function __construct($rule)
13746 {
13747 $this->rule = $rule;
13748
13749 $literals = $rule->getLiterals();
13750
13751 $literalCount = count($literals);
13752 $this->watch1 = $literalCount > 0 ? $literals[0] : 0;
13753 $this->watch2 = $literalCount > 1 ? $literals[1] : 0;
13754 }
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764 public function watch2OnHighest(Decisions $decisions)
13765 {
13766 $literals = $this->rule->getLiterals();
13767
13768
13769  if (count($literals) < 3) {
13770 return;
13771 }
13772
13773 $watchLevel = 0;
13774
13775 foreach ($literals as $literal) {
13776 $level = $decisions->decisionLevel($literal);
13777
13778 if ($level > $watchLevel) {
13779 $this->watch2 = $literal;
13780 $watchLevel = $level;
13781 }
13782 }
13783 }
13784
13785
13786
13787
13788
13789
13790 public function getRule()
13791 {
13792 return $this->rule;
13793 }
13794
13795
13796
13797
13798
13799
13800
13801 public function getOtherWatch($literal)
13802 {
13803 if ($this->watch1 == $literal) {
13804 return $this->watch2;
13805 }
13806
13807 return $this->watch1;
13808 }
13809
13810
13811
13812
13813
13814
13815
13816 public function moveWatch($from, $to)
13817 {
13818 if ($this->watch1 == $from) {
13819 $this->watch1 = $to;
13820 } else {
13821 $this->watch2 = $to;
13822 }
13823 }
13824 }
13825 <?php
13826
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837 namespace Composer\DependencyResolver;
13838
13839 use Composer\IO\IOInterface;
13840 use Composer\Repository\RepositoryInterface;
13841 use Composer\Repository\PlatformRepository;
13842
13843
13844
13845
13846 class Solver
13847 {
13848 const BRANCH_LITERALS = 0;
13849 const BRANCH_LEVEL = 1;
13850
13851
13852 protected $policy;
13853
13854 protected $pool;
13855
13856 protected $installed;
13857
13858 protected $rules;
13859
13860 protected $ruleSetGenerator;
13861
13862 protected $jobs;
13863
13864
13865 protected $updateMap = array();
13866
13867 protected $watchGraph;
13868
13869 protected $decisions;
13870
13871 protected $installedMap;
13872
13873
13874 protected $propagateIndex;
13875
13876 protected $branches = array();
13877
13878 protected $problems = array();
13879
13880 protected $learnedPool = array();
13881
13882 protected $learnedWhy = array();
13883
13884
13885 public $testFlagLearnedPositiveLiteral = false;
13886
13887
13888 protected $io;
13889
13890
13891
13892
13893
13894
13895
13896 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
13897 {
13898 $this->io = $io;
13899 $this->policy = $policy;
13900 $this->pool = $pool;
13901 $this->installed = $installed;
13902 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
13903 }
13904
13905
13906
13907
13908 public function getRuleSetSize()
13909 {
13910 return count($this->rules);
13911 }
13912
13913
13914
13915 private function makeAssertionRuleDecisions()
13916 {
13917 $decisionStart = count($this->decisions) - 1;
13918
13919 $rulesCount = count($this->rules);
13920 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
13921 $rule = $this->rules->ruleById[$ruleIndex];
13922
13923 if (!$rule->isAssertion() || $rule->isDisabled()) {
13924 continue;
13925 }
13926
13927 $literals = $rule->getLiterals();
13928 $literal = $literals[0];
13929
13930 if (!$this->decisions->decided($literal)) {
13931 $this->decisions->decide($literal, 1, $rule);
13932 continue;
13933 }
13934
13935 if ($this->decisions->satisfy($literal)) {
13936 continue;
13937 }
13938
13939
13940  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
13941 $rule->disable();
13942 continue;
13943 }
13944
13945 $conflict = $this->decisions->decisionRule($literal);
13946
13947 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
13948 $problem = new Problem($this->pool);
13949
13950 $problem->addRule($rule);
13951 $problem->addRule($conflict);
13952 $this->disableProblem($rule);
13953 $this->problems[] = $problem;
13954 continue;
13955 }
13956
13957
13958  $problem = new Problem($this->pool);
13959 $problem->addRule($rule);
13960 $problem->addRule($conflict);
13961
13962
13963  
13964  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
13965 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
13966 continue;
13967 }
13968
13969 $assertRuleLiterals = $assertRule->getLiterals();
13970 $assertRuleLiteral = $assertRuleLiterals[0];
13971
13972 if (abs($literal) !== abs($assertRuleLiteral)) {
13973 continue;
13974 }
13975
13976 $problem->addRule($assertRule);
13977 $this->disableProblem($assertRule);
13978 }
13979 $this->problems[] = $problem;
13980
13981 $this->decisions->resetToOffset($decisionStart);
13982 $ruleIndex = -1;
13983 }
13984 }
13985
13986 protected function setupInstalledMap()
13987 {
13988 $this->installedMap = array();
13989 foreach ($this->installed->getPackages() as $package) {
13990 $this->installedMap[$package->id] = $package;
13991 }
13992 }
13993
13994
13995
13996
13997 protected function checkForRootRequireProblems($ignorePlatformReqs)
13998 {
13999 foreach ($this->jobs as $job) {
14000 switch ($job['cmd']) {
14001 case 'update':
14002 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14003 foreach ($packages as $package) {
14004 if (isset($this->installedMap[$package->id])) {
14005 $this->updateMap[$package->id] = true;
14006 }
14007 }
14008 break;
14009
14010 case 'update-all':
14011 foreach ($this->installedMap as $package) {
14012 $this->updateMap[$package->id] = true;
14013 }
14014 break;
14015
14016 case 'install':
14017 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
14018 break;
14019 }
14020
14021 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
14022 $problem = new Problem($this->pool);
14023 $problem->addRule(new GenericRule(array(), null, null, $job));
14024 $this->problems[] = $problem;
14025 }
14026 break;
14027 }
14028 }
14029 }
14030
14031
14032
14033
14034
14035
14036 public function solve(Request $request, $ignorePlatformReqs = false)
14037 {
14038 $this->jobs = $request->getJobs();
14039
14040 $this->setupInstalledMap();
14041 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
14042 $this->checkForRootRequireProblems($ignorePlatformReqs);
14043 $this->decisions = new Decisions($this->pool);
14044 $this->watchGraph = new RuleWatchGraph;
14045
14046 foreach ($this->rules as $rule) {
14047 $this->watchGraph->insert(new RuleWatchNode($rule));
14048 }
14049
14050
14051 $this->makeAssertionRuleDecisions();
14052
14053 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
14054 $before = microtime(true);
14055 $this->runSat(true);
14056 $this->io->writeError('', true, IOInterface::DEBUG);
14057 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
14058
14059
14060  foreach ($this->installedMap as $packageId => $void) {
14061 if ($this->decisions->undecided($packageId)) {
14062 $this->decisions->decide(-$packageId, 1, null);
14063 }
14064 }
14065
14066 if ($this->problems) {
14067 throw new SolverProblemsException($this->problems, $this->installedMap);
14068 }
14069
14070 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
14071
14072 return $transaction->getOperations();
14073 }
14074
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084 protected function propagate($level)
14085 {
14086 while ($this->decisions->validOffset($this->propagateIndex)) {
14087 $decision = $this->decisions->atOffset($this->propagateIndex);
14088
14089 $conflict = $this->watchGraph->propagateLiteral(
14090 $decision[Decisions::DECISION_LITERAL],
14091 $level,
14092 $this->decisions
14093 );
14094
14095 $this->propagateIndex++;
14096
14097 if ($conflict) {
14098 return $conflict;
14099 }
14100 }
14101
14102 return null;
14103 }
14104
14105
14106
14107
14108
14109
14110 private function revert($level)
14111 {
14112 while (!$this->decisions->isEmpty()) {
14113 $literal = $this->decisions->lastLiteral();
14114
14115 if ($this->decisions->undecided($literal)) {
14116 break;
14117 }
14118
14119 $decisionLevel = $this->decisions->decisionLevel($literal);
14120
14121 if ($decisionLevel <= $level) {
14122 break;
14123 }
14124
14125 $this->decisions->revertLast();
14126 $this->propagateIndex = count($this->decisions);
14127 }
14128
14129 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
14130 array_pop($this->branches);
14131 }
14132 }
14133
14134
14135
14136
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147
14148
14149
14150
14151
14152
14153 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
14154 {
14155 $level++;
14156
14157 $this->decisions->decide($literal, $level, $rule);
14158
14159 while (true) {
14160 $rule = $this->propagate($level);
14161
14162 if (!$rule) {
14163 break;
14164 }
14165
14166 if ($level == 1) {
14167 return $this->analyzeUnsolvable($rule, $disableRules);
14168 }
14169
14170
14171  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
14172
14173 if ($newLevel <= 0 || $newLevel >= $level) {
14174 throw new SolverBugException(
14175 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
14176 );
14177 } elseif (!$newRule) {
14178 throw new SolverBugException(
14179 "No rule was learned from analyzing $rule at level $level."
14180 );
14181 }
14182
14183 $level = $newLevel;
14184
14185 $this->revert($level);
14186
14187 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
14188
14189 $this->learnedWhy[spl_object_hash($newRule)] = $why;
14190
14191 $ruleNode = new RuleWatchNode($newRule);
14192 $ruleNode->watch2OnHighest($this->decisions);
14193 $this->watchGraph->insert($ruleNode);
14194
14195 $this->decisions->decide($learnLiteral, $level, $newRule);
14196 }
14197
14198 return $level;
14199 }
14200
14201
14202
14203
14204
14205
14206
14207
14208 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
14209 {
14210
14211  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
14212
14213 $selectedLiteral = array_shift($literals);
14214
14215
14216  if (count($literals)) {
14217 $this->branches[] = array($literals, $level);
14218 }
14219
14220 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
14221 }
14222
14223
14224
14225
14226
14227
14228 protected function analyze($level, Rule $rule)
14229 {
14230 $analyzedRule = $rule;
14231 $ruleLevel = 1;
14232 $num = 0;
14233 $l1num = 0;
14234 $seen = array();
14235 $learnedLiterals = array(null);
14236
14237 $decisionId = count($this->decisions);
14238
14239 $this->learnedPool[] = array();
14240
14241 while (true) {
14242 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
14243
14244 foreach ($rule->getLiterals() as $literal) {
14245
14246  if ($this->decisions->satisfy($literal)) {
14247 continue;
14248 }
14249
14250 if (isset($seen[abs($literal)])) {
14251 continue;
14252 }
14253 $seen[abs($literal)] = true;
14254
14255 $l = $this->decisions->decisionLevel($literal);
14256
14257 if (1 === $l) {
14258 $l1num++;
14259 } elseif ($level === $l) {
14260 $num++;
14261 } else {
14262
14263  $learnedLiterals[] = $literal;
14264
14265 if ($l > $ruleLevel) {
14266 $ruleLevel = $l;
14267 }
14268 }
14269 }
14270
14271 $l1retry = true;
14272 while ($l1retry) {
14273 $l1retry = false;
14274
14275 if (!$num && !--$l1num) {
14276
14277  break 2;
14278 }
14279
14280 while (true) {
14281 if ($decisionId <= 0) {
14282 throw new SolverBugException(
14283 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
14284 );
14285 }
14286
14287 $decisionId--;
14288
14289 $decision = $this->decisions->atOffset($decisionId);
14290 $literal = $decision[Decisions::DECISION_LITERAL];
14291
14292 if (isset($seen[abs($literal)])) {
14293 break;
14294 }
14295 }
14296
14297 unset($seen[abs($literal)]);
14298
14299 if ($num && 0 === --$num) {
14300 if ($literal < 0) {
14301 $this->testFlagLearnedPositiveLiteral = true;
14302 }
14303 $learnedLiterals[0] = -$literal;
14304
14305 if (!$l1num) {
14306 break 2;
14307 }
14308
14309 foreach ($learnedLiterals as $i => $learnedLiteral) {
14310 if ($i !== 0) {
14311 unset($seen[abs($learnedLiteral)]);
14312 }
14313 }
14314
14315  $l1num++;
14316 $l1retry = true;
14317 }
14318 }
14319
14320 $decision = $this->decisions->atOffset($decisionId);
14321 $rule = $decision[Decisions::DECISION_REASON];
14322 }
14323
14324 $why = count($this->learnedPool) - 1;
14325
14326 if (!$learnedLiterals[0]) {
14327 throw new SolverBugException(
14328 "Did not find a learnable literal in analyzed rule $analyzedRule."
14329 );
14330 }
14331
14332 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
14333
14334 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
14335 }
14336
14337
14338
14339
14340
14341 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
14342 {
14343 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
14344 $why = spl_object_hash($conflictRule);
14345 $learnedWhy = $this->learnedWhy[$why];
14346 $problemRules = $this->learnedPool[$learnedWhy];
14347
14348 foreach ($problemRules as $problemRule) {
14349 $this->analyzeUnsolvableRule($problem, $problemRule);
14350 }
14351
14352 return;
14353 }
14354
14355 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
14356
14357  return;
14358 }
14359
14360 $problem->nextSection();
14361 $problem->addRule($conflictRule);
14362 }
14363
14364
14365
14366
14367
14368
14369 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
14370 {
14371 $problem = new Problem($this->pool);
14372 $problem->addRule($conflictRule);
14373
14374 $this->analyzeUnsolvableRule($problem, $conflictRule);
14375
14376 $this->problems[] = $problem;
14377
14378 $seen = array();
14379 $literals = $conflictRule->getLiterals();
14380
14381 foreach ($literals as $literal) {
14382
14383  if ($this->decisions->satisfy($literal)) {
14384 continue;
14385 }
14386 $seen[abs($literal)] = true;
14387 }
14388
14389 foreach ($this->decisions as $decision) {
14390 $literal = $decision[Decisions::DECISION_LITERAL];
14391
14392
14393  if (!isset($seen[abs($literal)])) {
14394 continue;
14395 }
14396
14397 $why = $decision[Decisions::DECISION_REASON];
14398
14399 $problem->addRule($why);
14400 $this->analyzeUnsolvableRule($problem, $why);
14401
14402 $literals = $why->getLiterals();
14403
14404 foreach ($literals as $literal) {
14405
14406  if ($this->decisions->satisfy($literal)) {
14407 continue;
14408 }
14409 $seen[abs($literal)] = true;
14410 }
14411 }
14412
14413 if ($disableRules) {
14414 foreach ($this->problems[count($this->problems) - 1] as $reason) {
14415 $this->disableProblem($reason['rule']);
14416 }
14417
14418 $this->resetSolver();
14419
14420 return 1;
14421 }
14422
14423 return 0;
14424 }
14425
14426
14427
14428
14429 private function disableProblem(Rule $why)
14430 {
14431 $job = $why->getJob();
14432
14433 if (!$job) {
14434 $why->disable();
14435
14436 return;
14437 }
14438
14439
14440  foreach ($this->rules as $rule) {
14441
14442 if ($job === $rule->getJob()) {
14443 $rule->disable();
14444 }
14445 }
14446 }
14447
14448 private function resetSolver()
14449 {
14450 $this->decisions->reset();
14451
14452 $this->propagateIndex = 0;
14453 $this->branches = array();
14454
14455 $this->enableDisableLearnedRules();
14456 $this->makeAssertionRuleDecisions();
14457 }
14458
14459
14460
14461
14462
14463
14464
14465
14466 private function enableDisableLearnedRules()
14467 {
14468 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
14469 $why = $this->learnedWhy[spl_object_hash($rule)];
14470 $problemRules = $this->learnedPool[$why];
14471
14472 $foundDisabled = false;
14473 foreach ($problemRules as $problemRule) {
14474 if ($problemRule->isDisabled()) {
14475 $foundDisabled = true;
14476 break;
14477 }
14478 }
14479
14480 if ($foundDisabled && $rule->isEnabled()) {
14481 $rule->disable();
14482 } elseif (!$foundDisabled && $rule->isDisabled()) {
14483 $rule->enable();
14484 }
14485 }
14486 }
14487
14488
14489
14490
14491 private function runSat($disableRules = true)
14492 {
14493 $this->propagateIndex = 0;
14494
14495
14496
14497
14498
14499
14500
14501
14502
14503
14504
14505 $decisionQueue = array();
14506 $decisionSupplementQueue = array();
14507
14508
14509
14510 $disableRules = array();
14511
14512 $level = 1;
14513 $systemLevel = $level + 1;
14514 $installedPos = 0;
14515
14516 while (true) {
14517 if (1 === $level) {
14518 $conflictRule = $this->propagate($level);
14519 if (null !== $conflictRule) {
14520 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
14521 continue;
14522 }
14523
14524 return;
14525 }
14526 }
14527
14528
14529  if ($level < $systemLevel) {
14530 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
14531 foreach ($iterator as $rule) {
14532 if ($rule->isEnabled()) {
14533 $decisionQueue = array();
14534 $noneSatisfied = true;
14535
14536 foreach ($rule->getLiterals() as $literal) {
14537 if ($this->decisions->satisfy($literal)) {
14538 $noneSatisfied = false;
14539 break;
14540 }
14541 if ($literal > 0 && $this->decisions->undecided($literal)) {
14542 $decisionQueue[] = $literal;
14543 }
14544 }
14545
14546 if ($noneSatisfied && count($decisionQueue)) {
14547
14548  
14549  if (count($this->installed) != count($this->updateMap)) {
14550 $prunedQueue = array();
14551 foreach ($decisionQueue as $literal) {
14552 if (isset($this->installedMap[abs($literal)])) {
14553 $prunedQueue[] = $literal;
14554 if (isset($this->updateMap[abs($literal)])) {
14555 $prunedQueue = $decisionQueue;
14556 break;
14557 }
14558 }
14559 }
14560 $decisionQueue = $prunedQueue;
14561 }
14562 }
14563
14564 if ($noneSatisfied && count($decisionQueue)) {
14565 $oLevel = $level;
14566 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
14567
14568 if (0 === $level) {
14569 return;
14570 }
14571 if ($level <= $oLevel) {
14572 break;
14573 }
14574 }
14575 }
14576 }
14577
14578 $systemLevel = $level + 1;
14579
14580
14581  $iterator->next();
14582 if ($iterator->valid()) {
14583 continue;
14584 }
14585 }
14586
14587 if ($level < $systemLevel) {
14588 $systemLevel = $level;
14589 }
14590
14591 $rulesCount = count($this->rules);
14592 $pass = 1;
14593
14594 $this->io->writeError('Looking at all rules.', true, IOInterface::DEBUG);
14595 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
14596 if ($i == $rulesCount) {
14597 if (1 === $pass) {
14598 $this->io->writeError("Something's changed, looking at all rules again (pass #$pass)", false, IOInterface::DEBUG);
14599 } else {
14600 $this->io->overwriteError("Something's changed, looking at all rules again (pass #$pass)", false, null, IOInterface::DEBUG);
14601 }
14602
14603 $i = 0;
14604 $pass++;
14605 }
14606
14607 $rule = $this->rules->ruleById[$i];
14608 $literals = $rule->getLiterals();
14609
14610 if ($rule->isDisabled()) {
14611 continue;
14612 }
14613
14614 $decisionQueue = array();
14615
14616
14617  
14618  
14619  
14620  
14621  
14622  foreach ($literals as $literal) {
14623 if ($literal <= 0) {
14624 if (!$this->decisions->decidedInstall($literal)) {
14625 continue 2; 
14626  }
14627 } else {
14628 if ($this->decisions->decidedInstall($literal)) {
14629 continue 2; 
14630  }
14631 if ($this->decisions->undecided($literal)) {
14632 $decisionQueue[] = $literal;
14633 }
14634 }
14635 }
14636
14637
14638  if (count($decisionQueue) < 2) {
14639 continue;
14640 }
14641
14642 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
14643
14644 if (0 === $level) {
14645 return;
14646 }
14647
14648
14649  $rulesCount = count($this->rules);
14650 $n = -1;
14651 }
14652
14653 if ($level < $systemLevel) {
14654 continue;
14655 }
14656
14657
14658  if (count($this->branches)) {
14659 $lastLiteral = null;
14660 $lastLevel = null;
14661 $lastBranchIndex = 0;
14662 $lastBranchOffset = 0;
14663
14664 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
14665 list($literals, $l) = $this->branches[$i];
14666
14667 foreach ($literals as $offset => $literal) {
14668 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
14669 $lastLiteral = $literal;
14670 $lastBranchIndex = $i;
14671 $lastBranchOffset = $offset;
14672 $lastLevel = $l;
14673 }
14674 }
14675 }
14676
14677 if ($lastLiteral) {
14678 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
14679
14680 $level = $lastLevel;
14681 $this->revert($level);
14682
14683 $why = $this->decisions->lastReason();
14684
14685 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
14686
14687 if ($level == 0) {
14688 return;
14689 }
14690
14691 continue;
14692 }
14693 }
14694
14695 break;
14696 }
14697 }
14698 }
14699 <?php
14700
14701
14702
14703
14704
14705
14706
14707
14708
14709
14710
14711 namespace Composer\DependencyResolver;
14712
14713
14714
14715
14716 class SolverBugException extends \RuntimeException
14717 {
14718 public function __construct($message)
14719 {
14720 parent::__construct(
14721 $message."\nThis exception was most likely caused by a bug in Composer.\n".
14722 "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"
14723 );
14724 }
14725 }
14726 <?php
14727
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738 namespace Composer\DependencyResolver;
14739
14740 use Composer\Util\IniHelper;
14741
14742
14743
14744
14745 class SolverProblemsException extends \RuntimeException
14746 {
14747 protected $problems;
14748 protected $installedMap;
14749
14750 public function __construct(array $problems, array $installedMap)
14751 {
14752 $this->problems = $problems;
14753 $this->installedMap = $installedMap;
14754
14755 parent::__construct($this->createMessage(), 2);
14756 }
14757
14758 protected function createMessage()
14759 {
14760 $text = "\n";
14761 $hasExtensionProblems = false;
14762 foreach ($this->problems as $i => $problem) {
14763 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
14764
14765 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
14766 $hasExtensionProblems = true;
14767 }
14768 }
14769
14770 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
14771 $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.";
14772 }
14773
14774 if ($hasExtensionProblems) {
14775 $text .= $this->createExtensionHint();
14776 }
14777
14778 return $text;
14779 }
14780
14781 public function getProblems()
14782 {
14783 return $this->problems;
14784 }
14785
14786 private function createExtensionHint()
14787 {
14788 $paths = IniHelper::getAll();
14789
14790 if (count($paths) === 1 && empty($paths[0])) {
14791 return '';
14792 }
14793
14794 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
14795 $text .= implode("\n    - ", $paths);
14796 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
14797
14798 return $text;
14799 }
14800
14801 private function hasExtensionProblems(array $reasonSets)
14802 {
14803 foreach ($reasonSets as $reasonSet) {
14804 foreach ($reasonSet as $reason) {
14805 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
14806 return true;
14807 }
14808 }
14809 }
14810
14811 return false;
14812 }
14813 }
14814 <?php
14815
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826 namespace Composer\DependencyResolver;
14827
14828 use Composer\Package\AliasPackage;
14829
14830
14831
14832
14833 class Transaction
14834 {
14835 protected $policy;
14836 protected $pool;
14837 protected $installedMap;
14838 protected $decisions;
14839 protected $transaction;
14840
14841 public function __construct($policy, $pool, $installedMap, $decisions)
14842 {
14843 $this->policy = $policy;
14844 $this->pool = $pool;
14845 $this->installedMap = $installedMap;
14846 $this->decisions = $decisions;
14847 $this->transaction = array();
14848 }
14849
14850 public function getOperations()
14851 {
14852 $installMeansUpdateMap = $this->findUpdates();
14853
14854 $updateMap = array();
14855 $installMap = array();
14856 $uninstallMap = array();
14857
14858 foreach ($this->decisions as $i => $decision) {
14859 $literal = $decision[Decisions::DECISION_LITERAL];
14860 $reason = $decision[Decisions::DECISION_REASON];
14861
14862 $package = $this->pool->literalToPackage($literal);
14863
14864
14865  if (($literal > 0) == isset($this->installedMap[$package->id])) {
14866 continue;
14867 }
14868
14869 if ($literal > 0) {
14870 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
14871 $source = $installMeansUpdateMap[abs($literal)];
14872
14873 $updateMap[$package->id] = array(
14874 'package' => $package,
14875 'source' => $source,
14876 'reason' => $reason,
14877 );
14878
14879
14880  unset($installMeansUpdateMap[abs($literal)]);
14881 $ignoreRemove[$source->id] = true;
14882 } else {
14883 $installMap[$package->id] = array(
14884 'package' => $package,
14885 'reason' => $reason,
14886 );
14887 }
14888 }
14889 }
14890
14891 foreach ($this->decisions as $i => $decision) {
14892 $literal = $decision[Decisions::DECISION_LITERAL];
14893 $reason = $decision[Decisions::DECISION_REASON];
14894 $package = $this->pool->literalToPackage($literal);
14895
14896 if ($literal <= 0 &&
14897 isset($this->installedMap[$package->id]) &&
14898 !isset($ignoreRemove[$package->id])) {
14899 $uninstallMap[$package->id] = array(
14900 'package' => $package,
14901 'reason' => $reason,
14902 );
14903 }
14904 }
14905
14906 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
14907
14908 return $this->transaction;
14909 }
14910
14911 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
14912 {
14913 $queue = array_map(
14914 function ($operation) {
14915 return $operation['package'];
14916 },
14917 $this->findRootPackages($installMap, $updateMap)
14918 );
14919
14920 $visited = array();
14921
14922 while (!empty($queue)) {
14923 $package = array_pop($queue);
14924 $packageId = $package->id;
14925
14926 if (!isset($visited[$packageId])) {
14927 $queue[] = $package;
14928
14929 if ($package instanceof AliasPackage) {
14930 $queue[] = $package->getAliasOf();
14931 } else {
14932 foreach ($package->getRequires() as $link) {
14933 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14934
14935 foreach ($possibleRequires as $require) {
14936 $queue[] = $require;
14937 }
14938 }
14939 }
14940
14941 $visited[$package->id] = true;
14942 } else {
14943 if (isset($installMap[$packageId])) {
14944 $this->install(
14945 $installMap[$packageId]['package'],
14946 $installMap[$packageId]['reason']
14947 );
14948 unset($installMap[$packageId]);
14949 }
14950 if (isset($updateMap[$packageId])) {
14951 $this->update(
14952 $updateMap[$packageId]['source'],
14953 $updateMap[$packageId]['package'],
14954 $updateMap[$packageId]['reason']
14955 );
14956 unset($updateMap[$packageId]);
14957 }
14958 }
14959 }
14960
14961 foreach ($uninstallMap as $uninstall) {
14962 $this->uninstall($uninstall['package'], $uninstall['reason']);
14963 }
14964 }
14965
14966 protected function findRootPackages($installMap, $updateMap)
14967 {
14968 $packages = $installMap + $updateMap;
14969 $roots = $packages;
14970
14971 foreach ($packages as $packageId => $operation) {
14972 $package = $operation['package'];
14973
14974 if (!isset($roots[$packageId])) {
14975 continue;
14976 }
14977
14978 foreach ($package->getRequires() as $link) {
14979 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
14980
14981 foreach ($possibleRequires as $require) {
14982 if ($require !== $package) {
14983 unset($roots[$require->id]);
14984 }
14985 }
14986 }
14987 }
14988
14989 return $roots;
14990 }
14991
14992 protected function findUpdates()
14993 {
14994 $installMeansUpdateMap = array();
14995
14996 foreach ($this->decisions as $i => $decision) {
14997 $literal = $decision[Decisions::DECISION_LITERAL];
14998 $package = $this->pool->literalToPackage($literal);
14999
15000 if ($package instanceof AliasPackage) {
15001 continue;
15002 }
15003
15004
15005  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
15006 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
15007
15008 $literals = array($package->id);
15009
15010 foreach ($updates as $update) {
15011 $literals[] = $update->id;
15012 }
15013
15014 foreach ($literals as $updateLiteral) {
15015 if ($updateLiteral !== $literal) {
15016 $installMeansUpdateMap[abs($updateLiteral)] = $package;
15017 }
15018 }
15019 }
15020 }
15021
15022 return $installMeansUpdateMap;
15023 }
15024
15025 protected function install($package, $reason)
15026 {
15027 if ($package instanceof AliasPackage) {
15028 return $this->markAliasInstalled($package, $reason);
15029 }
15030
15031 $this->transaction[] = new Operation\InstallOperation($package, $reason);
15032 }
15033
15034 protected function update($from, $to, $reason)
15035 {
15036 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
15037 }
15038
15039 protected function uninstall($package, $reason)
15040 {
15041 if ($package instanceof AliasPackage) {
15042 return $this->markAliasUninstalled($package, $reason);
15043 }
15044
15045 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
15046 }
15047
15048 protected function markAliasInstalled($package, $reason)
15049 {
15050 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
15051 }
15052
15053 protected function markAliasUninstalled($package, $reason)
15054 {
15055 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
15056 }
15057 }
15058 <?php
15059
15060
15061
15062
15063
15064
15065
15066
15067
15068
15069
15070 namespace Composer\Downloader;
15071
15072 use Composer\Package\PackageInterface;
15073 use Symfony\Component\Finder\Finder;
15074 use Composer\IO\IOInterface;
15075
15076
15077
15078
15079
15080
15081
15082
15083 abstract class ArchiveDownloader extends FileDownloader
15084 {
15085
15086
15087
15088
15089
15090 public function download(PackageInterface $package, $path, $output = true)
15091 {
15092 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
15093 $retries = 3;
15094 while ($retries--) {
15095 $fileName = parent::download($package, $path, $output);
15096
15097 if ($output) {
15098 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
15099 }
15100
15101 try {
15102 $this->filesystem->ensureDirectoryExists($temporaryDir);
15103 try {
15104 $this->extract($fileName, $temporaryDir);
15105 } catch (\Exception $e) {
15106
15107  parent::clearLastCacheWrite($package);
15108 throw $e;
15109 }
15110
15111 $this->filesystem->unlink($fileName);
15112
15113 $contentDir = $this->getFolderContent($temporaryDir);
15114
15115
15116  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
15117 $contentDir = $this->getFolderContent((string) reset($contentDir));
15118 }
15119
15120
15121  foreach ($contentDir as $file) {
15122 $file = (string) $file;
15123 $this->filesystem->rename($file, $path . '/' . basename($file));
15124 }
15125
15126 $this->filesystem->removeDirectory($temporaryDir);
15127 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
15128 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
15129 }
15130 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
15131 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
15132 }
15133 } catch (\Exception $e) {
15134
15135  $this->filesystem->removeDirectory($path);
15136 $this->filesystem->removeDirectory($temporaryDir);
15137
15138
15139  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
15140 $this->io->writeError('');
15141 if ($this->io->isDebug()) {
15142 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
15143 } else {
15144 $this->io->writeError('    Invalid zip file, retrying...');
15145 }
15146 usleep(500000);
15147 continue;
15148 }
15149
15150 throw $e;
15151 }
15152
15153 break;
15154 }
15155 }
15156
15157
15158
15159
15160 protected function getFileName(PackageInterface $package, $path)
15161 {
15162 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
15163 }
15164
15165
15166
15167
15168
15169
15170
15171
15172
15173 abstract protected function extract($file, $path);
15174
15175
15176
15177
15178
15179
15180
15181 private function getFolderContent($dir)
15182 {
15183 $finder = Finder::create()
15184 ->ignoreVCS(false)
15185 ->ignoreDotFiles(false)
15186 ->notName('.DS_Store')
15187 ->depth(0)
15188 ->in($dir);
15189
15190 return iterator_to_array($finder);
15191 }
15192 }
15193 <?php
15194
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205 namespace Composer\Downloader;
15206
15207 use Composer\Package\PackageInterface;
15208
15209
15210
15211
15212
15213
15214 interface ChangeReportInterface
15215 {
15216
15217
15218
15219
15220
15221
15222
15223 public function getLocalChanges(PackageInterface $package, $path);
15224 }
15225 <?php
15226
15227
15228
15229
15230
15231
15232
15233
15234
15235
15236
15237 namespace Composer\Downloader;
15238
15239 use Composer\Package\PackageInterface;
15240 use Composer\IO\IOInterface;
15241 use Composer\Util\Filesystem;
15242
15243
15244
15245
15246
15247
15248 class DownloadManager
15249 {
15250 private $io;
15251 private $preferDist = false;
15252 private $preferSource = false;
15253 private $packagePreferences = array();
15254 private $filesystem;
15255 private $downloaders = array();
15256
15257
15258
15259
15260
15261
15262
15263
15264 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
15265 {
15266 $this->io = $io;
15267 $this->preferSource = $preferSource;
15268 $this->filesystem = $filesystem ?: new Filesystem();
15269 }
15270
15271
15272
15273
15274
15275
15276
15277 public function setPreferSource($preferSource)
15278 {
15279 $this->preferSource = $preferSource;
15280
15281 return $this;
15282 }
15283
15284
15285
15286
15287
15288
15289
15290 public function setPreferDist($preferDist)
15291 {
15292 $this->preferDist = $preferDist;
15293
15294 return $this;
15295 }
15296
15297
15298
15299
15300
15301
15302
15303 public function setPreferences(array $preferences)
15304 {
15305 $this->packagePreferences = $preferences;
15306
15307 return $this;
15308 }
15309
15310
15311
15312
15313
15314
15315
15316
15317 public function setOutputProgress($outputProgress)
15318 {
15319 foreach ($this->downloaders as $downloader) {
15320 $downloader->setOutputProgress($outputProgress);
15321 }
15322
15323 return $this;
15324 }
15325
15326
15327
15328
15329
15330
15331
15332
15333 public function setDownloader($type, DownloaderInterface $downloader)
15334 {
15335 $type = strtolower($type);
15336 $this->downloaders[$type] = $downloader;
15337
15338 return $this;
15339 }
15340
15341
15342
15343
15344
15345
15346
15347
15348 public function getDownloader($type)
15349 {
15350 $type = strtolower($type);
15351 if (!isset($this->downloaders[$type])) {
15352 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
15353 }
15354
15355 return $this->downloaders[$type];
15356 }
15357
15358
15359
15360
15361
15362
15363
15364
15365
15366
15367 public function getDownloaderForInstalledPackage(PackageInterface $package)
15368 {
15369 $installationSource = $package->getInstallationSource();
15370
15371 if ('metapackage' === $package->getType()) {
15372 return;
15373 }
15374
15375 if ('dist' === $installationSource) {
15376 $downloader = $this->getDownloader($package->getDistType());
15377 } elseif ('source' === $installationSource) {
15378 $downloader = $this->getDownloader($package->getSourceType());
15379 } else {
15380 throw new \InvalidArgumentException(
15381 'Package '.$package.' seems not been installed properly'
15382 );
15383 }
15384
15385 if ($installationSource !== $downloader->getInstallationSource()) {
15386 throw new \LogicException(sprintf(
15387 'Downloader "%s" is a %s type downloader and can not be used to download %s for package %s',
15388 get_class($downloader),
15389 $downloader->getInstallationSource(),
15390 $installationSource,
15391 $package
15392 ));
15393 }
15394
15395 return $downloader;
15396 }
15397
15398
15399
15400
15401
15402
15403
15404
15405
15406
15407
15408 public function download(PackageInterface $package, $targetDir, $preferSource = null)
15409 {
15410 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
15411 $sourceType = $package->getSourceType();
15412 $distType = $package->getDistType();
15413
15414 $sources = array();
15415 if ($sourceType) {
15416 $sources[] = 'source';
15417 }
15418 if ($distType) {
15419 $sources[] = 'dist';
15420 }
15421
15422 if (empty($sources)) {
15423 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
15424 }
15425
15426 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
15427 $sources = array_reverse($sources);
15428 }
15429
15430 $this->filesystem->ensureDirectoryExists($targetDir);
15431
15432 foreach ($sources as $i => $source) {
15433 if (isset($e)) {
15434 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
15435 }
15436 $package->setInstallationSource($source);
15437 try {
15438 $downloader = $this->getDownloaderForInstalledPackage($package);
15439 if ($downloader) {
15440 $downloader->download($package, $targetDir);
15441 }
15442 break;
15443 } catch (\RuntimeException $e) {
15444 if ($i === count($sources) - 1) {
15445 throw $e;
15446 }
15447
15448 $this->io->writeError(
15449 '    <warning>Failed to download '.
15450 $package->getPrettyName().
15451 ' from ' . $source . ': '.
15452 $e->getMessage().'</warning>'
15453 );
15454 }
15455 }
15456 }
15457
15458
15459
15460
15461
15462
15463
15464
15465
15466
15467 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
15468 {
15469 $downloader = $this->getDownloaderForInstalledPackage($initial);
15470 if (!$downloader) {
15471 return;
15472 }
15473
15474 $installationSource = $initial->getInstallationSource();
15475
15476 if ('dist' === $installationSource) {
15477 $initialType = $initial->getDistType();
15478 $targetType = $target->getDistType();
15479 } else {
15480 $initialType = $initial->getSourceType();
15481 $targetType = $target->getSourceType();
15482 }
15483
15484
15485  if ($target->isDev() && 'dist' === $installationSource) {
15486 $downloader->remove($initial, $targetDir);
15487 $this->download($target, $targetDir);
15488
15489 return;
15490 }
15491
15492 if ($initialType === $targetType) {
15493 $target->setInstallationSource($installationSource);
15494 try {
15495 $downloader->update($initial, $target, $targetDir);
15496
15497 return;
15498 } catch (\RuntimeException $e) {
15499 if (!$this->io->isInteractive()) {
15500 throw $e;
15501 }
15502 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
15503 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
15504 throw $e;
15505 }
15506 }
15507 }
15508
15509 $downloader->remove($initial, $targetDir);
15510 $this->download($target, $targetDir, 'source' === $installationSource);
15511 }
15512
15513
15514
15515
15516
15517
15518
15519 public function remove(PackageInterface $package, $targetDir)
15520 {
15521 $downloader = $this->getDownloaderForInstalledPackage($package);
15522 if ($downloader) {
15523 $downloader->remove($package, $targetDir);
15524 }
15525 }
15526
15527
15528
15529
15530
15531
15532
15533
15534 protected function resolvePackageInstallPreference(PackageInterface $package)
15535 {
15536 foreach ($this->packagePreferences as $pattern => $preference) {
15537 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
15538 if (preg_match($pattern, $package->getName())) {
15539 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
15540 return 'dist';
15541 }
15542
15543 return 'source';
15544 }
15545 }
15546
15547 return $package->isDev() ? 'source' : 'dist';
15548 }
15549 }
15550 <?php
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561
15562 namespace Composer\Downloader;
15563
15564 use Composer\Package\PackageInterface;
15565
15566
15567
15568
15569
15570
15571
15572 interface DownloaderInterface
15573 {
15574
15575
15576
15577
15578
15579 public function getInstallationSource();
15580
15581
15582
15583
15584
15585
15586
15587 public function download(PackageInterface $package, $path);
15588
15589
15590
15591
15592
15593
15594
15595
15596 public function update(PackageInterface $initial, PackageInterface $target, $path);
15597
15598
15599
15600
15601
15602
15603
15604 public function remove(PackageInterface $package, $path);
15605
15606
15607
15608
15609
15610
15611
15612 public function setOutputProgress($outputProgress);
15613 }
15614 <?php
15615
15616
15617
15618
15619
15620
15621
15622
15623
15624
15625
15626 namespace Composer\Downloader;
15627
15628 use Composer\Package\PackageInterface;
15629
15630
15631
15632
15633
15634
15635 interface DvcsDownloaderInterface
15636 {
15637
15638
15639
15640
15641
15642
15643
15644 public function getUnpushedChanges(PackageInterface $package, $path);
15645 }
15646 <?php
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657
15658 namespace Composer\Downloader;
15659
15660 use Composer\Config;
15661 use Composer\Cache;
15662 use Composer\Factory;
15663 use Composer\IO\IOInterface;
15664 use Composer\IO\NullIO;
15665 use Composer\Package\Comparer\Comparer;
15666 use Composer\Package\PackageInterface;
15667 use Composer\Package\Version\VersionParser;
15668 use Composer\Plugin\PluginEvents;
15669 use Composer\Plugin\PreFileDownloadEvent;
15670 use Composer\EventDispatcher\EventDispatcher;
15671 use Composer\Util\Filesystem;
15672 use Composer\Util\RemoteFilesystem;
15673 use Composer\Util\Url as UrlUtil;
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683 class FileDownloader implements DownloaderInterface, ChangeReportInterface
15684 {
15685 protected $io;
15686 protected $config;
15687 protected $rfs;
15688 protected $filesystem;
15689 protected $cache;
15690 protected $outputProgress = true;
15691 private $lastCacheWrites = array();
15692 private $eventDispatcher;
15693
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
15705 {
15706 $this->io = $io;
15707 $this->config = $config;
15708 $this->eventDispatcher = $eventDispatcher;
15709 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
15710 $this->filesystem = $filesystem ?: new Filesystem();
15711 $this->cache = $cache;
15712
15713 if ($this->cache && $this->cache->gcIsNecessary()) {
15714 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
15715 }
15716 }
15717
15718
15719
15720
15721 public function getInstallationSource()
15722 {
15723 return 'dist';
15724 }
15725
15726
15727
15728
15729 public function download(PackageInterface $package, $path, $output = true)
15730 {
15731 if (!$package->getDistUrl()) {
15732 throw new \InvalidArgumentException('The given package is missing url information');
15733 }
15734
15735 if ($output) {
15736 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
15737 }
15738
15739 $urls = $package->getDistUrls();
15740 while ($url = array_shift($urls)) {
15741 try {
15742 $fileName = $this->doDownload($package, $path, $url);
15743 break;
15744 } catch (\Exception $e) {
15745 if ($this->io->isDebug()) {
15746 $this->io->writeError('');
15747 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
15748 } elseif (count($urls)) {
15749 $this->io->writeError('');
15750 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
15751 }
15752
15753 if (!count($urls)) {
15754 throw $e;
15755 }
15756 }
15757 }
15758
15759 if ($output) {
15760 $this->io->writeError('');
15761 }
15762
15763 return $fileName;
15764 }
15765
15766 protected function doDownload(PackageInterface $package, $path, $url)
15767 {
15768 $this->filesystem->emptyDirectory($path);
15769
15770 $fileName = $this->getFileName($package, $path);
15771
15772 $processedUrl = $this->processUrl($package, $url);
15773 $origin = RemoteFilesystem::getOrigin($processedUrl);
15774
15775 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
15776 if ($this->eventDispatcher) {
15777 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
15778 }
15779 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
15780
15781 try {
15782 $checksum = $package->getDistSha1Checksum();
15783 $cacheKey = $this->getCacheKey($package, $processedUrl);
15784
15785
15786  if ($this->cache && (!$checksum || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) {
15787 $this->io->writeError('Loading from cache', false);
15788 } else {
15789
15790  if (!$this->outputProgress) {
15791 $this->io->writeError('Downloading', false);
15792 }
15793
15794
15795  $retries = 3;
15796 while ($retries--) {
15797 try {
15798 $rfs->copy($origin, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
15799 break;
15800 } catch (TransportException $e) {
15801
15802  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
15803 throw $e;
15804 }
15805 $this->io->writeError('');
15806 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
15807 usleep(500000);
15808 }
15809 }
15810
15811 if (!$this->outputProgress) {
15812 $this->io->writeError(' (<comment>100%</comment>)', false);
15813 }
15814
15815 if ($this->cache) {
15816 $this->lastCacheWrites[$package->getName()] = $cacheKey;
15817 $this->cache->copyFrom($cacheKey, $fileName);
15818 }
15819 }
15820
15821 if (!file_exists($fileName)) {
15822 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
15823 .' directory is writable and you have internet connectivity');
15824 }
15825
15826 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
15827 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
15828 }
15829 } catch (\Exception $e) {
15830
15831  $this->filesystem->removeDirectory($path);
15832 $this->clearLastCacheWrite($package);
15833 throw $e;
15834 }
15835
15836 return $fileName;
15837 }
15838
15839
15840
15841
15842 public function setOutputProgress($outputProgress)
15843 {
15844 $this->outputProgress = $outputProgress;
15845
15846 return $this;
15847 }
15848
15849 protected function clearLastCacheWrite(PackageInterface $package)
15850 {
15851 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
15852 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
15853 unset($this->lastCacheWrites[$package->getName()]);
15854 }
15855 }
15856
15857
15858
15859
15860 public function update(PackageInterface $initial, PackageInterface $target, $path)
15861 {
15862 $name = $target->getName();
15863 $from = $initial->getFullPrettyVersion();
15864 $to = $target->getFullPrettyVersion();
15865
15866 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
15867 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
15868
15869 $this->remove($initial, $path, false);
15870 $this->download($target, $path, false);
15871
15872 $this->io->writeError('');
15873 }
15874
15875
15876
15877
15878 public function remove(PackageInterface $package, $path, $output = true)
15879 {
15880 if ($output) {
15881 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15882 }
15883 if (!$this->filesystem->removeDirectory($path)) {
15884 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
15885 }
15886 }
15887
15888
15889
15890
15891
15892
15893
15894
15895 protected function getFileName(PackageInterface $package, $path)
15896 {
15897 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15898 }
15899
15900
15901
15902
15903
15904
15905
15906
15907
15908 protected function processUrl(PackageInterface $package, $url)
15909 {
15910 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
15911 throw new \RuntimeException('You must enable the openssl extension to download files via https');
15912 }
15913
15914 if ($package->getDistReference()) {
15915 $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
15916 }
15917
15918 return $url;
15919 }
15920
15921 private function getCacheKey(PackageInterface $package, $processedUrl)
15922 {
15923
15924  
15925  
15926  
15927  $cacheKey = sha1($processedUrl);
15928
15929 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
15930 }
15931
15932
15933
15934
15935
15936 public function getLocalChanges(PackageInterface $package, $targetDir)
15937 {
15938 $prevIO = $this->io;
15939 $prevProgress = $this->outputProgress;
15940
15941 $this->io = new NullIO;
15942 $this->io->loadConfiguration($this->config);
15943 $this->outputProgress = false;
15944 $e = null;
15945
15946 try {
15947 $this->download($package, $targetDir.'_compare', false);
15948
15949 $comparer = new Comparer();
15950 $comparer->setSource($targetDir.'_compare');
15951 $comparer->setUpdate($targetDir);
15952 $comparer->doCompare();
15953 $output = $comparer->getChanged(true, true);
15954 $this->filesystem->removeDirectory($targetDir.'_compare');
15955 } catch (\Exception $e) {
15956 }
15957
15958 $this->io = $prevIO;
15959 $this->outputProgress = $prevProgress;
15960
15961 if ($e) {
15962 throw $e;
15963 }
15964
15965 return trim($output);
15966 }
15967 }
15968 <?php
15969
15970
15971
15972
15973
15974
15975
15976
15977
15978
15979
15980 namespace Composer\Downloader;
15981
15982
15983
15984
15985
15986
15987 class FilesystemException extends \Exception
15988 {
15989 public function __construct($message = '', $code = 0, \Exception $previous = null)
15990 {
15991 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
15992 }
15993 }
15994 <?php
15995
15996
15997
15998
15999
16000
16001
16002
16003
16004
16005
16006 namespace Composer\Downloader;
16007
16008 use Composer\Package\PackageInterface;
16009 use Composer\Util\ProcessExecutor;
16010
16011
16012
16013
16014 class FossilDownloader extends VcsDownloader
16015 {
16016
16017
16018
16019 public function doDownload(PackageInterface $package, $path, $url)
16020 {
16021
16022  $this->config->prohibitUrlByConfig($url, $this->io);
16023
16024 $url = ProcessExecutor::escape($url);
16025 $ref = ProcessExecutor::escape($package->getSourceReference());
16026 $repoFile = $path . '.fossil';
16027 $this->io->writeError("Cloning ".$package->getSourceReference());
16028 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
16029 if (0 !== $this->process->execute($command, $ignoredOutput)) {
16030 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16031 }
16032 $command = sprintf('fossil open %s --nested', ProcessExecutor::escape($repoFile));
16033 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16034 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16035 }
16036 $command = sprintf('fossil update %s', $ref);
16037 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16038 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16039 }
16040 }
16041
16042
16043
16044
16045 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16046 {
16047
16048  $this->config->prohibitUrlByConfig($url, $this->io);
16049
16050 $url = ProcessExecutor::escape($url);
16051 $ref = ProcessExecutor::escape($target->getSourceReference());
16052 $this->io->writeError(" Updating to ".$target->getSourceReference());
16053
16054 if (!$this->hasMetadataRepository($path)) {
16055 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16056 }
16057
16058 $command = sprintf('fossil pull && fossil up %s', $ref);
16059 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16060 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16061 }
16062 }
16063
16064
16065
16066
16067 public function getLocalChanges(PackageInterface $package, $path)
16068 {
16069 if (!$this->hasMetadataRepository($path)) {
16070 return null;
16071 }
16072
16073 $this->process->execute('fossil changes', $output, realpath($path));
16074
16075 return trim($output) ?: null;
16076 }
16077
16078
16079
16080
16081 protected function getCommitLogs($fromReference, $toReference, $path)
16082 {
16083 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', ProcessExecutor::escape($toReference));
16084
16085 if (0 !== $this->process->execute($command, $output, realpath($path))) {
16086 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16087 }
16088
16089 $log = '';
16090 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
16091
16092 foreach ($this->process->splitLines($output) as $line) {
16093 if (preg_match($match, $line)) {
16094 break;
16095 }
16096 $log .= $line;
16097 }
16098
16099 return $log;
16100 }
16101
16102
16103
16104
16105 protected function hasMetadataRepository($path)
16106 {
16107 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
16108 }
16109 }
16110 <?php
16111
16112
16113
16114
16115
16116
16117
16118
16119
16120
16121
16122 namespace Composer\Downloader;
16123
16124 use Composer\Config;
16125 use Composer\IO\IOInterface;
16126 use Composer\Package\PackageInterface;
16127 use Composer\Util\Filesystem;
16128 use Composer\Util\Git as GitUtil;
16129 use Composer\Util\Platform;
16130 use Composer\Util\ProcessExecutor;
16131 use Composer\Cache;
16132
16133
16134
16135
16136 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
16137 {
16138 private $hasStashedChanges = false;
16139 private $hasDiscardedChanges = false;
16140 private $gitUtil;
16141
16142 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
16143 {
16144 parent::__construct($io, $config, $process, $fs);
16145 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
16146 }
16147
16148
16149
16150
16151 public function doDownload(PackageInterface $package, $path, $url)
16152 {
16153 GitUtil::cleanEnv();
16154 $path = $this->normalizePath($path);
16155 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
16156 $ref = $package->getSourceReference();
16157 $flag = Platform::isWindows() ? '/D ' : '';
16158
16159
16160  $gitVersion = $this->gitUtil->getVersion();
16161 $msg = "Cloning ".$this->getShortHash($ref);
16162
16163 $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%';
16164 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
16165 $this->io->writeError('', true, IOInterface::DEBUG);
16166 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
16167 try {
16168 if (!$this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref)) {
16169 $this->io->writeError('<error>Failed to update '.$url.' in cache, package installation for '.$package->getPrettyName().' might fail.</error>');
16170 }
16171 if (is_dir($cachePath)) {
16172 $command =
16173 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
16174 . '&& cd '.$flag.'%path% '
16175 . '&& git remote set-url origin %sanitizedUrl% && git remote add composer %sanitizedUrl%';
16176 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
16177 }
16178 } catch (\RuntimeException $e) {
16179 if (0 === strpos(get_class($e), 'PHPUnit')) {
16180 throw $e;
16181 }
16182 }
16183 }
16184 $this->io->writeError($msg);
16185
16186 $commandCallable = function ($url) use ($path, $command, $cachePath) {
16187 return str_replace(
16188 array('%url%', '%path%', '%cachePath%', '%sanitizedUrl%'),
16189 array(
16190 ProcessExecutor::escape($url),
16191 ProcessExecutor::escape($path),
16192 ProcessExecutor::escape($cachePath),
16193 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url)),
16194 ),
16195 $command
16196 );
16197 };
16198
16199 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
16200 if ($url !== $package->getSourceUrl()) {
16201 $this->updateOriginUrl($path, $package->getSourceUrl());
16202 } else {
16203 $this->setPushUrl($path, $url);
16204 }
16205
16206 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
16207 if ($package->getDistReference() === $package->getSourceReference()) {
16208 $package->setDistReference($newRef);
16209 }
16210 $package->setSourceReference($newRef);
16211 }
16212 }
16213
16214
16215
16216
16217 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16218 {
16219 GitUtil::cleanEnv();
16220 if (!$this->hasMetadataRepository($path)) {
16221 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16222 }
16223
16224 $updateOriginUrl = false;
16225 if (
16226 0 === $this->process->execute('git remote -v', $output, $path)
16227 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
16228 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
16229 ) {
16230 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
16231 $updateOriginUrl = true;
16232 }
16233 }
16234
16235 $ref = $target->getSourceReference();
16236 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
16237 $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';
16238
16239 $commandCallable = function ($url) use ($command, $ref) {
16240 return sprintf(
16241 $command,
16242 ProcessExecutor::escape($url),
16243 ProcessExecutor::escape($ref.'^{commit}'),
16244 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url))
16245 );
16246 };
16247
16248 $this->gitUtil->runCommand($commandCallable, $url, $path);
16249 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
16250 if ($target->getDistReference() === $target->getSourceReference()) {
16251 $target->setDistReference($newRef);
16252 }
16253 $target->setSourceReference($newRef);
16254 }
16255
16256 if ($updateOriginUrl) {
16257 $this->updateOriginUrl($path, $target->getSourceUrl());
16258 }
16259 }
16260
16261
16262
16263
16264 public function getLocalChanges(PackageInterface $package, $path)
16265 {
16266 GitUtil::cleanEnv();
16267 if (!$this->hasMetadataRepository($path)) {
16268 return;
16269 }
16270
16271 $command = 'git status --porcelain --untracked-files=no';
16272 if (0 !== $this->process->execute($command, $output, $path)) {
16273 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16274 }
16275
16276 return trim($output) ?: null;
16277 }
16278
16279 public function getUnpushedChanges(PackageInterface $package, $path)
16280 {
16281 GitUtil::cleanEnv();
16282 $path = $this->normalizePath($path);
16283 if (!$this->hasMetadataRepository($path)) {
16284 return;
16285 }
16286
16287 $command = 'git show-ref --head -d';
16288 if (0 !== $this->process->execute($command, $output, $path)) {
16289 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16290 }
16291
16292 $refs = trim($output);
16293 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
16294
16295  return;
16296 }
16297
16298 $headRef = $match[1];
16299 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
16300
16301  return;
16302 }
16303
16304
16305  $branch = $matches[1][0];
16306 $unpushedChanges = null;
16307
16308
16309  for ($i = 0; $i <= 1; $i++) {
16310
16311  foreach ($matches[1] as $candidate) {
16312 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
16313 $branch = $candidate;
16314 $remoteBranch = $match[1];
16315 break;
16316 }
16317 }
16318
16319
16320  
16321  
16322  if (!isset($remoteBranch)) {
16323 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
16324 } else {
16325 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
16326 if (0 !== $this->process->execute($command, $output, $path)) {
16327 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16328 }
16329
16330 $unpushedChanges = trim($output) ?: null;
16331 }
16332
16333
16334  
16335  if ($unpushedChanges && $i === 0) {
16336 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
16337 }
16338
16339
16340  if (!$unpushedChanges) {
16341 break;
16342 }
16343 }
16344
16345 return $unpushedChanges;
16346 }
16347
16348
16349
16350
16351 protected function cleanChanges(PackageInterface $package, $path, $update)
16352 {
16353 GitUtil::cleanEnv();
16354 $path = $this->normalizePath($path);
16355
16356 $unpushed = $this->getUnpushedChanges($package, $path);
16357 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
16358 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
16359 }
16360
16361 if (!$changes = $this->getLocalChanges($package, $path)) {
16362 return;
16363 }
16364
16365 if (!$this->io->isInteractive()) {
16366 $discardChanges = $this->config->get('discard-changes');
16367 if (true === $discardChanges) {
16368 return $this->discardChanges($path);
16369 }
16370 if ('stash' === $discardChanges) {
16371 if (!$update) {
16372 return parent::cleanChanges($package, $path, $update);
16373 }
16374
16375 return $this->stashChanges($path);
16376 }
16377
16378 return parent::cleanChanges($package, $path, $update);
16379 }
16380
16381 $changes = array_map(function ($elem) {
16382 return '    '.$elem;
16383 }, preg_split('{\s*\r?\n\s*}', $changes));
16384 $this->io->writeError('    <error>The package has modified files:</error>');
16385 $this->io->writeError(array_slice($changes, 0, 10));
16386 if (count($changes) > 10) {
16387 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
16388 }
16389
16390 while (true) {
16391 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
16392 case 'y':
16393 $this->discardChanges($path);
16394 break 2;
16395
16396 case 's':
16397 if (!$update) {
16398 goto help;
16399 }
16400
16401 $this->stashChanges($path);
16402 break 2;
16403
16404 case 'n':
16405 throw new \RuntimeException('Update aborted');
16406
16407 case 'v':
16408 $this->io->writeError($changes);
16409 break;
16410
16411 case 'd':
16412 $this->viewDiff($path);
16413 break;
16414
16415 case '?':
16416 default:
16417 help:
16418 $this->io->writeError(array(
16419 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
16420 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
16421 '    v - view modified files',
16422 '    d - view local modifications (diff)',
16423 ));
16424 if ($update) {
16425 $this->io->writeError('    s - stash changes and try to reapply them after the update');
16426 }
16427 $this->io->writeError('    ? - print help');
16428 break;
16429 }
16430 }
16431 }
16432
16433
16434
16435
16436 protected function reapplyChanges($path)
16437 {
16438 $path = $this->normalizePath($path);
16439 if ($this->hasStashedChanges) {
16440 $this->hasStashedChanges = false;
16441 $this->io->writeError('    <info>Re-applying stashed changes</info>');
16442 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
16443 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
16444 }
16445 }
16446
16447 $this->hasDiscardedChanges = false;
16448 }
16449
16450
16451
16452
16453
16454
16455
16456
16457
16458
16459
16460 protected function updateToCommit($path, $reference, $branch, $date)
16461 {
16462 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
16463
16464
16465  
16466  
16467  
16468  
16469  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
16470 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
16471
16472 $branches = null;
16473 if (0 === $this->process->execute('git branch -r', $output, $path)) {
16474 $branches = $output;
16475 }
16476
16477
16478  $gitRef = $reference;
16479 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
16480 && $branches
16481 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
16482 ) {
16483 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
16484 if (0 === $this->process->execute($command, $output, $path)) {
16485 return;
16486 }
16487 }
16488
16489
16490  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
16491
16492  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
16493 $branch = 'v' . $branch;
16494 }
16495
16496 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
16497 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
16498 if (0 === $this->process->execute($command, $output, $path)
16499 || 0 === $this->process->execute($fallbackCommand, $output, $path)
16500 ) {
16501 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
16502 if (0 === $this->process->execute($command, $output, $path)) {
16503 return;
16504 }
16505 }
16506 }
16507
16508 $command = sprintf($template, ProcessExecutor::escape($gitRef));
16509 if (0 === $this->process->execute($command, $output, $path)) {
16510 return;
16511 }
16512
16513
16514  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
16515 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
16516 }
16517
16518 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
16519 }
16520
16521 protected function updateOriginUrl($path, $url)
16522 {
16523 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
16524 $this->setPushUrl($path, $url);
16525 }
16526
16527 protected function setPushUrl($path, $url)
16528 {
16529
16530  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
16531 $protocols = $this->config->get('github-protocols');
16532 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
16533 if (!in_array('ssh', $protocols, true)) {
16534 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
16535 }
16536 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
16537 $this->process->execute($cmd, $ignoredOutput, $path);
16538 }
16539 }
16540
16541
16542
16543
16544 protected function getCommitLogs($fromReference, $toReference, $path)
16545 {
16546 $path = $this->normalizePath($path);
16547 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
16548
16549 if (0 !== $this->process->execute($command, $output, $path)) {
16550 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16551 }
16552
16553 return $output;
16554 }
16555
16556
16557
16558
16559
16560 protected function discardChanges($path)
16561 {
16562 $path = $this->normalizePath($path);
16563 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
16564 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16565 }
16566
16567 $this->hasDiscardedChanges = true;
16568 }
16569
16570
16571
16572
16573
16574 protected function stashChanges($path)
16575 {
16576 $path = $this->normalizePath($path);
16577 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
16578 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
16579 }
16580
16581 $this->hasStashedChanges = true;
16582 }
16583
16584
16585
16586
16587
16588 protected function viewDiff($path)
16589 {
16590 $path = $this->normalizePath($path);
16591 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
16592 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
16593 }
16594
16595 $this->io->writeError($output);
16596 }
16597
16598 protected function normalizePath($path)
16599 {
16600 if (Platform::isWindows() && strlen($path) > 0) {
16601 $basePath = $path;
16602 $removed = array();
16603
16604 while (!is_dir($basePath) && $basePath !== '\\') {
16605 array_unshift($removed, basename($basePath));
16606 $basePath = dirname($basePath);
16607 }
16608
16609 if ($basePath === '\\') {
16610 return $path;
16611 }
16612
16613 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
16614 }
16615
16616 return $path;
16617 }
16618
16619
16620
16621
16622 protected function hasMetadataRepository($path)
16623 {
16624 $path = $this->normalizePath($path);
16625
16626 return is_dir($path.'/.git');
16627 }
16628
16629 protected function getShortHash($reference)
16630 {
16631 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
16632 return substr($reference, 0, 10);
16633 }
16634
16635 return $reference;
16636 }
16637 }
16638 <?php
16639
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650 namespace Composer\Downloader;
16651
16652 use Composer\Config;
16653 use Composer\Cache;
16654 use Composer\EventDispatcher\EventDispatcher;
16655 use Composer\Package\PackageInterface;
16656 use Composer\Util\Platform;
16657 use Composer\Util\ProcessExecutor;
16658 use Composer\Util\RemoteFilesystem;
16659 use Composer\IO\IOInterface;
16660
16661
16662
16663
16664
16665
16666 class GzipDownloader extends ArchiveDownloader
16667 {
16668 protected $process;
16669
16670 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16671 {
16672 $this->process = $process ?: new ProcessExecutor($io);
16673 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16674 }
16675
16676 protected function extract($file, $path)
16677 {
16678 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
16679
16680
16681  if (!Platform::isWindows()) {
16682 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
16683
16684 if (0 === $this->process->execute($command, $ignoredOutput)) {
16685 return;
16686 }
16687
16688 if (extension_loaded('zlib')) {
16689
16690  $this->extractUsingExt($file, $targetFilepath);
16691
16692 return;
16693 }
16694
16695 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16696 throw new \RuntimeException($processError);
16697 }
16698
16699
16700  $this->extractUsingExt($file, $targetFilepath);
16701 }
16702
16703
16704
16705
16706 protected function getFileName(PackageInterface $package, $path)
16707 {
16708 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
16709 }
16710
16711 private function extractUsingExt($file, $targetFilepath)
16712 {
16713 $archiveFile = gzopen($file, 'rb');
16714 $targetFile = fopen($targetFilepath, 'wb');
16715 while ($string = gzread($archiveFile, 4096)) {
16716 fwrite($targetFile, $string, Platform::strlen($string));
16717 }
16718 gzclose($archiveFile);
16719 fclose($targetFile);
16720 }
16721 }
16722 <?php
16723
16724
16725
16726
16727
16728
16729
16730
16731
16732
16733
16734 namespace Composer\Downloader;
16735
16736 use Composer\Package\PackageInterface;
16737 use Composer\Util\ProcessExecutor;
16738 use Composer\Util\Hg as HgUtils;
16739
16740
16741
16742
16743 class HgDownloader extends VcsDownloader
16744 {
16745
16746
16747
16748 public function doDownload(PackageInterface $package, $path, $url)
16749 {
16750 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
16751
16752 $cloneCommand = function ($url) use ($path) {
16753 return sprintf('hg clone %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
16754 };
16755
16756 $hgUtils->runCommand($cloneCommand, $url, $path);
16757
16758 $ref = ProcessExecutor::escape($package->getSourceReference());
16759 $command = sprintf('hg up %s', $ref);
16760 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16761 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16762 }
16763 }
16764
16765
16766
16767
16768 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16769 {
16770 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
16771
16772 $ref = $target->getSourceReference();
16773 $this->io->writeError(" Updating to ".$target->getSourceReference());
16774
16775 if (!$this->hasMetadataRepository($path)) {
16776 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16777 }
16778
16779 $command = function ($url) use ($ref) {
16780 return sprintf('hg pull %s && hg up %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
16781 };
16782
16783 $hgUtils->runCommand($command, $url, $path);
16784 }
16785
16786
16787
16788
16789 public function getLocalChanges(PackageInterface $package, $path)
16790 {
16791 if (!is_dir($path.'/.hg')) {
16792 return null;
16793 }
16794
16795 $this->process->execute('hg st', $output, realpath($path));
16796
16797 return trim($output) ?: null;
16798 }
16799
16800
16801
16802
16803 protected function getCommitLogs($fromReference, $toReference, $path)
16804 {
16805 $command = sprintf('hg log -r %s:%s --style compact', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
16806
16807 if (0 !== $this->process->execute($command, $output, realpath($path))) {
16808 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16809 }
16810
16811 return $output;
16812 }
16813
16814
16815
16816
16817 protected function hasMetadataRepository($path)
16818 {
16819 return is_dir($path . '/.hg');
16820 }
16821 }
16822 <?php
16823
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834 namespace Composer\Downloader;
16835
16836 use Composer\Package\Archiver\ArchivableFilesFinder;
16837 use Composer\Package\Dumper\ArrayDumper;
16838 use Composer\Package\PackageInterface;
16839 use Composer\Package\Version\VersionGuesser;
16840 use Composer\Package\Version\VersionParser;
16841 use Composer\Util\Platform;
16842 use Composer\Util\ProcessExecutor;
16843 use Composer\Util\Filesystem as ComposerFilesystem;
16844 use Symfony\Component\Filesystem\Exception\IOException;
16845 use Symfony\Component\Filesystem\Filesystem;
16846
16847
16848
16849
16850
16851
16852
16853 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
16854 {
16855 const STRATEGY_SYMLINK = 10;
16856 const STRATEGY_MIRROR = 20;
16857
16858
16859
16860
16861 public function download(PackageInterface $package, $path, $output = true)
16862 {
16863 $url = $package->getDistUrl();
16864 $realUrl = realpath($url);
16865 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
16866 throw new \RuntimeException(sprintf(
16867 'Source path "%s" is not found for package %s',
16868 $url,
16869 $package->getName()
16870 ));
16871 }
16872
16873 if (realpath($path) === $realUrl) {
16874 if ($output) {
16875 $this->io->writeError(sprintf(
16876 '  - Installing <info>%s</info> (<comment>%s</comment>): Source already present',
16877 $package->getName(),
16878 $package->getFullPrettyVersion()
16879 ));
16880 }
16881
16882 return;
16883 }
16884
16885 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
16886
16887  
16888  
16889  
16890  throw new \RuntimeException(sprintf(
16891 'Package %s cannot install to "%s" inside its source at "%s"',
16892 $package->getName(),
16893 realpath($path),
16894 $realUrl
16895 ));
16896 }
16897
16898
16899  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
16900
16901
16902  $currentStrategy = self::STRATEGY_SYMLINK;
16903 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
16904
16905 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
16906 if ($mirrorPathRepos) {
16907 $currentStrategy = self::STRATEGY_MIRROR;
16908 }
16909
16910 if (true === $transportOptions['symlink']) {
16911 $currentStrategy = self::STRATEGY_SYMLINK;
16912 $allowedStrategies = array(self::STRATEGY_SYMLINK);
16913 } elseif (false === $transportOptions['symlink']) {
16914 $currentStrategy = self::STRATEGY_MIRROR;
16915 $allowedStrategies = array(self::STRATEGY_MIRROR);
16916 }
16917
16918
16919  if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
16920 $currentStrategy = self::STRATEGY_MIRROR;
16921 $allowedStrategies = array(self::STRATEGY_MIRROR);
16922 }
16923
16924 $fileSystem = new Filesystem();
16925 $this->filesystem->removeDirectory($path);
16926
16927 if ($output) {
16928 $this->io->writeError(sprintf(
16929 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
16930 $package->getName(),
16931 $package->getFullPrettyVersion()
16932 ), false);
16933 }
16934
16935 $isFallback = false;
16936 if (self::STRATEGY_SYMLINK == $currentStrategy) {
16937 try {
16938 if (Platform::isWindows()) {
16939
16940  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
16941 $this->filesystem->junction($realUrl, $path);
16942 } else {
16943 $absolutePath = $path;
16944 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
16945 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
16946 }
16947 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
16948 $path = rtrim($path, "/");
16949 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
16950 $fileSystem->symlink($shortestPath, $path);
16951 }
16952 } catch (IOException $e) {
16953 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
16954 $this->io->writeError('');
16955 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
16956 $currentStrategy = self::STRATEGY_MIRROR;
16957 $isFallback = true;
16958 } else {
16959 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
16960 }
16961 }
16962 }
16963
16964
16965  if (self::STRATEGY_MIRROR == $currentStrategy) {
16966 $fs = new ComposerFilesystem();
16967 $realUrl = $fs->normalizePath($realUrl);
16968
16969 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
16970 $iterator = new ArchivableFilesFinder($realUrl, array());
16971 $fileSystem->mirror($realUrl, $path, $iterator);
16972 }
16973
16974 $this->io->writeError('');
16975 }
16976
16977
16978
16979
16980 public function remove(PackageInterface $package, $path, $output = true)
16981 {
16982 $realUrl = realpath($package->getDistUrl());
16983
16984 if (realpath($path) === $realUrl) {
16985 if ($output) {
16986 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>), source is still present in $path");
16987 }
16988
16989 return;
16990 }
16991
16992
16993
16994
16995
16996
16997 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
16998 if ($output) {
16999 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
17000 }
17001 if (!$this->filesystem->removeJunction($path)) {
17002 $this->io->writeError("    <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>");
17003 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
17004 }
17005 } else {
17006 parent::remove($package, $path, $output);
17007 }
17008 }
17009
17010
17011
17012
17013 public function getVcsReference(PackageInterface $package, $path)
17014 {
17015 $parser = new VersionParser;
17016 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
17017 $dumper = new ArrayDumper;
17018
17019 $packageConfig = $dumper->dump($package);
17020 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
17021 return $packageVersion['commit'];
17022 }
17023 }
17024
17025
17026
17027
17028
17029
17030
17031
17032
17033
17034
17035
17036
17037
17038 private function safeJunctions()
17039 {
17040
17041  return function_exists('proc_open') &&
17042 (PHP_WINDOWS_VERSION_MAJOR > 6 ||
17043 (PHP_WINDOWS_VERSION_MAJOR === 6 && PHP_WINDOWS_VERSION_MINOR >= 1));
17044 }
17045 }
17046 <?php
17047
17048
17049
17050
17051
17052
17053
17054
17055
17056
17057
17058 namespace Composer\Downloader;
17059
17060 use Composer\Util\Filesystem;
17061
17062
17063
17064
17065
17066
17067
17068
17069
17070
17071 class PearPackageExtractor
17072 {
17073 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
17074
17075 private $filesystem;
17076 private $file;
17077
17078 public function __construct($file)
17079 {
17080 if (!is_file($file)) {
17081 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
17082 }
17083
17084 $this->filesystem = new Filesystem();
17085 $this->file = $file;
17086 }
17087
17088
17089
17090
17091
17092
17093
17094
17095
17096
17097 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
17098 {
17099 $extractionPath = $target.'/tarball';
17100
17101 try {
17102 $archive = new \PharData($this->file);
17103 $archive->extractTo($extractionPath, null, true);
17104
17105 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
17106 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
17107 }
17108
17109 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
17110 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
17111 $this->filesystem->removeDirectory($extractionPath);
17112 } catch (\Exception $exception) {
17113 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
17114 }
17115 }
17116
17117
17118
17119
17120
17121
17122
17123
17124
17125
17126 private function copyFiles($files, $source, $target, $roles, $vars)
17127 {
17128 foreach ($files as $file) {
17129 $from = $this->combine($source, $file['from']);
17130 $to = $this->combine($target, $roles[$file['role']]);
17131 $to = $this->combine($to, $file['to']);
17132 $tasks = $file['tasks'];
17133 $this->copyFile($from, $to, $tasks, $vars);
17134 }
17135 }
17136
17137 private function copyFile($from, $to, $tasks, $vars)
17138 {
17139 if (!is_file($from)) {
17140 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
17141 }
17142
17143 $this->filesystem->ensureDirectoryExists(dirname($to));
17144
17145 if (0 == count($tasks)) {
17146 $copied = copy($from, $to);
17147 } else {
17148 $content = file_get_contents($from);
17149 $replacements = array();
17150 foreach ($tasks as $task) {
17151 $pattern = $task['from'];
17152 $varName = $task['to'];
17153 if (isset($vars[$varName])) {
17154 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
17155 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
17156 } else {
17157 $replacements[$pattern] = $vars[$varName];
17158 }
17159 }
17160 }
17161 $content = strtr($content, $replacements);
17162
17163 $copied = file_put_contents($to, $content);
17164 }
17165
17166 if (false === $copied) {
17167 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
17168 }
17169 }
17170
17171
17172
17173
17174
17175
17176
17177
17178
17179
17180
17181 private function buildCopyActions($source, array $roles, $vars)
17182 {
17183
17184 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
17185 if (false === $package) {
17186 throw new \RuntimeException('Package definition file is not valid.');
17187 }
17188
17189 $packageSchemaVersion = $package['version'];
17190 if ('1.0' == $packageSchemaVersion) {
17191 $children = $package->release->filelist->children();
17192 $packageName = (string) $package->name;
17193 $packageVersion = (string) $package->release->version;
17194 $sourceDir = $packageName . '-' . $packageVersion;
17195 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
17196 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
17197 $children = $package->contents->children();
17198 $packageName = (string) $package->name;
17199 $packageVersion = (string) $package->version->release;
17200 $sourceDir = $packageName . '-' . $packageVersion;
17201 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
17202
17203 $namespaces = $package->getNamespaces();
17204 $package->registerXPathNamespace('ns', $namespaces['']);
17205 $releaseNodes = $package->xpath('ns:phprelease');
17206 $this->applyRelease($result, $releaseNodes, $vars);
17207 } else {
17208 throw new \RuntimeException('Unsupported schema version of package definition file.');
17209 }
17210
17211 return $result;
17212 }
17213
17214 private function applyRelease(&$actions, $releaseNodes, $vars)
17215 {
17216 foreach ($releaseNodes as $releaseNode) {
17217 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
17218 if ($requiredOs && $vars['os'] != $requiredOs) {
17219 continue;
17220 }
17221
17222 if ($releaseNode->filelist) {
17223 foreach ($releaseNode->filelist->children() as $action) {
17224 if ('install' == $action->getName()) {
17225 $name = (string) $action['name'];
17226 $as = (string) $action['as'];
17227 if (isset($actions[$name])) {
17228 $actions[$name]['to'] = $as;
17229 }
17230 } elseif ('ignore' == $action->getName()) {
17231 $name = (string) $action['name'];
17232 unset($actions[$name]);
17233 } else {
17234
17235  }
17236 }
17237 }
17238 break;
17239 }
17240 }
17241
17242 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
17243 {
17244 $result = array();
17245
17246
17247  foreach ($children as $child) {
17248
17249 if ($child->getName() == 'dir') {
17250 $dirSource = $this->combine($source, (string) $child['name']);
17251 $dirTarget = $child['baseinstalldir'] ?: $target;
17252 $dirRole = $child['role'] ?: $role;
17253 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
17254 $result = array_merge($result, $dirFiles);
17255 } elseif ($child->getName() == 'file') {
17256 $fileRole = (string) $child['role'] ?: $role;
17257 if (isset($targetRoles[$fileRole])) {
17258 $fileName = (string) ($child['name'] ?: $child[0]); 
17259  $fileSource = $this->combine($source, $fileName);
17260 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
17261 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
17262 $fileTarget = $packageName . '/' . $fileTarget;
17263 }
17264 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
17265 }
17266 }
17267 }
17268
17269 return $result;
17270 }
17271
17272 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
17273 {
17274 $result = array();
17275
17276
17277  foreach ($children as $child) {
17278
17279 if ('dir' == $child->getName()) {
17280 $dirSource = $this->combine($source, $child['name']);
17281 $dirTarget = $child['baseinstalldir'] ?: $target;
17282 $dirRole = $child['role'] ?: $role;
17283 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
17284 $result = array_merge($result, $dirFiles);
17285 } elseif ('file' == $child->getName()) {
17286 $fileRole = (string) $child['role'] ?: $role;
17287 if (isset($targetRoles[$fileRole])) {
17288 $fileSource = $this->combine($source, (string) $child['name']);
17289 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
17290 $fileTasks = array();
17291 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
17292 if ('replace' == $taskNode->getName()) {
17293 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
17294 }
17295 }
17296 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
17297 $fileTarget = $packageName . '/' . $fileTarget;
17298 }
17299 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
17300 }
17301 }
17302 }
17303
17304 return $result;
17305 }
17306
17307 private function combine($left, $right)
17308 {
17309 return rtrim($left, '/') . '/' . ltrim($right, '/');
17310 }
17311 }
17312 <?php
17313
17314
17315
17316
17317
17318
17319
17320
17321
17322
17323
17324 namespace Composer\Downloader;
17325
17326 use Composer\Package\PackageInterface;
17327 use Composer\Repository\VcsRepository;
17328 use Composer\Util\Perforce;
17329
17330
17331
17332
17333 class PerforceDownloader extends VcsDownloader
17334 {
17335
17336 protected $perforce;
17337
17338
17339
17340
17341 public function doDownload(PackageInterface $package, $path, $url)
17342 {
17343 $ref = $package->getSourceReference();
17344 $label = $this->getLabelFromSourceReference($ref);
17345
17346 $this->io->writeError('Cloning ' . $ref);
17347 $this->initPerforce($package, $path, $url);
17348 $this->perforce->setStream($ref);
17349 $this->perforce->p4Login();
17350 $this->perforce->writeP4ClientSpec();
17351 $this->perforce->connectClient();
17352 $this->perforce->syncCodeBase($label);
17353 $this->perforce->cleanupClientSpec();
17354 }
17355
17356 private function getLabelFromSourceReference($ref)
17357 {
17358 $pos = strpos($ref, '@');
17359 if (false !== $pos) {
17360 return substr($ref, $pos + 1);
17361 }
17362
17363 return null;
17364 }
17365
17366 public function initPerforce(PackageInterface $package, $path, $url)
17367 {
17368 if (!empty($this->perforce)) {
17369 $this->perforce->initializePath($path);
17370
17371 return;
17372 }
17373
17374 $repository = $package->getRepository();
17375 $repoConfig = null;
17376 if ($repository instanceof VcsRepository) {
17377 $repoConfig = $this->getRepoConfig($repository);
17378 }
17379 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
17380 }
17381
17382 private function getRepoConfig(VcsRepository $repository)
17383 {
17384 return $repository->getRepoConfig();
17385 }
17386
17387
17388
17389
17390 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17391 {
17392 $this->doDownload($target, $path, $url);
17393 }
17394
17395
17396
17397
17398 public function getLocalChanges(PackageInterface $package, $path)
17399 {
17400 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
17401 }
17402
17403
17404
17405
17406 protected function getCommitLogs($fromReference, $toReference, $path)
17407 {
17408 return $this->perforce->getCommitLogs($fromReference, $toReference);
17409 }
17410
17411 public function setPerforce($perforce)
17412 {
17413 $this->perforce = $perforce;
17414 }
17415
17416
17417
17418
17419 protected function hasMetadataRepository($path)
17420 {
17421 return true;
17422 }
17423 }
17424 <?php
17425
17426
17427
17428
17429
17430
17431
17432
17433
17434
17435
17436 namespace Composer\Downloader;
17437
17438
17439
17440
17441
17442
17443 class PharDownloader extends ArchiveDownloader
17444 {
17445
17446
17447
17448 protected function extract($file, $path)
17449 {
17450
17451  $archive = new \Phar($file);
17452 $archive->extractTo($path, null, true);
17453
17454
17455
17456
17457
17458 }
17459 }
17460 <?php
17461
17462
17463
17464
17465
17466
17467
17468
17469
17470
17471
17472 namespace Composer\Downloader;
17473
17474 use Composer\Config;
17475 use Composer\Cache;
17476 use Composer\EventDispatcher\EventDispatcher;
17477 use Composer\Util\IniHelper;
17478 use Composer\Util\Platform;
17479 use Composer\Util\ProcessExecutor;
17480 use Composer\Util\RemoteFilesystem;
17481 use Composer\IO\IOInterface;
17482 use RarArchive;
17483
17484
17485
17486
17487
17488
17489
17490
17491 class RarDownloader extends ArchiveDownloader
17492 {
17493 protected $process;
17494
17495 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17496 {
17497 $this->process = $process ?: new ProcessExecutor($io);
17498 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17499 }
17500
17501 protected function extract($file, $path)
17502 {
17503 $processError = null;
17504
17505
17506  if (!Platform::isWindows()) {
17507 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
17508
17509 if (0 === $this->process->execute($command, $ignoredOutput)) {
17510 return;
17511 }
17512
17513 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17514 }
17515
17516 if (!class_exists('RarArchive')) {
17517
17518  $iniMessage = IniHelper::getMessage();
17519
17520 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
17521 . $iniMessage . "\n" . $processError;
17522
17523 if (!Platform::isWindows()) {
17524 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
17525 }
17526
17527 throw new \RuntimeException($error);
17528 }
17529
17530 $rarArchive = RarArchive::open($file);
17531
17532 if (false === $rarArchive) {
17533 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
17534 }
17535
17536 $entries = $rarArchive->getEntries();
17537
17538 if (false === $entries) {
17539 throw new \RuntimeException('Could not retrieve RAR archive entries');
17540 }
17541
17542 foreach ($entries as $entry) {
17543 if (false === $entry->extract($path)) {
17544 throw new \RuntimeException('Could not extract entry');
17545 }
17546 }
17547
17548 $rarArchive->close();
17549 }
17550 }
17551 <?php
17552
17553
17554
17555
17556
17557
17558
17559
17560
17561
17562
17563 namespace Composer\Downloader;
17564
17565 use Composer\Package\PackageInterface;
17566 use Composer\Util\Svn as SvnUtil;
17567 use Composer\Repository\VcsRepository;
17568 use Composer\Util\ProcessExecutor;
17569
17570
17571
17572
17573
17574 class SvnDownloader extends VcsDownloader
17575 {
17576 protected $cacheCredentials = true;
17577
17578
17579
17580
17581 public function doDownload(PackageInterface $package, $path, $url)
17582 {
17583 SvnUtil::cleanEnv();
17584 $ref = $package->getSourceReference();
17585
17586 $repo = $package->getRepository();
17587 if ($repo instanceof VcsRepository) {
17588 $repoConfig = $repo->getRepoConfig();
17589 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
17590 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
17591 }
17592 }
17593
17594 $this->io->writeError(" Checking out ".$package->getSourceReference());
17595 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
17596 }
17597
17598
17599
17600
17601 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17602 {
17603 SvnUtil::cleanEnv();
17604 $ref = $target->getSourceReference();
17605
17606 if (!$this->hasMetadataRepository($path)) {
17607 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
17608 }
17609
17610 $util = new SvnUtil($url, $this->io, $this->config);
17611 $flags = "";
17612 if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
17613 $flags .= ' --ignore-ancestry';
17614 }
17615
17616 $this->io->writeError(" Checking out " . $ref);
17617 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
17618 }
17619
17620
17621
17622
17623 public function getLocalChanges(PackageInterface $package, $path)
17624 {
17625 if (!$this->hasMetadataRepository($path)) {
17626 return null;
17627 }
17628
17629 $this->process->execute('svn status --ignore-externals', $output, $path);
17630
17631 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
17632 }
17633
17634
17635
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645
17646 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
17647 {
17648 $util = new SvnUtil($baseUrl, $this->io, $this->config);
17649 $util->setCacheCredentials($this->cacheCredentials);
17650 try {
17651 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
17652 } catch (\RuntimeException $e) {
17653 throw new \RuntimeException(
17654 'Package could not be downloaded, '.$e->getMessage()
17655 );
17656 }
17657 }
17658
17659
17660
17661
17662 protected function cleanChanges(PackageInterface $package, $path, $update)
17663 {
17664 if (!$changes = $this->getLocalChanges($package, $path)) {
17665 return;
17666 }
17667
17668 if (!$this->io->isInteractive()) {
17669 if (true === $this->config->get('discard-changes')) {
17670 return $this->discardChanges($path);
17671 }
17672
17673 return parent::cleanChanges($package, $path, $update);
17674 }
17675
17676 $changes = array_map(function ($elem) {
17677 return '    '.$elem;
17678 }, preg_split('{\s*\r?\n\s*}', $changes));
17679 $countChanges = count($changes);
17680 $this->io->writeError(sprintf('    <error>The package has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
17681 $this->io->writeError(array_slice($changes, 0, 10));
17682 if ($countChanges > 10) {
17683 $remaingChanges = $countChanges - 10;
17684 $this->io->writeError(
17685 sprintf(
17686 '    <info>'.$remaingChanges.' more file%s modified, choose "v" to view the full list</info>',
17687 $remaingChanges === 1 ? '' : 's'
17688 )
17689 );
17690 }
17691
17692 while (true) {
17693 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
17694 case 'y':
17695 $this->discardChanges($path);
17696 break 2;
17697
17698 case 'n':
17699 throw new \RuntimeException('Update aborted');
17700
17701 case 'v':
17702 $this->io->writeError($changes);
17703 break;
17704
17705 case '?':
17706 default:
17707 $this->io->writeError(array(
17708 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
17709 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
17710 '    v - view modified files',
17711 '    ? - print help',
17712 ));
17713 break;
17714 }
17715 }
17716 }
17717
17718
17719
17720
17721 protected function getCommitLogs($fromReference, $toReference, $path)
17722 {
17723 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
17724
17725  $command = sprintf('svn info --non-interactive --xml %s', ProcessExecutor::escape($path));
17726 if (0 !== $this->process->execute($command, $output, $path)) {
17727 throw new \RuntimeException(
17728 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
17729 );
17730 }
17731
17732 $urlPattern = '#<url>(.*)</url>#';
17733 if (preg_match($urlPattern, $output, $matches)) {
17734 $baseUrl = $matches[1];
17735 } else {
17736 throw new \RuntimeException(
17737 'Unable to determine svn url for path '. $path
17738 );
17739 }
17740
17741
17742  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
17743 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
17744
17745 $command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision));
17746
17747 $util = new SvnUtil($baseUrl, $this->io, $this->config);
17748 $util->setCacheCredentials($this->cacheCredentials);
17749 try {
17750 return $util->executeLocal($command, $path, null, $this->io->isVerbose());
17751 } catch (\RuntimeException $e) {
17752 throw new \RuntimeException(
17753 'Failed to execute ' . $command . "\n\n".$e->getMessage()
17754 );
17755 }
17756 }
17757
17758 return "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
17759 }
17760
17761 protected function discardChanges($path)
17762 {
17763 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
17764 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
17765 }
17766 }
17767
17768
17769
17770
17771 protected function hasMetadataRepository($path)
17772 {
17773 return is_dir($path.'/.svn');
17774 }
17775 }
17776 <?php
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788 namespace Composer\Downloader;
17789
17790
17791
17792
17793
17794
17795 class TarDownloader extends ArchiveDownloader
17796 {
17797
17798
17799
17800 protected function extract($file, $path)
17801 {
17802
17803  $archive = new \PharData($file);
17804 $archive->extractTo($path, null, true);
17805 }
17806 }
17807 <?php
17808
17809
17810
17811
17812
17813
17814
17815
17816
17817
17818
17819 namespace Composer\Downloader;
17820
17821
17822
17823
17824 class TransportException extends \RuntimeException
17825 {
17826 protected $headers;
17827 protected $response;
17828 protected $statusCode;
17829
17830 public function setHeaders($headers)
17831 {
17832 $this->headers = $headers;
17833 }
17834
17835 public function getHeaders()
17836 {
17837 return $this->headers;
17838 }
17839
17840 public function setResponse($response)
17841 {
17842 $this->response = $response;
17843 }
17844
17845 public function getResponse()
17846 {
17847 return $this->response;
17848 }
17849
17850 public function setStatusCode($statusCode)
17851 {
17852 $this->statusCode = $statusCode;
17853 }
17854
17855 public function getStatusCode()
17856 {
17857 return $this->statusCode;
17858 }
17859 }
17860 <?php
17861
17862
17863
17864
17865
17866
17867
17868
17869
17870
17871
17872 namespace Composer\Downloader;
17873
17874 use Composer\Package\PackageInterface;
17875
17876
17877
17878
17879
17880
17881 interface VcsCapableDownloaderInterface
17882 {
17883
17884
17885
17886
17887
17888
17889
17890 public function getVcsReference(PackageInterface $package, $path);
17891 }
17892 <?php
17893
17894
17895
17896
17897
17898
17899
17900
17901
17902
17903
17904 namespace Composer\Downloader;
17905
17906 use Composer\Config;
17907 use Composer\Package\Dumper\ArrayDumper;
17908 use Composer\Package\PackageInterface;
17909 use Composer\Package\Version\VersionGuesser;
17910 use Composer\Package\Version\VersionParser;
17911 use Composer\Util\ProcessExecutor;
17912 use Composer\IO\IOInterface;
17913 use Composer\Util\Filesystem;
17914
17915
17916
17917
17918 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
17919 {
17920
17921 protected $io;
17922
17923 protected $config;
17924
17925 protected $process;
17926
17927 protected $filesystem;
17928
17929 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
17930 {
17931 $this->io = $io;
17932 $this->config = $config;
17933 $this->process = $process ?: new ProcessExecutor($io);
17934 $this->filesystem = $fs ?: new Filesystem($this->process);
17935 }
17936
17937
17938
17939
17940 public function getInstallationSource()
17941 {
17942 return 'source';
17943 }
17944
17945
17946
17947
17948 public function download(PackageInterface $package, $path)
17949 {
17950 if (!$package->getSourceReference()) {
17951 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
17952 }
17953
17954 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
17955 $this->filesystem->emptyDirectory($path);
17956
17957 $urls = $package->getSourceUrls();
17958 while ($url = array_shift($urls)) {
17959 try {
17960 if (Filesystem::isLocalPath($url)) {
17961
17962  
17963  $needle = 'file://';
17964 $isFileProtocol = false;
17965 if (0 === strpos($url, $needle)) {
17966 $url = substr($url, strlen($needle));
17967 $isFileProtocol = true;
17968 }
17969
17970
17971  if (false !== strpos($url, '%')) {
17972 $url = rawurldecode($url);
17973 }
17974
17975 $url = realpath($url);
17976
17977 if ($isFileProtocol) {
17978 $url = $needle . $url;
17979 }
17980 }
17981 $this->doDownload($package, $path, $url);
17982 break;
17983 } catch (\Exception $e) {
17984
17985  if ($e instanceof \PHPUnit_Framework_Exception) {
17986 throw $e;
17987 }
17988 if ($this->io->isDebug()) {
17989 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
17990 } elseif (count($urls)) {
17991 $this->io->writeError('    Failed, trying the next URL');
17992 }
17993 if (!count($urls)) {
17994 throw $e;
17995 }
17996 }
17997 }
17998 }
17999
18000
18001
18002
18003 public function update(PackageInterface $initial, PackageInterface $target, $path)
18004 {
18005 if (!$target->getSourceReference()) {
18006 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
18007 }
18008
18009 $name = $target->getName();
18010 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
18011 if ($target->getSourceType() === 'svn') {
18012 $from = $initial->getSourceReference();
18013 $to = $target->getSourceReference();
18014 } else {
18015 $from = substr($initial->getSourceReference(), 0, 7);
18016 $to = substr($target->getSourceReference(), 0, 7);
18017 }
18018 $name .= ' '.$initial->getPrettyVersion();
18019 } else {
18020 $from = $initial->getFullPrettyVersion();
18021 $to = $target->getFullPrettyVersion();
18022 }
18023
18024 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
18025 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
18026
18027 $this->cleanChanges($initial, $path, true);
18028 $urls = $target->getSourceUrls();
18029
18030 $exception = null;
18031 while ($url = array_shift($urls)) {
18032 try {
18033 if (Filesystem::isLocalPath($url)) {
18034 $url = realpath($url);
18035 }
18036 $this->doUpdate($initial, $target, $path, $url);
18037
18038 $exception = null;
18039 break;
18040 } catch (\Exception $exception) {
18041
18042  if ($exception instanceof \PHPUnit_Framework_Exception) {
18043 throw $exception;
18044 }
18045 if ($this->io->isDebug()) {
18046 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
18047 } elseif (count($urls)) {
18048 $this->io->writeError('    Failed, trying the next URL');
18049 }
18050 }
18051 }
18052
18053 $this->reapplyChanges($path);
18054
18055
18056  
18057  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
18058 $message = 'Pulling in changes:';
18059 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
18060
18061 if (!trim($logs)) {
18062 $message = 'Rolling back changes:';
18063 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
18064 }
18065
18066 if (trim($logs)) {
18067 $logs = implode("\n", array_map(function ($line) {
18068 return '      ' . $line;
18069 }, explode("\n", $logs)));
18070
18071
18072  $logs = str_replace('<', '\<', $logs);
18073
18074 $this->io->writeError('    '.$message);
18075 $this->io->writeError($logs);
18076 }
18077 }
18078
18079 if (!$urls && $exception) {
18080 throw $exception;
18081 }
18082 }
18083
18084
18085
18086
18087 public function remove(PackageInterface $package, $path)
18088 {
18089 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
18090 $this->cleanChanges($package, $path, false);
18091 if (!$this->filesystem->removeDirectory($path)) {
18092 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
18093 }
18094 }
18095
18096
18097
18098
18099
18100 public function setOutputProgress($outputProgress)
18101 {
18102 return $this;
18103 }
18104
18105
18106
18107
18108 public function getVcsReference(PackageInterface $package, $path)
18109 {
18110 $parser = new VersionParser;
18111 $guesser = new VersionGuesser($this->config, $this->process, $parser);
18112 $dumper = new ArrayDumper;
18113
18114 $packageConfig = $dumper->dump($package);
18115 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
18116 return $packageVersion['commit'];
18117 }
18118 }
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129 protected function cleanChanges(PackageInterface $package, $path, $update)
18130 {
18131
18132  if (null !== $this->getLocalChanges($package, $path)) {
18133 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
18134 }
18135 }
18136
18137
18138
18139
18140
18141
18142
18143 protected function reapplyChanges($path)
18144 {
18145 }
18146
18147
18148
18149
18150
18151
18152
18153
18154 abstract protected function doDownload(PackageInterface $package, $path, $url);
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
18165
18166
18167
18168
18169
18170
18171
18172
18173
18174 abstract protected function getCommitLogs($fromReference, $toReference, $path);
18175
18176
18177
18178
18179
18180
18181
18182
18183 abstract protected function hasMetadataRepository($path);
18184 }
18185 <?php
18186
18187
18188
18189
18190
18191
18192
18193
18194
18195
18196
18197 namespace Composer\Downloader;
18198
18199 use Composer\Config;
18200 use Composer\Cache;
18201 use Composer\EventDispatcher\EventDispatcher;
18202 use Composer\Package\PackageInterface;
18203 use Composer\Util\ProcessExecutor;
18204 use Composer\Util\RemoteFilesystem;
18205 use Composer\IO\IOInterface;
18206
18207
18208
18209
18210
18211
18212
18213 class XzDownloader extends ArchiveDownloader
18214 {
18215 protected $process;
18216
18217 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18218 {
18219 $this->process = $process ?: new ProcessExecutor($io);
18220
18221 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
18222 }
18223
18224 protected function extract($file, $path)
18225 {
18226 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
18227
18228 if (0 === $this->process->execute($command, $ignoredOutput)) {
18229 return;
18230 }
18231
18232 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
18233
18234 throw new \RuntimeException($processError);
18235 }
18236
18237
18238
18239
18240 protected function getFileName(PackageInterface $package, $path)
18241 {
18242 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
18243 }
18244 }
18245 <?php
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257 namespace Composer\Downloader;
18258
18259 use Composer\Config;
18260 use Composer\Cache;
18261 use Composer\EventDispatcher\EventDispatcher;
18262 use Composer\Package\PackageInterface;
18263 use Composer\Util\IniHelper;
18264 use Composer\Util\Platform;
18265 use Composer\Util\ProcessExecutor;
18266 use Composer\Util\RemoteFilesystem;
18267 use Composer\IO\IOInterface;
18268 use Symfony\Component\Process\ExecutableFinder;
18269 use ZipArchive;
18270
18271
18272
18273
18274 class ZipDownloader extends ArchiveDownloader
18275 {
18276 protected static $hasSystemUnzip;
18277 private static $hasZipArchive;
18278 private static $isWindows;
18279
18280 protected $process;
18281 private $zipArchiveObject;
18282
18283 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18284 {
18285 $this->process = $process ?: new ProcessExecutor($io);
18286 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
18287 }
18288
18289
18290
18291
18292 public function download(PackageInterface $package, $path, $output = true)
18293 {
18294 if (null === self::$hasSystemUnzip) {
18295 $finder = new ExecutableFinder;
18296 self::$hasSystemUnzip = (bool) $finder->find('unzip');
18297 }
18298
18299 if (null === self::$hasZipArchive) {
18300 self::$hasZipArchive = class_exists('ZipArchive');
18301 }
18302
18303 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
18304
18305  $iniMessage = IniHelper::getMessage();
18306 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
18307
18308 throw new \RuntimeException($error);
18309 }
18310
18311 if (null === self::$isWindows) {
18312 self::$isWindows = Platform::isWindows();
18313
18314 if (!self::$isWindows && !self::$hasSystemUnzip) {
18315 $this->io->writeError("<warning>As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.</warning>");
18316 $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>");
18317 $this->io->writeError("<warning>Installing 'unzip' may remediate them.</warning>");
18318 }
18319 }
18320
18321 return parent::download($package, $path, $output);
18322 }
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332 protected function extractWithSystemUnzip($file, $path, $isLastChance)
18333 {
18334 if (!self::$hasZipArchive) {
18335
18336  $isLastChance = true;
18337 }
18338
18339 if (!self::$hasSystemUnzip && !$isLastChance) {
18340
18341  
18342  return $this->extractWithZipArchive($file, $path, true);
18343 }
18344
18345 $processError = null;
18346
18347  $overwrite = $isLastChance ? '-o' : '';
18348
18349 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
18350
18351 try {
18352 if (0 === $this->process->execute($command, $ignoredOutput)) {
18353 return true;
18354 }
18355
18356 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
18357 } catch (\Exception $e) {
18358 $processError = $e;
18359 }
18360
18361 if ($isLastChance) {
18362 throw $processError;
18363 }
18364
18365 $this->io->writeError('    '.$processError->getMessage());
18366 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
18367 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
18368
18369 return $this->extractWithZipArchive($file, $path, true);
18370 }
18371
18372
18373
18374
18375
18376
18377
18378
18379
18380 protected function extractWithZipArchive($file, $path, $isLastChance)
18381 {
18382 if (!self::$hasSystemUnzip) {
18383
18384  $isLastChance = true;
18385 }
18386
18387 if (!self::$hasZipArchive && !$isLastChance) {
18388
18389  
18390  return $this->extractWithSystemUnzip($file, $path, true);
18391 }
18392
18393 $processError = null;
18394 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
18395
18396 try {
18397 if (true === ($retval = $zipArchive->open($file))) {
18398 $extractResult = $zipArchive->extractTo($path);
18399
18400 if (true === $extractResult) {
18401 $zipArchive->close();
18402
18403 return true;
18404 }
18405
18406 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
18407 } else {
18408 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
18409 }
18410 } catch (\ErrorException $e) {
18411 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
18412 } catch (\Exception $e) {
18413 $processError = $e;
18414 }
18415
18416 if ($isLastChance) {
18417 throw $processError;
18418 }
18419
18420 $this->io->writeError('    '.$processError->getMessage());
18421 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
18422
18423 return $this->extractWithSystemUnzip($file, $path, true);
18424 }
18425
18426
18427
18428
18429
18430
18431
18432 public function extract($file, $path)
18433 {
18434
18435  if (self::$isWindows) {
18436 $this->extractWithZipArchive($file, $path, false);
18437 } else {
18438 $this->extractWithSystemUnzip($file, $path, false);
18439 }
18440 }
18441
18442
18443
18444
18445
18446
18447
18448
18449 protected function getErrorMessage($retval, $file)
18450 {
18451 switch ($retval) {
18452 case ZipArchive::ER_EXISTS:
18453 return sprintf("File '%s' already exists.", $file);
18454 case ZipArchive::ER_INCONS:
18455 return sprintf("Zip archive '%s' is inconsistent.", $file);
18456 case ZipArchive::ER_INVAL:
18457 return sprintf("Invalid argument (%s)", $file);
18458 case ZipArchive::ER_MEMORY:
18459 return sprintf("Malloc failure (%s)", $file);
18460 case ZipArchive::ER_NOENT:
18461 return sprintf("No such zip file: '%s'", $file);
18462 case ZipArchive::ER_NOZIP:
18463 return sprintf("'%s' is not a zip archive.", $file);
18464 case ZipArchive::ER_OPEN:
18465 return sprintf("Can't open zip file: %s", $file);
18466 case ZipArchive::ER_READ:
18467 return sprintf("Zip read error (%s)", $file);
18468 case ZipArchive::ER_SEEK:
18469 return sprintf("Zip seek error (%s)", $file);
18470 default:
18471 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
18472 }
18473 }
18474 }
18475 <?php
18476
18477
18478
18479
18480
18481
18482
18483
18484
18485
18486
18487 namespace Composer\EventDispatcher;
18488
18489
18490
18491
18492
18493
18494 class Event
18495 {
18496
18497
18498
18499 protected $name;
18500
18501
18502
18503
18504 protected $args;
18505
18506
18507
18508
18509 protected $flags;
18510
18511
18512
18513
18514 private $propagationStopped = false;
18515
18516
18517
18518
18519
18520
18521
18522
18523 public function __construct($name, array $args = array(), array $flags = array())
18524 {
18525 $this->name = $name;
18526 $this->args = $args;
18527 $this->flags = $flags;
18528 }
18529
18530
18531
18532
18533
18534
18535 public function getName()
18536 {
18537 return $this->name;
18538 }
18539
18540
18541
18542
18543
18544
18545 public function getArguments()
18546 {
18547 return $this->args;
18548 }
18549
18550
18551
18552
18553
18554
18555 public function getFlags()
18556 {
18557 return $this->flags;
18558 }
18559
18560
18561
18562
18563
18564
18565 public function isPropagationStopped()
18566 {
18567 return $this->propagationStopped;
18568 }
18569
18570
18571
18572
18573 public function stopPropagation()
18574 {
18575 $this->propagationStopped = true;
18576 }
18577 }
18578 <?php
18579
18580
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590 namespace Composer\EventDispatcher;
18591
18592 use Composer\DependencyResolver\PolicyInterface;
18593 use Composer\DependencyResolver\Pool;
18594 use Composer\DependencyResolver\Request;
18595 use Composer\Installer\InstallerEvent;
18596 use Composer\IO\IOInterface;
18597 use Composer\Composer;
18598 use Composer\DependencyResolver\Operation\OperationInterface;
18599 use Composer\Repository\CompositeRepository;
18600 use Composer\Script;
18601 use Composer\Installer\PackageEvent;
18602 use Composer\Installer\BinaryInstaller;
18603 use Composer\Util\ProcessExecutor;
18604 use Composer\Script\Event as ScriptEvent;
18605 use Symfony\Component\Process\PhpExecutableFinder;
18606
18607
18608
18609
18610
18611
18612
18613
18614
18615
18616
18617
18618
18619
18620 class EventDispatcher
18621 {
18622 protected $composer;
18623 protected $io;
18624 protected $loader;
18625 protected $process;
18626 protected $listeners;
18627 private $eventStack;
18628
18629
18630
18631
18632
18633
18634
18635
18636 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
18637 {
18638 $this->composer = $composer;
18639 $this->io = $io;
18640 $this->process = $process ?: new ProcessExecutor($io);
18641 $this->eventStack = array();
18642 }
18643
18644
18645
18646
18647
18648
18649
18650
18651
18652 public function dispatch($eventName, Event $event = null)
18653 {
18654 if (null === $event) {
18655 $event = new Event($eventName);
18656 }
18657
18658 return $this->doDispatch($event);
18659 }
18660
18661
18662
18663
18664
18665
18666
18667
18668
18669
18670
18671 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
18672 {
18673 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
18674 }
18675
18676
18677
18678
18679
18680
18681
18682
18683
18684
18685
18686
18687
18688
18689
18690
18691 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
18692 {
18693 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
18694 }
18695
18696
18697
18698
18699
18700
18701
18702
18703
18704
18705
18706
18707
18708
18709
18710 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
18711 {
18712 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
18713 }
18714
18715
18716
18717
18718
18719
18720
18721
18722
18723 protected function doDispatch(Event $event)
18724 {
18725 $pathStr = 'PATH';
18726 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
18727 $pathStr = 'Path';
18728 }
18729
18730
18731  $binDir = $this->composer->getConfig()->get('bin-dir');
18732 if (is_dir($binDir)) {
18733 $binDir = realpath($binDir);
18734 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
18735 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
18736 putenv($pathStr.'='.$_SERVER[$pathStr]);
18737 }
18738 }
18739
18740 $listeners = $this->getListeners($event);
18741
18742 $this->pushEvent($event);
18743
18744 $return = 0;
18745 foreach ($listeners as $callable) {
18746 if (!is_string($callable)) {
18747 if (!is_callable($callable)) {
18748 $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
18749
18750 throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
18751 }
18752 $event = $this->checkListenerExpectedEvent($callable, $event);
18753 $return = false === call_user_func($callable, $event) ? 1 : 0;
18754 } elseif ($this->isComposerScript($callable)) {
18755 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
18756
18757 $script = explode(' ', substr($callable, 1));
18758 $scriptName = $script[0];
18759 unset($script[0]);
18760
18761 $args = array_merge($script, $event->getArguments());
18762 $flags = $event->getFlags();
18763 if (substr($callable, 0, 10) === '@composer ') {
18764 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
18765 if (0 !== ($exitCode = $this->process->execute($exec))) {
18766 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18767
18768 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
18769 }
18770 } else {
18771 if (!$this->getListeners(new Event($scriptName))) {
18772 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
18773 }
18774
18775 try {
18776 $scriptEvent = new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags);
18777 $scriptEvent->setOriginatingEvent($event);
18778 $return = $this->dispatch($scriptName, $scriptEvent);
18779 } catch (ScriptExecutionException $e) {
18780 $this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18781 throw $e;
18782 }
18783 }
18784 } elseif ($this->isPhpScript($callable)) {
18785 $className = substr($callable, 0, strpos($callable, '::'));
18786 $methodName = substr($callable, strpos($callable, '::') + 2);
18787
18788 if (!class_exists($className)) {
18789 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
18790 continue;
18791 }
18792 if (!is_callable($callable)) {
18793 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
18794 continue;
18795 }
18796
18797 try {
18798 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
18799 } catch (\Exception $e) {
18800 $message = "Script %s handling the %s event terminated with an exception";
18801 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
18802 throw $e;
18803 }
18804 } else {
18805 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
18806 $exec = $callable . ($args === '' ? '' : ' '.$args);
18807 if ($this->io->isVerbose()) {
18808 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
18809 } else {
18810 $this->io->writeError(sprintf('> %s', $exec));
18811 }
18812
18813 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
18814 if ($possibleLocalBinaries) {
18815 foreach ($possibleLocalBinaries as $localExec) {
18816 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
18817 $caller = BinaryInstaller::determineBinaryCaller($localExec);
18818 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
18819 break;
18820 }
18821 }
18822 }
18823
18824 if (substr($exec, 0, 5) === '@php ') {
18825 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
18826 } else {
18827 $finder = new PhpExecutableFinder();
18828 $phpPath = $finder->find(false);
18829 if ($phpPath) {
18830 putenv('PHP_BINARY=' . $phpPath);
18831 }
18832 }
18833
18834 if (0 !== ($exitCode = $this->process->execute($exec))) {
18835 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
18836
18837 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
18838 }
18839 }
18840
18841 if ($event->isPropagationStopped()) {
18842 break;
18843 }
18844 }
18845
18846 $this->popEvent();
18847
18848 return $return;
18849 }
18850
18851 protected function getPhpExecCommand()
18852 {
18853 $finder = new PhpExecutableFinder();
18854 $phpPath = $finder->find(false);
18855 if (!$phpPath) {
18856 throw new \RuntimeException('Failed to locate PHP binary to execute '.$phpPath);
18857 }
18858 $phpArgs = $finder->findArguments();
18859 $phpArgs = $phpArgs ? ' ' . implode(' ', $phpArgs) : '';
18860 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
18861 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
18862 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
18863
18864 return ProcessExecutor::escape($phpPath) . $phpArgs . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
18865 }
18866
18867
18868
18869
18870
18871
18872 protected function executeEventPhpScript($className, $methodName, Event $event)
18873 {
18874 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
18875
18876 if ($this->io->isVerbose()) {
18877 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
18878 } else {
18879 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
18880 }
18881
18882 return $className::$methodName($event);
18883 }
18884
18885
18886
18887
18888
18889
18890 protected function checkListenerExpectedEvent($target, Event $event)
18891 {
18892 if (in_array($event->getName(), array(
18893 'init',
18894 'command',
18895 'pre-file-download',
18896 ), true)) {
18897 return $event;
18898 }
18899
18900 try {
18901 $reflected = new \ReflectionParameter($target, 0);
18902 } catch (\Exception $e) {
18903 return $event;
18904 }
18905
18906 $typehint = $reflected->getClass();
18907
18908 if (!$typehint instanceof \ReflectionClass) {
18909 return $event;
18910 }
18911
18912 $expected = $typehint->getName();
18913
18914
18915  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
18916 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);
18917 $event = new \Composer\Script\CommandEvent(
18918 $event->getName(),
18919 $event->getComposer(),
18920 $event->getIO(),
18921 $event->isDevMode(),
18922 $event->getArguments()
18923 );
18924 }
18925 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
18926 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);
18927 $event = new \Composer\Script\PackageEvent(
18928 $event->getName(),
18929 $event->getComposer(),
18930 $event->getIO(),
18931 $event->isDevMode(),
18932 $event->getPolicy(),
18933 $event->getPool(),
18934 $event->getInstalledRepo(),
18935 $event->getRequest(),
18936 $event->getOperations(),
18937 $event->getOperation()
18938 );
18939 }
18940 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
18941 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);
18942 $event = new \Composer\Script\Event(
18943 $event->getName(),
18944 $event->getComposer(),
18945 $event->getIO(),
18946 $event->isDevMode(),
18947 $event->getArguments(),
18948 $event->getFlags()
18949 );
18950 }
18951
18952 return $event;
18953 }
18954
18955 private function serializeCallback($cb)
18956 {
18957 if (is_array($cb) && count($cb) === 2) {
18958 if (is_object($cb[0])) {
18959 $cb[0] = get_class($cb[0]);
18960 }
18961 if (is_string($cb[0]) && is_string($cb[1])) {
18962 $cb = implode('::', $cb);
18963 }
18964 }
18965 if (is_string($cb)) {
18966 return $cb;
18967 }
18968
18969 return var_export($cb, true);
18970 }
18971
18972
18973
18974
18975
18976
18977
18978
18979 public function addListener($eventName, $listener, $priority = 0)
18980 {
18981 $this->listeners[$eventName][$priority][] = $listener;
18982 }
18983
18984
18985
18986
18987
18988
18989
18990
18991 public function addSubscriber(EventSubscriberInterface $subscriber)
18992 {
18993 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
18994 if (is_string($params)) {
18995 $this->addListener($eventName, array($subscriber, $params));
18996 } elseif (is_string($params[0])) {
18997 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
18998 } else {
18999 foreach ($params as $listener) {
19000 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
19001 }
19002 }
19003 }
19004 }
19005
19006
19007
19008
19009
19010
19011
19012 protected function getListeners(Event $event)
19013 {
19014 $scriptListeners = $this->getScriptListeners($event);
19015
19016 if (!isset($this->listeners[$event->getName()][0])) {
19017 $this->listeners[$event->getName()][0] = array();
19018 }
19019 krsort($this->listeners[$event->getName()]);
19020
19021 $listeners = $this->listeners;
19022 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
19023
19024 return call_user_func_array('array_merge', $listeners[$event->getName()]);
19025 }
19026
19027
19028
19029
19030
19031
19032
19033 public function hasEventListeners(Event $event)
19034 {
19035 $listeners = $this->getListeners($event);
19036
19037 return count($listeners) > 0;
19038 }
19039
19040
19041
19042
19043
19044
19045
19046 protected function getScriptListeners(Event $event)
19047 {
19048 $package = $this->composer->getPackage();
19049 $scripts = $package->getScripts();
19050
19051 if (empty($scripts[$event->getName()])) {
19052 return array();
19053 }
19054
19055 if ($this->loader) {
19056 $this->loader->unregister();
19057 }
19058
19059 $generator = $this->composer->getAutoloadGenerator();
19060 if ($event instanceof ScriptEvent) {
19061 $generator->setDevMode($event->isDevMode());
19062 }
19063
19064 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
19065 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
19066 $map = $generator->parseAutoloads($packageMap, $package);
19067 $this->loader = $generator->createLoader($map);
19068 $this->loader->register();
19069
19070 return $scripts[$event->getName()];
19071 }
19072
19073
19074
19075
19076
19077
19078
19079 protected function isPhpScript($callable)
19080 {
19081 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
19082 }
19083
19084
19085
19086
19087
19088
19089
19090 protected function isComposerScript($callable)
19091 {
19092 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
19093 }
19094
19095
19096
19097
19098
19099
19100
19101
19102 protected function pushEvent(Event $event)
19103 {
19104 $eventName = $event->getName();
19105 if (in_array($eventName, $this->eventStack)) {
19106 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
19107 }
19108
19109 return array_push($this->eventStack, $eventName);
19110 }
19111
19112
19113
19114
19115
19116
19117 protected function popEvent()
19118 {
19119 return array_pop($this->eventStack);
19120 }
19121 }
19122 <?php
19123
19124
19125
19126
19127
19128
19129
19130
19131
19132
19133
19134 namespace Composer\EventDispatcher;
19135
19136
19137
19138
19139
19140
19141
19142
19143
19144
19145
19146
19147
19148 interface EventSubscriberInterface
19149 {
19150
19151
19152
19153
19154
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168 public static function getSubscribedEvents();
19169 }
19170 <?php
19171
19172
19173
19174
19175
19176
19177
19178
19179
19180
19181
19182 namespace Composer\EventDispatcher;
19183
19184
19185
19186
19187 class ScriptExecutionException extends \RuntimeException
19188 {
19189 }
19190 <?php
19191
19192
19193
19194
19195
19196
19197
19198
19199
19200
19201
19202 namespace Composer\Exception;
19203
19204
19205
19206
19207 class NoSslException extends \RuntimeException
19208 {
19209 }
19210 <?php
19211
19212
19213
19214
19215
19216
19217
19218
19219
19220
19221
19222 namespace Composer;
19223
19224 use Composer\Config\JsonConfigSource;
19225 use Composer\Json\JsonFile;
19226 use Composer\IO\IOInterface;
19227 use Composer\Package\Archiver;
19228 use Composer\Package\Version\VersionGuesser;
19229 use Composer\Repository\RepositoryManager;
19230 use Composer\Repository\RepositoryFactory;
19231 use Composer\Repository\WritableRepositoryInterface;
19232 use Composer\Util\Filesystem;
19233 use Composer\Util\Platform;
19234 use Composer\Util\ProcessExecutor;
19235 use Composer\Util\RemoteFilesystem;
19236 use Composer\Util\Silencer;
19237 use Composer\Plugin\PluginEvents;
19238 use Composer\EventDispatcher\Event;
19239 use Seld\JsonLint\DuplicateKeyException;
19240 use Symfony\Component\Console\Formatter\OutputFormatter;
19241 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
19242 use Symfony\Component\Console\Output\ConsoleOutput;
19243 use Composer\EventDispatcher\EventDispatcher;
19244 use Composer\Autoload\AutoloadGenerator;
19245 use Composer\Package\Version\VersionParser;
19246 use Composer\Downloader\TransportException;
19247 use Seld\JsonLint\JsonParser;
19248
19249
19250
19251
19252
19253
19254
19255
19256
19257 class Factory
19258 {
19259
19260
19261
19262
19263 protected static function getHomeDir()
19264 {
19265 $home = getenv('COMPOSER_HOME');
19266 if ($home) {
19267 return $home;
19268 }
19269
19270 if (Platform::isWindows()) {
19271 if (!getenv('APPDATA')) {
19272 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
19273 }
19274
19275 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
19276 }
19277
19278 $userDir = self::getUserDir();
19279 if (is_dir($userDir . '/.composer')) {
19280 return $userDir . '/.composer';
19281 }
19282
19283 if (self::useXdg()) {
19284
19285  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
19286
19287 return $xdgConfig . '/composer';
19288 }
19289
19290 return $userDir . '/.composer';
19291 }
19292
19293
19294
19295
19296
19297 protected static function getCacheDir($home)
19298 {
19299 $cacheDir = getenv('COMPOSER_CACHE_DIR');
19300 if ($cacheDir) {
19301 return $cacheDir;
19302 }
19303
19304 $homeEnv = getenv('COMPOSER_HOME');
19305 if ($homeEnv) {
19306 return $homeEnv . '/cache';
19307 }
19308
19309 if (Platform::isWindows()) {
19310 if ($cacheDir = getenv('LOCALAPPDATA')) {
19311 $cacheDir .= '/Composer';
19312 } else {
19313 $cacheDir = $home . '/cache';
19314 }
19315
19316 return rtrim(strtr($cacheDir, '\\', '/'), '/');
19317 }
19318
19319 $userDir = self::getUserDir();
19320 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
19321 return $home . '/cache';
19322 }
19323
19324 if (self::useXdg()) {
19325 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
19326
19327 return $xdgCache . '/composer';
19328 }
19329
19330 return $home . '/cache';
19331 }
19332
19333
19334
19335
19336
19337 protected static function getDataDir($home)
19338 {
19339 $homeEnv = getenv('COMPOSER_HOME');
19340 if ($homeEnv) {
19341 return $homeEnv;
19342 }
19343
19344 if (Platform::isWindows()) {
19345 return strtr($home, '\\', '/');
19346 }
19347
19348 $userDir = self::getUserDir();
19349 if ($home !== $userDir . '/.composer' && self::useXdg()) {
19350 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
19351
19352 return $xdgData . '/composer';
19353 }
19354
19355 return $home;
19356 }
19357
19358
19359
19360
19361
19362 public static function createConfig(IOInterface $io = null, $cwd = null)
19363 {
19364 $cwd = $cwd ?: getcwd();
19365
19366 $config = new Config(true, $cwd);
19367
19368
19369  $home = self::getHomeDir();
19370 $config->merge(array('config' => array(
19371 'home' => $home,
19372 'cache-dir' => self::getCacheDir($home),
19373 'data-dir' => self::getDataDir($home),
19374 )));
19375
19376
19377  $file = new JsonFile($config->get('home').'/config.json');
19378 if ($file->exists()) {
19379 if ($io && $io->isDebug()) {
19380 $io->writeError('Loading config file ' . $file->getPath());
19381 }
19382 $config->merge($file->read());
19383 }
19384 $config->setConfigSource(new JsonConfigSource($file));
19385
19386 $htaccessProtect = (bool) $config->get('htaccess-protect');
19387 if ($htaccessProtect) {
19388
19389  
19390  
19391  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
19392 foreach ($dirs as $dir) {
19393 if (!file_exists($dir . '/.htaccess')) {
19394 if (!is_dir($dir)) {
19395 Silencer::call('mkdir', $dir, 0777, true);
19396 }
19397 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
19398 }
19399 }
19400 }
19401
19402
19403  $file = new JsonFile($config->get('home').'/auth.json');
19404 if ($file->exists()) {
19405 if ($io && $io->isDebug()) {
19406 $io->writeError('Loading config file ' . $file->getPath());
19407 }
19408 $config->merge(array('config' => $file->read()));
19409 }
19410 $config->setAuthConfigSource(new JsonConfigSource($file, true));
19411
19412
19413  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
19414 $authData = json_decode($composerAuthEnv, true);
19415
19416 if (null === $authData) {
19417 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
19418 }
19419
19420 if ($io && $io->isDebug()) {
19421 $io->writeError('Loading auth config from COMPOSER_AUTH');
19422 }
19423 $config->merge(array('config' => $authData));
19424 }
19425
19426 return $config;
19427 }
19428
19429 public static function getComposerFile()
19430 {
19431 return trim(getenv('COMPOSER')) ?: './composer.json';
19432 }
19433
19434 public static function createAdditionalStyles()
19435 {
19436 return array(
19437 'highlight' => new OutputFormatterStyle('red'),
19438 'warning' => new OutputFormatterStyle('black', 'yellow'),
19439 );
19440 }
19441
19442
19443
19444
19445
19446
19447 public static function createOutput()
19448 {
19449 $styles = self::createAdditionalStyles();
19450 $formatter = new OutputFormatter(false, $styles);
19451
19452 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
19453 }
19454
19455
19456
19457
19458 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
19459 {
19460 return RepositoryFactory::defaultRepos($io, $config, $rm);
19461 }
19462
19463
19464
19465
19466
19467
19468
19469
19470
19471
19472
19473
19474
19475 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
19476 {
19477 $cwd = $cwd ?: getcwd();
19478
19479
19480  if (null === $localConfig) {
19481 $localConfig = static::getComposerFile();
19482 }
19483
19484 if (is_string($localConfig)) {
19485 $composerFile = $localConfig;
19486
19487 $file = new JsonFile($localConfig, null, $io);
19488
19489 if (!$file->exists()) {
19490 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
19491 $message = 'Composer could not find a composer.json file in '.$cwd;
19492 } else {
19493 $message = 'Composer could not find the config file: '.$localConfig;
19494 }
19495 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
19496 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
19497 }
19498
19499 $file->validateSchema(JsonFile::LAX_SCHEMA);
19500 $jsonParser = new JsonParser;
19501 try {
19502 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
19503 } catch (DuplicateKeyException $e) {
19504 $details = $e->getDetails();
19505 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
19506 }
19507
19508 $localConfig = $file->read();
19509 }
19510
19511
19512  $config = static::createConfig($io, $cwd);
19513 $config->merge($localConfig);
19514 if (isset($composerFile)) {
19515 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
19516 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
19517
19518 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
19519 if ($localAuthFile->exists()) {
19520 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
19521 $config->merge(array('config' => $localAuthFile->read()));
19522 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
19523 }
19524 }
19525
19526 $vendorDir = $config->get('vendor-dir');
19527
19528
19529  $composer = new Composer();
19530 $composer->setConfig($config);
19531
19532 if ($fullLoad) {
19533
19534  $io->loadConfiguration($config);
19535 }
19536
19537 $rfs = self::createRemoteFilesystem($io, $config);
19538
19539
19540  $dispatcher = new EventDispatcher($composer, $io);
19541 $composer->setEventDispatcher($dispatcher);
19542
19543
19544  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
19545 $composer->setRepositoryManager($rm);
19546
19547
19548  $this->addLocalRepository($io, $rm, $vendorDir);
19549
19550
19551  
19552  if (!$fullLoad && !isset($localConfig['version'])) {
19553 $localConfig['version'] = '1.0.0';
19554 }
19555
19556
19557  $parser = new VersionParser;
19558 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
19559 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
19560 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
19561 $composer->setPackage($package);
19562
19563
19564  $im = $this->createInstallationManager();
19565 $composer->setInstallationManager($im);
19566
19567 if ($fullLoad) {
19568
19569  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
19570 $composer->setDownloadManager($dm);
19571
19572
19573  $generator = new AutoloadGenerator($dispatcher, $io);
19574 $composer->setAutoloadGenerator($generator);
19575
19576
19577  $am = $this->createArchiveManager($config, $dm);
19578 $composer->setArchiveManager($am);
19579 }
19580
19581
19582  $this->createDefaultInstallers($im, $composer, $io);
19583
19584 if ($fullLoad) {
19585 $globalComposer = null;
19586 if (realpath($config->get('home')) !== $cwd) {
19587 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
19588 }
19589
19590 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
19591 $composer->setPluginManager($pm);
19592
19593 $pm->loadInstalledPlugins();
19594 }
19595
19596
19597  if ($fullLoad && isset($composerFile)) {
19598 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
19599 ? substr($composerFile, 0, -4).'lock'
19600 : $composerFile . '.lock';
19601
19602 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
19603 $composer->setLocker($locker);
19604 }
19605
19606 if ($fullLoad) {
19607 $initEvent = new Event(PluginEvents::INIT);
19608 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
19609
19610
19611  
19612  if ($rm->getLocalRepository()) {
19613 $this->purgePackages($rm->getLocalRepository(), $im);
19614 }
19615 }
19616
19617 return $composer;
19618 }
19619
19620
19621
19622
19623
19624
19625 public static function createGlobal(IOInterface $io, $disablePlugins = false)
19626 {
19627 $factory = new static();
19628
19629 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
19630 }
19631
19632
19633
19634
19635
19636 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
19637 {
19638 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
19639 }
19640
19641
19642
19643
19644
19645 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
19646 {
19647 $composer = null;
19648 try {
19649 $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
19650 } catch (\Exception $e) {
19651 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
19652 }
19653
19654 return $composer;
19655 }
19656
19657
19658
19659
19660
19661
19662
19663 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
19664 {
19665 $cache = null;
19666 if ($config->get('cache-files-ttl') > 0) {
19667 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
19668 }
19669
19670 $dm = new Downloader\DownloadManager($io);
19671 switch ($preferred = $config->get('preferred-install')) {
19672 case 'dist':
19673 $dm->setPreferDist(true);
19674 break;
19675 case 'source':
19676 $dm->setPreferSource(true);
19677 break;
19678 case 'auto':
19679 default:
19680
19681  break;
19682 }
19683
19684 if (is_array($preferred)) {
19685 $dm->setPreferences($preferred);
19686 }
19687
19688 $executor = new ProcessExecutor($io);
19689 $fs = new Filesystem($executor);
19690
19691 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
19692 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
19693 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
19694 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
19695 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
19696 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19697 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19698 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19699 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19700 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
19701 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19702 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19703 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
19704
19705 return $dm;
19706 }
19707
19708
19709
19710
19711
19712
19713 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
19714 {
19715 if (null === $dm) {
19716 $io = new IO\NullIO();
19717 $io->loadConfiguration($config);
19718 $dm = $this->createDownloadManager($io, $config);
19719 }
19720
19721 $am = new Archiver\ArchiveManager($dm);
19722 $am->addArchiver(new Archiver\ZipArchiver);
19723 $am->addArchiver(new Archiver\PharArchiver);
19724
19725 return $am;
19726 }
19727
19728
19729
19730
19731
19732
19733
19734
19735 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
19736 {
19737 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
19738 }
19739
19740
19741
19742
19743 protected function createInstallationManager()
19744 {
19745 return new Installer\InstallationManager();
19746 }
19747
19748
19749
19750
19751
19752
19753 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
19754 {
19755 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
19756 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
19757 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
19758 $im->addInstaller(new Installer\MetapackageInstaller($io));
19759 }
19760
19761
19762
19763
19764
19765 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
19766 {
19767 foreach ($repo->getPackages() as $package) {
19768 if (!$im->isPackageInstalled($repo, $package)) {
19769 $repo->removePackage($package);
19770 }
19771 }
19772 }
19773
19774
19775
19776
19777
19778
19779
19780
19781 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
19782 {
19783 $factory = new static();
19784
19785 return $factory->createComposer($io, $config, $disablePlugins);
19786 }
19787
19788
19789
19790
19791
19792
19793
19794 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
19795 {
19796 static $warned = false;
19797 $disableTls = false;
19798 if ($config && $config->get('disable-tls') === true) {
19799 if (!$warned) {
19800 $io->writeError('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
19801 }
19802 $warned = true;
19803 $disableTls = true;
19804 } elseif (!extension_loaded('openssl')) {
19805 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
19806 . '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.');
19807 }
19808 $remoteFilesystemOptions = array();
19809 if ($disableTls === false) {
19810 if ($config && $config->get('cafile')) {
19811 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
19812 }
19813 if ($config && $config->get('capath')) {
19814 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
19815 }
19816 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
19817 }
19818 try {
19819 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
19820 } catch (TransportException $e) {
19821 if (false !== strpos($e->getMessage(), 'cafile')) {
19822 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
19823 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
19824 if (PHP_VERSION_ID < 50600) {
19825 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
19826 }
19827 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
19828 }
19829 throw $e;
19830 }
19831
19832 return $remoteFilesystem;
19833 }
19834
19835
19836
19837
19838 private static function useXdg()
19839 {
19840 foreach (array_keys($_SERVER) as $key) {
19841 if (substr($key, 0, 4) === 'XDG_') {
19842 return true;
19843 }
19844 }
19845
19846 return false;
19847 }
19848
19849
19850
19851
19852
19853 private static function getUserDir()
19854 {
19855 $home = getenv('HOME');
19856 if (!$home) {
19857 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
19858 }
19859
19860 return rtrim(strtr($home, '\\', '/'), '/');
19861 }
19862 }
19863 <?php
19864
19865
19866
19867
19868
19869
19870
19871
19872
19873
19874
19875 namespace Composer\IO;
19876
19877 use Composer\Config;
19878 use Composer\Util\ProcessExecutor;
19879 use Psr\Log\LoggerInterface;
19880 use Psr\Log\LogLevel;
19881
19882 abstract class BaseIO implements IOInterface, LoggerInterface
19883 {
19884 protected $authentications = array();
19885
19886
19887
19888
19889 public function getAuthentications()
19890 {
19891 return $this->authentications;
19892 }
19893
19894
19895
19896
19897 public function resetAuthentications()
19898 {
19899 $this->authentications = array();
19900 }
19901
19902
19903
19904
19905 public function hasAuthentication($repositoryName)
19906 {
19907 return isset($this->authentications[$repositoryName]);
19908 }
19909
19910
19911
19912
19913 public function getAuthentication($repositoryName)
19914 {
19915 if (isset($this->authentications[$repositoryName])) {
19916 return $this->authentications[$repositoryName];
19917 }
19918
19919 return array('username' => null, 'password' => null);
19920 }
19921
19922
19923
19924
19925 public function setAuthentication($repositoryName, $username, $password = null)
19926 {
19927 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
19928 }
19929
19930
19931
19932
19933
19934
19935
19936
19937 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
19938 {
19939 if ($this->hasAuthentication($repositoryName)) {
19940 $auth = $this->getAuthentication($repositoryName);
19941 if ($auth['username'] === $username && $auth['password'] === $password) {
19942 return;
19943 }
19944
19945 $this->writeError(
19946 sprintf(
19947 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
19948 $repositoryName
19949 )
19950 );
19951 }
19952 $this->setAuthentication($repositoryName, $username, $password);
19953 }
19954
19955
19956
19957
19958 public function loadConfiguration(Config $config)
19959 {
19960 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
19961 $githubOauth = $config->get('github-oauth') ?: array();
19962 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
19963 $gitlabToken = $config->get('gitlab-token') ?: array();
19964 $httpBasic = $config->get('http-basic') ?: array();
19965
19966
19967
19968 foreach ($bitbucketOauth as $domain => $cred) {
19969 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
19970 }
19971
19972 foreach ($githubOauth as $domain => $token) {
19973 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
19974 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
19975 }
19976 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
19977 }
19978
19979 foreach ($gitlabOauth as $domain => $token) {
19980 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
19981 }
19982
19983 foreach ($gitlabToken as $domain => $token) {
19984 $this->checkAndSetAuthentication($domain, $token, 'private-token');
19985 }
19986
19987
19988  foreach ($httpBasic as $domain => $cred) {
19989 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
19990 }
19991
19992
19993  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
19994 }
19995
19996
19997
19998
19999
20000
20001
20002
20003 public function emergency($message, array $context = array())
20004 {
20005 return $this->log(LogLevel::EMERGENCY, $message, $context);
20006 }
20007
20008
20009
20010
20011
20012
20013
20014
20015
20016
20017
20018 public function alert($message, array $context = array())
20019 {
20020 return $this->log(LogLevel::ALERT, $message, $context);
20021 }
20022
20023
20024
20025
20026
20027
20028
20029
20030
20031
20032 public function critical($message, array $context = array())
20033 {
20034 return $this->log(LogLevel::CRITICAL, $message, $context);
20035 }
20036
20037
20038
20039
20040
20041
20042
20043
20044
20045 public function error($message, array $context = array())
20046 {
20047 return $this->log(LogLevel::ERROR, $message, $context);
20048 }
20049
20050
20051
20052
20053
20054
20055
20056
20057
20058
20059
20060 public function warning($message, array $context = array())
20061 {
20062 return $this->log(LogLevel::WARNING, $message, $context);
20063 }
20064
20065
20066
20067
20068
20069
20070
20071
20072 public function notice($message, array $context = array())
20073 {
20074 return $this->log(LogLevel::NOTICE, $message, $context);
20075 }
20076
20077
20078
20079
20080
20081
20082
20083
20084
20085
20086 public function info($message, array $context = array())
20087 {
20088 return $this->log(LogLevel::INFO, $message, $context);
20089 }
20090
20091
20092
20093
20094
20095
20096
20097
20098 public function debug($message, array $context = array())
20099 {
20100 return $this->log(LogLevel::DEBUG, $message, $context);
20101 }
20102
20103
20104
20105
20106
20107
20108
20109
20110
20111 public function log($level, $message, array $context = array())
20112 {
20113 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
20114 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
20115 } elseif ($level === LogLevel::WARNING) {
20116 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
20117 } elseif ($level === LogLevel::NOTICE) {
20118 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
20119 } elseif ($level === LogLevel::INFO) {
20120 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
20121 } else {
20122 $this->writeError($message, true, self::DEBUG);
20123 }
20124 }
20125 }
20126 <?php
20127
20128
20129
20130
20131
20132
20133
20134
20135
20136
20137
20138 namespace Composer\IO;
20139
20140 use Symfony\Component\Console\Helper\QuestionHelper;
20141 use Symfony\Component\Console\Output\StreamOutput;
20142 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
20143 use Symfony\Component\Console\Input\StreamableInputInterface;
20144 use Symfony\Component\Console\Input\StringInput;
20145 use Symfony\Component\Console\Helper\HelperSet;
20146
20147
20148
20149
20150 class BufferIO extends ConsoleIO
20151 {
20152
20153
20154
20155
20156
20157 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
20158 {
20159 $input = new StringInput($input);
20160 $input->setInteractive(false);
20161
20162 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
20163
20164 parent::__construct($input, $output, new HelperSet(array(
20165 new QuestionHelper(),
20166 )));
20167 }
20168
20169 public function getOutput()
20170 {
20171 fseek($this->output->getStream(), 0);
20172
20173 $output = stream_get_contents($this->output->getStream());
20174
20175 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
20176 $pre = strip_tags($matches[1]);
20177
20178 if (strlen($pre) === strlen($matches[2])) {
20179 return '';
20180 }
20181
20182
20183  return rtrim($matches[1])."\n";
20184 }, $output);
20185
20186 return $output;
20187 }
20188
20189 public function setUserInputs(array $inputs)
20190 {
20191 if (!$this->input instanceof StreamableInputInterface) {
20192 throw new \RuntimeException('Setting the user inputs requires at least the version 3.2 of the symfony/console component.');
20193 }
20194
20195 $this->input->setStream($this->createStream($inputs));
20196 $this->input->setInteractive(true);
20197 }
20198
20199 private function createStream(array $inputs)
20200 {
20201 $stream = fopen('php://memory', 'r+', false);
20202
20203 foreach ($inputs as $input) {
20204 fwrite($stream, $input.PHP_EOL);
20205 }
20206
20207 rewind($stream);
20208
20209 return $stream;
20210 }
20211 }
20212 <?php
20213
20214
20215
20216
20217
20218
20219
20220
20221
20222
20223
20224 namespace Composer\IO;
20225
20226 use Composer\Question\StrictConfirmationQuestion;
20227 use Symfony\Component\Console\Helper\HelperSet;
20228 use Symfony\Component\Console\Input\InputInterface;
20229 use Symfony\Component\Console\Output\ConsoleOutputInterface;
20230 use Symfony\Component\Console\Output\OutputInterface;
20231 use Symfony\Component\Console\Question\ChoiceQuestion;
20232 use Symfony\Component\Console\Question\Question;
20233
20234
20235
20236
20237
20238
20239
20240 class ConsoleIO extends BaseIO
20241 {
20242
20243 protected $input;
20244
20245 protected $output;
20246
20247 protected $helperSet;
20248
20249 protected $lastMessage;
20250
20251 protected $lastMessageErr;
20252
20253
20254 private $startTime;
20255
20256 private $verbosityMap;
20257
20258
20259
20260
20261
20262
20263
20264
20265 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
20266 {
20267 $this->input = $input;
20268 $this->output = $output;
20269 $this->helperSet = $helperSet;
20270 $this->verbosityMap = array(
20271 self::QUIET => OutputInterface::VERBOSITY_QUIET,
20272 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
20273 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
20274 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
20275 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
20276 );
20277 }
20278
20279
20280
20281
20282 public function enableDebugging($startTime)
20283 {
20284 $this->startTime = $startTime;
20285 }
20286
20287
20288
20289
20290 public function isInteractive()
20291 {
20292 return $this->input->isInteractive();
20293 }
20294
20295
20296
20297
20298 public function isDecorated()
20299 {
20300 return $this->output->isDecorated();
20301 }
20302
20303
20304
20305
20306 public function isVerbose()
20307 {
20308 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
20309 }
20310
20311
20312
20313
20314 public function isVeryVerbose()
20315 {
20316 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
20317 }
20318
20319
20320
20321
20322 public function isDebug()
20323 {
20324 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
20325 }
20326
20327
20328
20329
20330 public function write($messages, $newline = true, $verbosity = self::NORMAL)
20331 {
20332 $this->doWrite($messages, $newline, false, $verbosity);
20333 }
20334
20335
20336
20337
20338 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
20339 {
20340 $this->doWrite($messages, $newline, true, $verbosity);
20341 }
20342
20343
20344
20345
20346
20347
20348
20349 private function doWrite($messages, $newline, $stderr, $verbosity)
20350 {
20351 $sfVerbosity = $this->verbosityMap[$verbosity];
20352 if ($sfVerbosity > $this->output->getVerbosity()) {
20353 return;
20354 }
20355
20356
20357  
20358  
20359  if (OutputInterface::VERBOSITY_QUIET === 0) {
20360 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
20361 }
20362
20363 if (null !== $this->startTime) {
20364 $memoryUsage = memory_get_usage() / 1024 / 1024;
20365 $timeSpent = microtime(true) - $this->startTime;
20366 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
20367 return sprintf('[%.1fMiB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
20368 }, (array) $messages);
20369 }
20370
20371 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
20372 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
20373 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
20374
20375 return;
20376 }
20377
20378 $this->output->write($messages, $newline, $sfVerbosity);
20379 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
20380 }
20381
20382
20383
20384
20385 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
20386 {
20387 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
20388 }
20389
20390
20391
20392
20393 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
20394 {
20395 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
20396 }
20397
20398
20399
20400
20401
20402
20403
20404
20405 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
20406 {
20407
20408  $messages = implode($newline ? "\n" : '', (array) $messages);
20409
20410
20411  if (!isset($size)) {
20412
20413  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
20414 }
20415
20416  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
20417
20418
20419  $this->doWrite($messages, false, $stderr, $verbosity);
20420
20421
20422  
20423  
20424  $fill = $size - strlen(strip_tags($messages));
20425 if ($fill > 0) {
20426
20427  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
20428
20429  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
20430 }
20431
20432 if ($newline) {
20433 $this->doWrite('', true, $stderr, $verbosity);
20434 }
20435
20436 if ($stderr) {
20437 $this->lastMessageErr = $messages;
20438 } else {
20439 $this->lastMessage = $messages;
20440 }
20441 }
20442
20443
20444
20445
20446 public function ask($question, $default = null)
20447 {
20448
20449 $helper = $this->helperSet->get('question');
20450 $question = new Question($question, $default);
20451
20452 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20453 }
20454
20455
20456
20457
20458 public function askConfirmation($question, $default = true)
20459 {
20460
20461 $helper = $this->helperSet->get('question');
20462 $question = new StrictConfirmationQuestion($question, $default);
20463
20464 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20465 }
20466
20467
20468
20469
20470 public function askAndValidate($question, $validator, $attempts = null, $default = null)
20471 {
20472
20473 $helper = $this->helperSet->get('question');
20474 $question = new Question($question, $default);
20475 $question->setValidator($validator);
20476 $question->setMaxAttempts($attempts);
20477
20478 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20479 }
20480
20481
20482
20483
20484 public function askAndHideAnswer($question)
20485 {
20486
20487 $helper = $this->helperSet->get('question');
20488 $question = new Question($question);
20489 $question->setHidden(true);
20490
20491 return $helper->ask($this->input, $this->getErrorOutput(), $question);
20492 }
20493
20494
20495
20496
20497 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
20498 {
20499
20500 $helper = $this->helperSet->get('question');
20501 $question = new ChoiceQuestion($question, $choices, $default);
20502 $question->setMaxAttempts($attempts ?: null); 
20503  $question->setErrorMessage($errorMessage);
20504 $question->setMultiselect($multiselect);
20505
20506 $result = $helper->ask($this->input, $this->getErrorOutput(), $question);
20507
20508 if (!is_array($result)) {
20509 return (string) array_search($result, $choices, true);
20510 }
20511
20512 $results = array();
20513 foreach ($choices as $index => $choice) {
20514 if (in_array($choice, $result, true)) {
20515 $results[] = (string) $index;
20516 }
20517 }
20518
20519 return $results;
20520 }
20521
20522
20523
20524
20525 private function getErrorOutput()
20526 {
20527 if ($this->output instanceof ConsoleOutputInterface) {
20528 return $this->output->getErrorOutput();
20529 }
20530
20531 return $this->output;
20532 }
20533 }
20534 <?php
20535
20536
20537
20538
20539
20540
20541
20542
20543
20544
20545
20546 namespace Composer\IO;
20547
20548 use Composer\Config;
20549
20550
20551
20552
20553
20554
20555 interface IOInterface
20556 {
20557 const QUIET = 1;
20558 const NORMAL = 2;
20559 const VERBOSE = 4;
20560 const VERY_VERBOSE = 8;
20561 const DEBUG = 16;
20562
20563
20564
20565
20566
20567
20568 public function isInteractive();
20569
20570
20571
20572
20573
20574
20575 public function isVerbose();
20576
20577
20578
20579
20580
20581
20582 public function isVeryVerbose();
20583
20584
20585
20586
20587
20588
20589 public function isDebug();
20590
20591
20592
20593
20594
20595
20596 public function isDecorated();
20597
20598
20599
20600
20601
20602
20603
20604
20605 public function write($messages, $newline = true, $verbosity = self::NORMAL);
20606
20607
20608
20609
20610
20611
20612
20613
20614 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
20615
20616
20617
20618
20619
20620
20621
20622
20623
20624 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
20625
20626
20627
20628
20629
20630
20631
20632
20633
20634 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
20635
20636
20637
20638
20639
20640
20641
20642
20643
20644
20645 public function ask($question, $default = null);
20646
20647
20648
20649
20650
20651
20652
20653
20654
20655
20656
20657 public function askConfirmation($question, $default = true);
20658
20659
20660
20661
20662
20663
20664
20665
20666
20667
20668
20669
20670
20671
20672
20673
20674 public function askAndValidate($question, $validator, $attempts = null, $default = null);
20675
20676
20677
20678
20679
20680
20681
20682
20683 public function askAndHideAnswer($question);
20684
20685
20686
20687
20688
20689
20690
20691
20692
20693
20694
20695
20696
20697
20698 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
20699
20700
20701
20702
20703
20704
20705 public function getAuthentications();
20706
20707
20708
20709
20710
20711
20712
20713
20714 public function hasAuthentication($repositoryName);
20715
20716
20717
20718
20719
20720
20721
20722
20723 public function getAuthentication($repositoryName);
20724
20725
20726
20727
20728
20729
20730
20731
20732 public function setAuthentication($repositoryName, $username, $password = null);
20733
20734
20735
20736
20737
20738
20739 public function loadConfiguration(Config $config);
20740 }
20741 <?php
20742
20743
20744
20745
20746
20747
20748
20749
20750
20751
20752
20753 namespace Composer\IO;
20754
20755
20756
20757
20758
20759
20760 class NullIO extends BaseIO
20761 {
20762
20763
20764
20765 public function isInteractive()
20766 {
20767 return false;
20768 }
20769
20770
20771
20772
20773 public function isVerbose()
20774 {
20775 return false;
20776 }
20777
20778
20779
20780
20781 public function isVeryVerbose()
20782 {
20783 return false;
20784 }
20785
20786
20787
20788
20789 public function isDebug()
20790 {
20791 return false;
20792 }
20793
20794
20795
20796
20797 public function isDecorated()
20798 {
20799 return false;
20800 }
20801
20802
20803
20804
20805 public function write($messages, $newline = true, $verbosity = self::NORMAL)
20806 {
20807 }
20808
20809
20810
20811
20812 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
20813 {
20814 }
20815
20816
20817
20818
20819 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
20820 {
20821 }
20822
20823
20824
20825
20826 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
20827 {
20828 }
20829
20830
20831
20832
20833 public function ask($question, $default = null)
20834 {
20835 return $default;
20836 }
20837
20838
20839
20840
20841 public function askConfirmation($question, $default = true)
20842 {
20843 return $default;
20844 }
20845
20846
20847
20848
20849 public function askAndValidate($question, $validator, $attempts = false, $default = null)
20850 {
20851 return $default;
20852 }
20853
20854
20855
20856
20857 public function askAndHideAnswer($question)
20858 {
20859 return null;
20860 }
20861
20862
20863
20864
20865 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
20866 {
20867 return $default;
20868 }
20869 }
20870 <?php
20871
20872
20873
20874
20875
20876
20877
20878
20879
20880
20881
20882 namespace Composer;
20883
20884 use Composer\Autoload\AutoloadGenerator;
20885 use Composer\DependencyResolver\DefaultPolicy;
20886 use Composer\DependencyResolver\Operation\UpdateOperation;
20887 use Composer\DependencyResolver\Operation\InstallOperation;
20888 use Composer\DependencyResolver\Operation\UninstallOperation;
20889 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
20890 use Composer\DependencyResolver\Operation\OperationInterface;
20891 use Composer\DependencyResolver\PolicyInterface;
20892 use Composer\DependencyResolver\Pool;
20893 use Composer\DependencyResolver\Request;
20894 use Composer\DependencyResolver\Rule;
20895 use Composer\DependencyResolver\Solver;
20896 use Composer\DependencyResolver\SolverProblemsException;
20897 use Composer\Downloader\DownloadManager;
20898 use Composer\EventDispatcher\EventDispatcher;
20899 use Composer\Installer\InstallationManager;
20900 use Composer\Installer\InstallerEvents;
20901 use Composer\Installer\NoopInstaller;
20902 use Composer\Installer\SuggestedPackagesReporter;
20903 use Composer\IO\IOInterface;
20904 use Composer\Package\AliasPackage;
20905 use Composer\Package\BasePackage;
20906 use Composer\Package\CompletePackage;
20907 use Composer\Package\Link;
20908 use Composer\Package\Loader\ArrayLoader;
20909 use Composer\Package\Dumper\ArrayDumper;
20910 use Composer\Semver\Constraint\Constraint;
20911 use Composer\Package\Locker;
20912 use Composer\Package\PackageInterface;
20913 use Composer\Package\RootPackageInterface;
20914 use Composer\Repository\CompositeRepository;
20915 use Composer\Repository\InstalledArrayRepository;
20916 use Composer\Repository\PlatformRepository;
20917 use Composer\Repository\RepositoryInterface;
20918 use Composer\Repository\RepositoryManager;
20919 use Composer\Repository\WritableRepositoryInterface;
20920 use Composer\Script\ScriptEvents;
20921
20922
20923
20924
20925
20926
20927
20928 class Installer
20929 {
20930
20931
20932
20933 protected $io;
20934
20935
20936
20937
20938 protected $config;
20939
20940
20941
20942
20943 protected $package;
20944
20945
20946
20947
20948 protected $downloadManager;
20949
20950
20951
20952
20953 protected $repositoryManager;
20954
20955
20956
20957
20958 protected $locker;
20959
20960
20961
20962
20963 protected $installationManager;
20964
20965
20966
20967
20968 protected $eventDispatcher;
20969
20970
20971
20972
20973 protected $autoloadGenerator;
20974
20975 protected $preferSource = false;
20976 protected $preferDist = false;
20977 protected $optimizeAutoloader = false;
20978 protected $classMapAuthoritative = false;
20979 protected $apcuAutoloader = false;
20980 protected $devMode = false;
20981 protected $dryRun = false;
20982 protected $verbose = false;
20983 protected $update = false;
20984 protected $dumpAutoloader = true;
20985 protected $runScripts = true;
20986 protected $ignorePlatformReqs = false;
20987 protected $preferStable = false;
20988 protected $preferLowest = false;
20989 protected $skipSuggest = false;
20990 protected $writeLock = true;
20991 protected $executeOperations = true;
20992
20993
20994
20995
20996
20997
20998 protected $updateWhitelist = null;
20999 protected $whitelistDependencies = false; 
21000  protected $whitelistAllDependencies = false;
21001
21002
21003
21004
21005 protected $suggestedPackagesReporter;
21006
21007
21008
21009
21010 protected $additionalInstalledRepository;
21011
21012
21013
21014
21015
21016
21017
21018
21019
21020
21021
21022
21023
21024
21025 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
21026 {
21027 $this->io = $io;
21028 $this->config = $config;
21029 $this->package = $package;
21030 $this->downloadManager = $downloadManager;
21031 $this->repositoryManager = $repositoryManager;
21032 $this->locker = $locker;
21033 $this->installationManager = $installationManager;
21034 $this->eventDispatcher = $eventDispatcher;
21035 $this->autoloadGenerator = $autoloadGenerator;
21036 }
21037
21038
21039
21040
21041
21042
21043
21044 public function run()
21045 {
21046
21047  
21048  
21049  
21050  gc_collect_cycles();
21051 gc_disable();
21052
21053
21054  if (!$this->update && !$this->locker->isLocked()) {
21055 $this->update = true;
21056 }
21057
21058 if ($this->dryRun) {
21059 $this->verbose = true;
21060 $this->runScripts = false;
21061 $this->executeOperations = false;
21062 $this->writeLock = false;
21063 $this->dumpAutoloader = false;
21064 $this->installationManager->addInstaller(new NoopInstaller);
21065 $this->mockLocalRepositories($this->repositoryManager);
21066 }
21067
21068 if ($this->runScripts) {
21069 $devMode = (int) $this->devMode;
21070 putenv("COMPOSER_DEV_MODE=$devMode");
21071
21072
21073  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
21074 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
21075 }
21076
21077 $this->downloadManager->setPreferSource($this->preferSource);
21078 $this->downloadManager->setPreferDist($this->preferDist);
21079
21080
21081  $localRepo = $this->repositoryManager->getLocalRepository();
21082 if ($this->update) {
21083 $platformOverrides = $this->config->get('platform') ?: array();
21084 } else {
21085 $platformOverrides = $this->locker->getPlatformOverrides();
21086 }
21087 $platformRepo = new PlatformRepository(array(), $platformOverrides);
21088 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
21089
21090 $aliases = $this->getRootAliases();
21091 $this->aliasPlatformPackages($platformRepo, $aliases);
21092
21093 if (!$this->suggestedPackagesReporter) {
21094 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
21095 }
21096
21097 try {
21098 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
21099 if ($res !== 0) {
21100 return $res;
21101 }
21102 } catch (\Exception $e) {
21103 if ($this->executeOperations) {
21104 $this->installationManager->notifyInstalls($this->io);
21105 }
21106
21107 throw $e;
21108 }
21109 if ($this->executeOperations) {
21110 $this->installationManager->notifyInstalls($this->io);
21111 }
21112
21113
21114  if ($this->devMode && !$this->skipSuggest) {
21115 $this->suggestedPackagesReporter->output($installedRepo);
21116 }
21117
21118
21119  foreach ($localRepo->getPackages() as $package) {
21120 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
21121 continue;
21122 }
21123
21124 $replacement = is_string($package->getReplacementPackage())
21125 ? 'Use ' . $package->getReplacementPackage() . ' instead'
21126 : 'No replacement was suggested';
21127
21128 $this->io->writeError(
21129 sprintf(
21130 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
21131 $package->getPrettyName(),
21132 $replacement
21133 )
21134 );
21135 }
21136
21137
21138  if ($this->update && $this->writeLock) {
21139 $localRepo->reload();
21140
21141 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
21142 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
21143
21144 $updatedLock = $this->locker->setLockData(
21145 array_diff($localRepo->getCanonicalPackages(), $devPackages),
21146 $devPackages,
21147 $platformReqs,
21148 $platformDevReqs,
21149 $aliases,
21150 $this->package->getMinimumStability(),
21151 $this->package->getStabilityFlags(),
21152 $this->preferStable || $this->package->getPreferStable(),
21153 $this->preferLowest,
21154 $this->config->get('platform') ?: array()
21155 );
21156 if ($updatedLock) {
21157 $this->io->writeError('<info>Writing lock file</info>');
21158 }
21159 }
21160
21161 if ($this->dumpAutoloader) {
21162
21163  if ($this->optimizeAutoloader) {
21164 $this->io->writeError('<info>Generating optimized autoload files</info>');
21165 } else {
21166 $this->io->writeError('<info>Generating autoload files</info>');
21167 }
21168
21169 $this->autoloadGenerator->setDevMode($this->devMode);
21170 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
21171 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
21172 $this->autoloadGenerator->setRunScripts($this->runScripts);
21173 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
21174 }
21175
21176 if ($this->executeOperations) {
21177
21178  foreach ($localRepo->getPackages() as $package) {
21179 $this->installationManager->ensureBinariesPresence($package);
21180 }
21181
21182 $vendorDir = $this->config->get('vendor-dir');
21183 if (is_dir($vendorDir)) {
21184
21185  
21186  @touch($vendorDir);
21187 }
21188 }
21189
21190 if ($this->runScripts) {
21191
21192  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
21193 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
21194 }
21195
21196
21197  if (!defined('HHVM_VERSION')) {
21198 gc_enable();
21199 }
21200
21201 return 0;
21202 }
21203
21204
21205
21206
21207
21208
21209
21210
21211 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
21212 {
21213
21214  $lockedRepository = null;
21215 $repositories = null;
21216
21217
21218  
21219  
21220  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
21221 try {
21222 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
21223 } catch (\RuntimeException $e) {
21224
21225  if ($this->package->getDevRequires()) {
21226 throw $e;
21227 }
21228
21229  $lockedRepository = $this->locker->getLockedRepository();
21230 }
21231 }
21232
21233 $this->whitelistUpdateDependencies(
21234 $lockedRepository ?: $localRepo,
21235 $this->package->getRequires(),
21236 $this->package->getDevRequires()
21237 );
21238
21239 $this->io->writeError('<info>Loading composer repositories with package information</info>');
21240
21241
21242  $policy = $this->createPolicy();
21243 $pool = $this->createPool($this->update ? null : $lockedRepository);
21244 $pool->addRepository($installedRepo, $aliases);
21245 if ($this->update) {
21246 $repositories = $this->repositoryManager->getRepositories();
21247 foreach ($repositories as $repository) {
21248 $pool->addRepository($repository, $aliases);
21249 }
21250 }
21251
21252  
21253  
21254  if ($lockedRepository) {
21255 $pool->addRepository($lockedRepository, $aliases);
21256 }
21257
21258
21259  $request = $this->createRequest($this->package, $platformRepo);
21260
21261 if ($this->update) {
21262
21263  $removedUnstablePackages = array();
21264 foreach ($localRepo->getPackages() as $package) {
21265 if (
21266 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
21267 && $this->installationManager->isPackageInstalled($localRepo, $package)
21268 ) {
21269 $removedUnstablePackages[$package->getName()] = true;
21270 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
21271 }
21272 }
21273
21274 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
21275
21276 $request->updateAll();
21277
21278 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
21279
21280 foreach ($links as $link) {
21281 $request->install($link->getTarget(), $link->getConstraint());
21282 }
21283
21284
21285  
21286  if ($this->updateWhitelist) {
21287 $currentPackages = $this->getCurrentPackages($installedRepo);
21288
21289
21290  $candidates = array();
21291 foreach ($links as $link) {
21292 $candidates[$link->getTarget()] = true;
21293 $rootRequires[$link->getTarget()] = $link;
21294 }
21295 foreach ($currentPackages as $package) {
21296 $candidates[$package->getName()] = true;
21297 }
21298
21299
21300  foreach ($candidates as $candidate => $dummy) {
21301 foreach ($currentPackages as $curPackage) {
21302 if ($curPackage->getName() === $candidate) {
21303 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
21304 $constraint = new Constraint('=', $curPackage->getVersion());
21305 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
21306 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
21307 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
21308 $request->install($curPackage->getName(), $constraint);
21309 }
21310 break;
21311 }
21312 }
21313 }
21314 }
21315 } else {
21316 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
21317
21318 if (!$this->locker->isFresh()) {
21319 $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. Run update to update them.</warning>', true, IOInterface::QUIET);
21320 }
21321
21322 foreach ($lockedRepository->getPackages() as $package) {
21323 $version = $package->getVersion();
21324 if (isset($aliases[$package->getName()][$version])) {
21325 $version = $aliases[$package->getName()][$version]['alias_normalized'];
21326 }
21327 $constraint = new Constraint('=', $version);
21328 $constraint->setPrettyString($package->getPrettyVersion());
21329 $request->install($package->getName(), $constraint);
21330 }
21331
21332 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
21333 $request->install($link->getTarget(), $link->getConstraint());
21334 }
21335 }
21336
21337
21338  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
21339
21340
21341  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
21342 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
21343 try {
21344 $operations = $solver->solve($request, $this->ignorePlatformReqs);
21345 $ruleSetSize = $solver->getRuleSetSize();
21346 $solver = null;
21347 } catch (SolverProblemsException $e) {
21348 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
21349 $this->io->writeError($e->getMessage());
21350 if ($this->update && !$this->devMode) {
21351 $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);
21352 }
21353
21354 return array(max(1, $e->getCode()), array());
21355 }
21356
21357
21358  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
21359
21360 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
21361
21362 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
21363 $this->io->writeError("Analyzed ".$ruleSetSize." rules to resolve dependencies", true, IOInterface::VERBOSE);
21364
21365
21366  if (!$operations) {
21367 $this->io->writeError('Nothing to install or update');
21368 }
21369
21370 $operations = $this->movePluginsToFront($operations);
21371 $operations = $this->moveUninstallsToFront($operations);
21372
21373
21374  
21375  if ($this->update) {
21376 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
21377 if (!$this->devMode) {
21378 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
21379 }
21380 } else {
21381 $devPackages = null;
21382 }
21383
21384 if ($operations) {
21385 $installs = $updates = $uninstalls = array();
21386 foreach ($operations as $operation) {
21387 if ($operation instanceof InstallOperation) {
21388 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
21389 } elseif ($operation instanceof UpdateOperation) {
21390 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
21391 } elseif ($operation instanceof UninstallOperation) {
21392 $uninstalls[] = $operation->getPackage()->getPrettyName();
21393 }
21394 }
21395
21396 $this->io->writeError(sprintf(
21397 "<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
21398 count($installs),
21399 1 === count($installs) ? '' : 's',
21400 count($updates),
21401 1 === count($updates) ? '' : 's',
21402 count($uninstalls),
21403 1 === count($uninstalls) ? '' : 's'
21404 ));
21405 if ($installs) {
21406 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
21407 }
21408 if ($updates) {
21409 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
21410 }
21411 if ($uninstalls) {
21412 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
21413 }
21414 }
21415
21416 foreach ($operations as $operation) {
21417
21418  $jobType = $operation->getJobType();
21419 if ('install' === $jobType) {
21420 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
21421 }
21422
21423
21424  if ($this->update) {
21425 $package = null;
21426 if ('update' === $jobType) {
21427 $package = $operation->getTargetPackage();
21428 } elseif ('install' === $jobType) {
21429 $package = $operation->getPackage();
21430 }
21431 if ($package && $package->isDev()) {
21432 $references = $this->package->getReferences();
21433 if (isset($references[$package->getName()])) {
21434 $this->updateInstallReferences($package, $references[$package->getName()]);
21435 }
21436 }
21437 if ('update' === $jobType) {
21438 $targetPackage = $operation->getTargetPackage();
21439 if ($targetPackage->isDev()) {
21440 $initialPackage = $operation->getInitialPackage();
21441 if ($targetPackage->getVersion() === $initialPackage->getVersion()
21442 && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference())
21443 && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference())
21444 ) {
21445 $this->io->writeError('  - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG);
21446 $this->io->writeError('', true, IOInterface::DEBUG);
21447
21448 continue;
21449 }
21450 }
21451 }
21452 }
21453
21454 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($jobType);
21455 if (defined($event) && $this->runScripts) {
21456 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
21457 }
21458
21459
21460  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
21461 $this->io->writeError('  - ' . $operation);
21462 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
21463 $this->io->writeError('  - ' . $operation);
21464 }
21465
21466 $this->installationManager->execute($localRepo, $operation);
21467
21468
21469  if ($this->verbose && $this->io->isVeryVerbose() && in_array($jobType, array('install', 'update'))) {
21470 $reason = $operation->getReason();
21471 if ($reason instanceof Rule) {
21472 switch ($reason->getReason()) {
21473 case Rule::RULE_JOB_INSTALL:
21474 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
21475 $this->io->writeError('');
21476 break;
21477 case Rule::RULE_PACKAGE_REQUIRES:
21478 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
21479 $this->io->writeError('');
21480 break;
21481 }
21482 }
21483 }
21484
21485 if ($this->executeOperations || $this->writeLock) {
21486 $localRepo->write();
21487 }
21488
21489 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($jobType);
21490 if (defined($event) && $this->runScripts) {
21491 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
21492 }
21493 }
21494
21495 if ($this->executeOperations) {
21496
21497  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
21498 $localRepo->write();
21499 }
21500
21501 return array(0, $devPackages);
21502 }
21503
21504
21505
21506
21507
21508
21509
21510
21511
21512
21513
21514 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
21515 {
21516 if (!$this->package->getDevRequires()) {
21517 return array();
21518 }
21519
21520
21521  $tempLocalRepo = clone $localRepo;
21522 foreach ($operations as $operation) {
21523 switch ($operation->getJobType()) {
21524 case 'install':
21525 case 'markAliasInstalled':
21526 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
21527 $tempLocalRepo->addPackage(clone $operation->getPackage());
21528 }
21529 break;
21530
21531 case 'uninstall':
21532 case 'markAliasUninstalled':
21533 $tempLocalRepo->removePackage($operation->getPackage());
21534 break;
21535
21536 case 'update':
21537 $tempLocalRepo->removePackage($operation->getInitialPackage());
21538 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
21539 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
21540 }
21541 break;
21542
21543 default:
21544 throw new \LogicException('Unknown type: '.$operation->getJobType());
21545 }
21546 }
21547
21548
21549  
21550  
21551  $localRepo = new InstalledArrayRepository(array());
21552 $loader = new ArrayLoader(null, true);
21553 $dumper = new ArrayDumper();
21554 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
21555 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
21556 }
21557 unset($tempLocalRepo, $loader, $dumper);
21558
21559 $policy = $this->createPolicy();
21560 $pool = $this->createPool();
21561 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
21562 $pool->addRepository($installedRepo, $aliases);
21563
21564
21565  $request = $this->createRequest($this->package, $platformRepo);
21566 $request->updateAll();
21567 foreach ($this->package->getRequires() as $link) {
21568 $request->install($link->getTarget(), $link->getConstraint());
21569 }
21570
21571
21572  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
21573 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
21574 $ops = $solver->solve($request, $this->ignorePlatformReqs);
21575 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
21576
21577 $devPackages = array();
21578 foreach ($ops as $op) {
21579 if ($op->getJobType() === 'uninstall') {
21580 $devPackages[] = $op->getPackage();
21581 }
21582 }
21583
21584 return $devPackages;
21585 }
21586
21587
21588
21589
21590 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
21591 {
21592 $finalOps = array();
21593 $packagesToSkip = array();
21594 foreach ($devPackages as $pkg) {
21595 $packagesToSkip[$pkg->getName()] = true;
21596 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
21597 if ($installedDevPkg instanceof AliasPackage) {
21598 $finalOps[] = new MarkAliasUninstalledOperation($installedDevPkg, 'non-dev install removing it');
21599 $installedDevPkg = $installedDevPkg->getAliasOf();
21600 }
21601 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
21602 }
21603 }
21604
21605
21606  foreach ($operations as $op) {
21607 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
21608 if (isset($packagesToSkip[$package->getName()])) {
21609 continue;
21610 }
21611
21612 $finalOps[] = $op;
21613 }
21614
21615 return $finalOps;
21616 }
21617
21618
21619
21620
21621
21622
21623
21624
21625
21626
21627
21628
21629
21630
21631 private function movePluginsToFront(array $operations)
21632 {
21633 $pluginsNoDeps = array();
21634 $pluginsWithDeps = array();
21635 $pluginRequires = array();
21636
21637 foreach (array_reverse($operations, true) as $idx => $op) {
21638 if ($op instanceof InstallOperation) {
21639 $package = $op->getPackage();
21640 } elseif ($op instanceof UpdateOperation) {
21641 $package = $op->getTargetPackage();
21642 } else {
21643 continue;
21644 }
21645
21646
21647  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
21648
21649
21650  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
21651
21652  $requires = array_filter(array_keys($package->getRequires()), function ($req) {
21653 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
21654 });
21655
21656
21657  if ($isPlugin && !count($requires)) {
21658
21659  array_unshift($pluginsNoDeps, $op);
21660 } else {
21661
21662  $pluginRequires = array_merge($pluginRequires, $requires);
21663
21664  array_unshift($pluginsWithDeps, $op);
21665 }
21666
21667 unset($operations[$idx]);
21668 }
21669 }
21670
21671 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
21672 }
21673
21674
21675
21676
21677
21678
21679
21680
21681 private function moveUninstallsToFront(array $operations)
21682 {
21683 $uninstOps = array();
21684 foreach ($operations as $idx => $op) {
21685 if ($op instanceof UninstallOperation) {
21686 $uninstOps[] = $op;
21687 unset($operations[$idx]);
21688 }
21689 }
21690
21691 return array_merge($uninstOps, $operations);
21692 }
21693
21694
21695
21696
21697 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
21698 {
21699
21700  
21701  
21702  $installedRootPackage = clone $this->package;
21703 $installedRootPackage->setRequires(array());
21704 $installedRootPackage->setDevRequires(array());
21705
21706 $repos = array(
21707 $localRepo,
21708 new InstalledArrayRepository(array($installedRootPackage)),
21709 $platformRepo,
21710 );
21711 $installedRepo = new CompositeRepository($repos);
21712 if ($this->additionalInstalledRepository) {
21713 $installedRepo->addRepository($this->additionalInstalledRepository);
21714 }
21715
21716 return $installedRepo;
21717 }
21718
21719
21720
21721
21722
21723 private function createPool(RepositoryInterface $lockedRepository = null)
21724 {
21725 if ($this->update) {
21726 $minimumStability = $this->package->getMinimumStability();
21727 $stabilityFlags = $this->package->getStabilityFlags();
21728
21729 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
21730 } else {
21731 $minimumStability = $this->locker->getMinimumStability();
21732 $stabilityFlags = $this->locker->getStabilityFlags();
21733
21734 $requires = array();
21735 foreach ($lockedRepository->getPackages() as $package) {
21736 $constraint = new Constraint('=', $package->getVersion());
21737 $constraint->setPrettyString($package->getPrettyVersion());
21738 $requires[$package->getName()] = $constraint;
21739 }
21740 }
21741
21742 $rootConstraints = array();
21743 foreach ($requires as $req => $constraint) {
21744
21745  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
21746 continue;
21747 }
21748 if ($constraint instanceof Link) {
21749 $rootConstraints[$req] = $constraint->getConstraint();
21750 } else {
21751 $rootConstraints[$req] = $constraint;
21752 }
21753 }
21754
21755 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
21756 }
21757
21758
21759
21760
21761 private function createPolicy()
21762 {
21763 $preferStable = null;
21764 $preferLowest = null;
21765 if (!$this->update) {
21766 $preferStable = $this->locker->getPreferStable();
21767 $preferLowest = $this->locker->getPreferLowest();
21768 }
21769
21770  
21771  if (null === $preferStable) {
21772 $preferStable = $this->preferStable || $this->package->getPreferStable();
21773 }
21774 if (null === $preferLowest) {
21775 $preferLowest = $this->preferLowest;
21776 }
21777
21778 return new DefaultPolicy($preferStable, $preferLowest);
21779 }
21780
21781
21782
21783
21784
21785
21786 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
21787 {
21788 $request = new Request();
21789
21790 $constraint = new Constraint('=', $rootPackage->getVersion());
21791 $constraint->setPrettyString($rootPackage->getPrettyVersion());
21792 $request->install($rootPackage->getName(), $constraint);
21793
21794 $fixedPackages = $platformRepo->getPackages();
21795 if ($this->additionalInstalledRepository) {
21796 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
21797 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
21798 }
21799
21800
21801  
21802  $provided = $rootPackage->getProvides();
21803 foreach ($fixedPackages as $package) {
21804 $constraint = new Constraint('=', $package->getVersion());
21805 $constraint->setPrettyString($package->getPrettyVersion());
21806
21807
21808  if ($package->getRepository() !== $platformRepo
21809 || !isset($provided[$package->getName()])
21810 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
21811 ) {
21812 $request->fix($package->getName(), $constraint);
21813 }
21814 }
21815
21816 return $request;
21817 }
21818
21819
21820
21821
21822
21823
21824
21825
21826
21827
21828
21829
21830 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
21831 {
21832 if ($task === 'force-updates' && null === $operations) {
21833 throw new \InvalidArgumentException('Missing operations argument');
21834 }
21835 if ($task === 'force-links') {
21836 $operations = array();
21837 }
21838
21839 if ($this->update && $this->updateWhitelist) {
21840 $currentPackages = $this->getCurrentPackages($installedRepo);
21841 }
21842
21843 foreach ($localRepo->getCanonicalPackages() as $package) {
21844
21845  if (!$package->isDev()) {
21846 continue;
21847 }
21848
21849
21850  foreach ($operations as $operation) {
21851 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
21852 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
21853 ) {
21854 continue 2;
21855 }
21856 }
21857
21858 if ($this->update) {
21859
21860  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
21861
21862  foreach ($currentPackages as $curPackage) {
21863 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
21864 if ($task === 'force-links') {
21865 $package->setRequires($curPackage->getRequires());
21866 $package->setConflicts($curPackage->getConflicts());
21867 $package->setProvides($curPackage->getProvides());
21868 $package->setReplaces($curPackage->getReplaces());
21869 } elseif ($task === 'force-updates') {
21870 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
21871 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
21872 ) {
21873 $operations[] = new UpdateOperation($package, $curPackage);
21874 }
21875 }
21876
21877 break;
21878 }
21879 }
21880
21881 continue;
21882 }
21883
21884
21885  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
21886 foreach ($matches as $index => $match) {
21887
21888  if (!in_array($match->getRepository(), $repositories, true)) {
21889 unset($matches[$index]);
21890 continue;
21891 }
21892
21893
21894  if ($match->getName() !== $package->getName()) {
21895 unset($matches[$index]);
21896 continue;
21897 }
21898
21899 $matches[$index] = $match->getId();
21900 }
21901
21902
21903  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
21904 $newPackage = $pool->literalToPackage($matches[0]);
21905
21906 if ($task === 'force-links' && $newPackage) {
21907 $package->setRequires($newPackage->getRequires());
21908 $package->setConflicts($newPackage->getConflicts());
21909 $package->setProvides($newPackage->getProvides());
21910 $package->setReplaces($newPackage->getReplaces());
21911 }
21912
21913 if (
21914 $task === 'force-updates'
21915 && $newPackage
21916 && (
21917 ($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
21918 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
21919 )
21920 ) {
21921 $operations[] = new UpdateOperation($package, $newPackage);
21922
21923 continue;
21924 }
21925 }
21926
21927 if ($task === 'force-updates') {
21928
21929  $references = $this->package->getReferences();
21930
21931 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
21932
21933  $operations[] = new UpdateOperation($package, clone $package);
21934 }
21935 }
21936 } else {
21937
21938  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
21939 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
21940 if ($task === 'force-links') {
21941 $package->setRequires($lockedPackage->getRequires());
21942 $package->setConflicts($lockedPackage->getConflicts());
21943 $package->setProvides($lockedPackage->getProvides());
21944 $package->setReplaces($lockedPackage->getReplaces());
21945 } elseif ($task === 'force-updates') {
21946 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
21947 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
21948 ) {
21949 $operations[] = new UpdateOperation($package, $lockedPackage);
21950 }
21951 }
21952
21953 break;
21954 }
21955 }
21956 }
21957 }
21958
21959 return $operations;
21960 }
21961
21962
21963
21964
21965
21966
21967 private function getCurrentPackages($installedRepo)
21968 {
21969 if ($this->locker->isLocked()) {
21970 try {
21971 return $this->locker->getLockedRepository(true)->getPackages();
21972 } catch (\RuntimeException $e) {
21973
21974  return $this->locker->getLockedRepository()->getPackages();
21975 }
21976 }
21977
21978 return $installedRepo->getPackages();
21979 }
21980
21981
21982
21983
21984 private function getRootAliases()
21985 {
21986 if ($this->update) {
21987 $aliases = $this->package->getAliases();
21988 } else {
21989 $aliases = $this->locker->getAliases();
21990 }
21991
21992 $normalizedAliases = array();
21993
21994 foreach ($aliases as $alias) {
21995 $normalizedAliases[$alias['package']][$alias['version']] = array(
21996 'alias' => $alias['alias'],
21997 'alias_normalized' => $alias['alias_normalized'],
21998 );
21999 }
22000
22001 return $normalizedAliases;
22002 }
22003
22004
22005
22006
22007
22008
22009
22010 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
22011 {
22012 if (!$this->update) {
22013 return;
22014 }
22015
22016 $rootRefs = $this->package->getReferences();
22017
22018 foreach ($localRepo->getCanonicalPackages() as $package) {
22019
22020  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
22021 foreach ($matches as $index => $match) {
22022
22023  if (!in_array($match->getRepository(), $repositories, true)) {
22024 unset($matches[$index]);
22025 continue;
22026 }
22027
22028
22029  if ($match->getName() !== $package->getName()) {
22030 unset($matches[$index]);
22031 continue;
22032 }
22033
22034 $matches[$index] = $match->getId();
22035 }
22036
22037
22038  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
22039 $newPackage = $pool->literalToPackage($matches[0]);
22040
22041
22042  $sourceUrl = $package->getSourceUrl();
22043 $newSourceUrl = $newPackage->getSourceUrl();
22044 $newReference = $newPackage->getSourceReference();
22045
22046 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
22047 $newReference = $rootRefs[$package->getName()];
22048 }
22049
22050 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl(), $newPackage->getDistType(), $newPackage->getDistSha1Checksum());
22051
22052 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
22053 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
22054 }
22055
22056 $package->setDistMirrors($newPackage->getDistMirrors());
22057 $package->setSourceMirrors($newPackage->getSourceMirrors());
22058 $package->setTransportOptions($newPackage->getTransportOptions());
22059 }
22060 }
22061 }
22062
22063 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl, $distType, $distShaSum)
22064 {
22065 $oldSourceRef = $package->getSourceReference();
22066
22067 if ($package->getSourceUrl() !== $sourceUrl) {
22068 $package->setSourceType($sourceType);
22069 $package->setSourceUrl($sourceUrl);
22070 $package->setSourceReference($sourceReference);
22071 }
22072
22073
22074  
22075  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $distUrl)) {
22076 $package->setDistUrl($distUrl);
22077 $package->setDistType($distType);
22078 $package->setDistSha1Checksum($distShaSum);
22079 $this->updateInstallReferences($package, $sourceReference);
22080 }
22081
22082 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
22083 $this->updateInstallReferences($package, $oldSourceRef);
22084 }
22085 }
22086
22087 private function updateInstallReferences(PackageInterface $package, $reference)
22088 {
22089 if (!$reference) {
22090 return;
22091 }
22092
22093 $package->setSourceReference($reference);
22094
22095 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $package->getDistUrl())) {
22096 $package->setDistReference($reference);
22097 $package->setDistUrl(preg_replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
22098 } elseif ($package->getDistReference()) { 
22099  $package->setDistReference($reference);
22100 }
22101 }
22102
22103
22104
22105
22106
22107 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
22108 {
22109 foreach ($aliases as $package => $versions) {
22110 foreach ($versions as $version => $alias) {
22111 $packages = $platformRepo->findPackages($package, $version);
22112 foreach ($packages as $package) {
22113 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
22114 $aliasPackage->setRootPackageAlias(true);
22115 $platformRepo->addPackage($aliasPackage);
22116 }
22117 }
22118 }
22119 }
22120
22121
22122
22123
22124
22125 private function isUpdateable(PackageInterface $package)
22126 {
22127 if (!$this->updateWhitelist) {
22128 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
22129 }
22130
22131 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
22132 $patternRegexp = BasePackage::packageNameToRegexp($whiteListedPattern);
22133 if (preg_match($patternRegexp, $package->getName())) {
22134 return true;
22135 }
22136 }
22137
22138 return false;
22139 }
22140
22141
22142
22143
22144
22145 private function extractPlatformRequirements($links)
22146 {
22147 $platformReqs = array();
22148 foreach ($links as $link) {
22149 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
22150 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
22151 }
22152 }
22153
22154 return $platformReqs;
22155 }
22156
22157
22158
22159
22160
22161
22162
22163
22164
22165
22166
22167
22168
22169
22170 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
22171 {
22172 if (!$this->updateWhitelist) {
22173 return;
22174 }
22175
22176 $rootRequires = array_merge($rootRequires, $rootDevRequires);
22177
22178 $skipPackages = array();
22179 if (!$this->whitelistAllDependencies) {
22180 foreach ($rootRequires as $require) {
22181 $skipPackages[$require->getTarget()] = true;
22182 }
22183 }
22184
22185 $pool = new Pool('dev');
22186 $pool->addRepository($localOrLockRepo);
22187
22188 $seen = array();
22189
22190 $rootRequiredPackageNames = array_keys($rootRequires);
22191
22192 foreach ($this->updateWhitelist as $packageName => $void) {
22193 $packageQueue = new \SplQueue;
22194 $nameMatchesRequiredPackage = false;
22195
22196 $depPackages = $pool->whatProvides($packageName);
22197 $matchesByPattern = array();
22198
22199  if (empty($depPackages)) {
22200
22201  $whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$');
22202 foreach ($localOrLockRepo->search($whitelistPatternSearchRegexp) as $installedPackage) {
22203 $matchesByPattern[] = $pool->whatProvides($installedPackage['name']);
22204 }
22205
22206
22207  $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName);
22208 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
22209 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
22210 $nameMatchesRequiredPackage = true;
22211 break;
22212 }
22213 }
22214 }
22215
22216 if (!empty($matchesByPattern)) {
22217 $depPackages = array_merge($depPackages, call_user_func_array('array_merge', $matchesByPattern));
22218 }
22219
22220 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
22221 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
22222 }
22223
22224 foreach ($depPackages as $depPackage) {
22225 $packageQueue->enqueue($depPackage);
22226 }
22227
22228 while (!$packageQueue->isEmpty()) {
22229 $package = $packageQueue->dequeue();
22230 if (isset($seen[$package->getId()])) {
22231 continue;
22232 }
22233
22234 $seen[$package->getId()] = true;
22235 $this->updateWhitelist[$package->getName()] = true;
22236
22237 if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) {
22238 continue;
22239 }
22240
22241 $requires = $package->getRequires();
22242
22243 foreach ($requires as $require) {
22244 $requirePackages = $pool->whatProvides($require->getTarget());
22245
22246 foreach ($requirePackages as $requirePackage) {
22247 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
22248 continue;
22249 }
22250
22251 if (isset($skipPackages[$requirePackage->getName()]) && !preg_match(BasePackage::packageNameToRegexp($packageName), $requirePackage->getName())) {
22252 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
22253 continue;
22254 }
22255
22256 $packageQueue->enqueue($requirePackage);
22257 }
22258 }
22259 }
22260 }
22261 }
22262
22263
22264
22265
22266
22267
22268
22269
22270 private function mockLocalRepositories(RepositoryManager $rm)
22271 {
22272 $packages = array();
22273 foreach ($rm->getLocalRepository()->getPackages() as $package) {
22274 $packages[(string) $package] = clone $package;
22275 }
22276 foreach ($packages as $key => $package) {
22277 if ($package instanceof AliasPackage) {
22278 $alias = (string) $package->getAliasOf();
22279 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
22280 }
22281 }
22282 $rm->setLocalRepository(
22283 new InstalledArrayRepository($packages)
22284 );
22285 }
22286
22287
22288
22289
22290
22291
22292
22293
22294 public static function create(IOInterface $io, Composer $composer)
22295 {
22296 return new static(
22297 $io,
22298 $composer->getConfig(),
22299 $composer->getPackage(),
22300 $composer->getDownloadManager(),
22301 $composer->getRepositoryManager(),
22302 $composer->getLocker(),
22303 $composer->getInstallationManager(),
22304 $composer->getEventDispatcher(),
22305 $composer->getAutoloadGenerator()
22306 );
22307 }
22308
22309
22310
22311
22312
22313 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
22314 {
22315 $this->additionalInstalledRepository = $additionalInstalledRepository;
22316
22317 return $this;
22318 }
22319
22320
22321
22322
22323
22324
22325
22326 public function setDryRun($dryRun = true)
22327 {
22328 $this->dryRun = (bool) $dryRun;
22329
22330 return $this;
22331 }
22332
22333
22334
22335
22336
22337
22338 public function isDryRun()
22339 {
22340 return $this->dryRun;
22341 }
22342
22343
22344
22345
22346
22347
22348
22349 public function setPreferSource($preferSource = true)
22350 {
22351 $this->preferSource = (bool) $preferSource;
22352
22353 return $this;
22354 }
22355
22356
22357
22358
22359
22360
22361
22362 public function setPreferDist($preferDist = true)
22363 {
22364 $this->preferDist = (bool) $preferDist;
22365
22366 return $this;
22367 }
22368
22369
22370
22371
22372
22373
22374
22375 public function setOptimizeAutoloader($optimizeAutoloader = false)
22376 {
22377 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
22378 if (!$this->optimizeAutoloader) {
22379
22380  
22381  $this->setClassMapAuthoritative(false);
22382 }
22383
22384 return $this;
22385 }
22386
22387
22388
22389
22390
22391
22392
22393
22394 public function setClassMapAuthoritative($classMapAuthoritative = false)
22395 {
22396 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
22397 if ($this->classMapAuthoritative) {
22398
22399  $this->setOptimizeAutoloader(true);
22400 }
22401
22402 return $this;
22403 }
22404
22405
22406
22407
22408
22409
22410
22411 public function setApcuAutoloader($apcuAutoloader = false)
22412 {
22413 $this->apcuAutoloader = (bool) $apcuAutoloader;
22414
22415 return $this;
22416 }
22417
22418
22419
22420
22421
22422
22423
22424 public function setUpdate($update = true)
22425 {
22426 $this->update = (bool) $update;
22427
22428 return $this;
22429 }
22430
22431
22432
22433
22434
22435
22436
22437 public function setDevMode($devMode = true)
22438 {
22439 $this->devMode = (bool) $devMode;
22440
22441 return $this;
22442 }
22443
22444
22445
22446
22447
22448
22449
22450
22451
22452 public function setDumpAutoloader($dumpAutoloader = true)
22453 {
22454 $this->dumpAutoloader = (bool) $dumpAutoloader;
22455
22456 return $this;
22457 }
22458
22459
22460
22461
22462
22463
22464
22465
22466
22467 public function setRunScripts($runScripts = true)
22468 {
22469 $this->runScripts = (bool) $runScripts;
22470
22471 return $this;
22472 }
22473
22474
22475
22476
22477
22478
22479
22480 public function setConfig(Config $config)
22481 {
22482 $this->config = $config;
22483
22484 return $this;
22485 }
22486
22487
22488
22489
22490
22491
22492
22493 public function setVerbose($verbose = true)
22494 {
22495 $this->verbose = (bool) $verbose;
22496
22497 return $this;
22498 }
22499
22500
22501
22502
22503
22504
22505 public function isVerbose()
22506 {
22507 return $this->verbose;
22508 }
22509
22510
22511
22512
22513
22514
22515
22516 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
22517 {
22518 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
22519
22520 return $this;
22521 }
22522
22523
22524
22525
22526
22527
22528
22529
22530 public function setUpdateWhitelist(array $packages)
22531 {
22532 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
22533
22534 return $this;
22535 }
22536
22537
22538
22539
22540 public function setWhitelistDependencies($updateDependencies = true)
22541 {
22542 return $this->setWhitelistTransitiveDependencies($updateDependencies);
22543 }
22544
22545
22546
22547
22548
22549
22550
22551
22552
22553
22554 public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true)
22555 {
22556 $this->whitelistDependencies = (bool) $updateTransitiveDependencies;
22557
22558 return $this;
22559 }
22560
22561
22562
22563
22564
22565
22566
22567
22568
22569
22570 public function setWhitelistAllDependencies($updateAllDependencies = true)
22571 {
22572 $this->whitelistAllDependencies = (bool) $updateAllDependencies;
22573
22574 return $this;
22575 }
22576
22577
22578
22579
22580
22581
22582
22583 public function setPreferStable($preferStable = true)
22584 {
22585 $this->preferStable = (bool) $preferStable;
22586
22587 return $this;
22588 }
22589
22590
22591
22592
22593
22594
22595
22596 public function setPreferLowest($preferLowest = true)
22597 {
22598 $this->preferLowest = (bool) $preferLowest;
22599
22600 return $this;
22601 }
22602
22603
22604
22605
22606
22607
22608
22609
22610
22611 public function setWriteLock($writeLock = true)
22612 {
22613 $this->writeLock = (bool) $writeLock;
22614
22615 return $this;
22616 }
22617
22618
22619
22620
22621
22622
22623
22624
22625
22626 public function setExecuteOperations($executeOperations = true)
22627 {
22628 $this->executeOperations = (bool) $executeOperations;
22629
22630 return $this;
22631 }
22632
22633
22634
22635
22636
22637
22638
22639 public function setSkipSuggest($skipSuggest = true)
22640 {
22641 $this->skipSuggest = (bool) $skipSuggest;
22642
22643 return $this;
22644 }
22645
22646
22647
22648
22649
22650
22651
22652
22653
22654
22655 public function disablePlugins()
22656 {
22657 $this->installationManager->disablePlugins();
22658
22659 return $this;
22660 }
22661
22662
22663
22664
22665
22666 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
22667 {
22668 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
22669
22670 return $this;
22671 }
22672 }
22673 <?php
22674
22675
22676
22677
22678
22679
22680
22681
22682
22683
22684
22685 namespace Composer\Installer;
22686
22687 use Composer\IO\IOInterface;
22688 use Composer\Package\PackageInterface;
22689 use Composer\Util\Filesystem;
22690 use Composer\Util\Platform;
22691 use Composer\Util\ProcessExecutor;
22692 use Composer\Util\Silencer;
22693
22694
22695
22696
22697
22698
22699
22700
22701 class BinaryInstaller
22702 {
22703 protected $binDir;
22704 protected $binCompat;
22705 protected $io;
22706 protected $filesystem;
22707
22708
22709
22710
22711
22712
22713
22714 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
22715 {
22716 $this->binDir = $binDir;
22717 $this->binCompat = $binCompat;
22718 $this->io = $io;
22719 $this->filesystem = $filesystem ?: new Filesystem();
22720 }
22721
22722 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
22723 {
22724 $binaries = $this->getBinaries($package);
22725 if (!$binaries) {
22726 return;
22727 }
22728 foreach ($binaries as $bin) {
22729 $binPath = $installPath.'/'.$bin;
22730 if (!file_exists($binPath)) {
22731 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
22732 continue;
22733 }
22734
22735
22736  
22737  
22738  
22739  $binPath = realpath($binPath);
22740
22741 $this->initializeBinDir();
22742 $link = $this->binDir.'/'.basename($bin);
22743 if (file_exists($link)) {
22744 if (is_link($link)) {
22745
22746  
22747  
22748  Silencer::call('chmod', $link, 0777 & ~umask());
22749 }
22750 if ($warnOnOverwrite) {
22751 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
22752 }
22753 continue;
22754 }
22755
22756 if ($this->binCompat === "auto") {
22757 if (Platform::isWindows()) {
22758 $this->installFullBinaries($binPath, $link, $bin, $package);
22759 } else {
22760 $this->installSymlinkBinaries($binPath, $link);
22761 }
22762 } elseif ($this->binCompat === "full") {
22763 $this->installFullBinaries($binPath, $link, $bin, $package);
22764 }
22765 Silencer::call('chmod', $link, 0777 & ~umask());
22766 }
22767 }
22768
22769 public function removeBinaries(PackageInterface $package)
22770 {
22771 $this->initializeBinDir();
22772
22773 $binaries = $this->getBinaries($package);
22774 if (!$binaries) {
22775 return;
22776 }
22777 foreach ($binaries as $bin) {
22778 $link = $this->binDir.'/'.basename($bin);
22779 if (is_link($link) || file_exists($link)) {
22780 $this->filesystem->unlink($link);
22781 }
22782 if (file_exists($link.'.bat')) {
22783 $this->filesystem->unlink($link.'.bat');
22784 }
22785 }
22786
22787
22788  if (is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) {
22789 Silencer::call('rmdir', $this->binDir);
22790 }
22791 }
22792
22793 public static function determineBinaryCaller($bin)
22794 {
22795 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
22796 return 'call';
22797 }
22798
22799 $handle = fopen($bin, 'r');
22800 $line = fgets($handle);
22801 fclose($handle);
22802 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
22803 return trim($match[1]);
22804 }
22805
22806 return 'php';
22807 }
22808
22809 protected function getBinaries(PackageInterface $package)
22810 {
22811 return $package->getBinaries();
22812 }
22813
22814 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
22815 {
22816
22817  if ('.bat' !== substr($binPath, -4)) {
22818 $this->installUnixyProxyBinaries($binPath, $link);
22819 @chmod($link, 0777 & ~umask());
22820 $link .= '.bat';
22821 if (file_exists($link)) {
22822 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
22823 }
22824 }
22825 if (!file_exists($link)) {
22826 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
22827 }
22828 }
22829
22830 protected function installSymlinkBinaries($binPath, $link)
22831 {
22832 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
22833 $this->installUnixyProxyBinaries($binPath, $link);
22834 }
22835 }
22836
22837 protected function installUnixyProxyBinaries($binPath, $link)
22838 {
22839 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
22840 }
22841
22842 protected function initializeBinDir()
22843 {
22844 $this->filesystem->ensureDirectoryExists($this->binDir);
22845 $this->binDir = realpath($this->binDir);
22846 }
22847
22848 protected function generateWindowsProxyCode($bin, $link)
22849 {
22850 $binPath = $this->filesystem->findShortestPath($link, $bin);
22851 $caller = self::determineBinaryCaller($bin);
22852
22853 return "@ECHO OFF\r\n".
22854 "setlocal DISABLEDELAYEDEXPANSION\r\n".
22855 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
22856 "{$caller} \"%BIN_TARGET%\" %*\r\n";
22857 }
22858
22859 protected function generateUnixyProxyCode($bin, $link)
22860 {
22861 $binPath = $this->filesystem->findShortestPath($link, $bin);
22862
22863 $binDir = ProcessExecutor::escape(dirname($binPath));
22864 $binFile = basename($binPath);
22865
22866 $proxyCode = <<<PROXY
22867 #!/usr/bin/env sh
22868
22869 dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
22870
22871 if [ -d /proc/cygdrive ]; then
22872     case \$(which php) in
22873         \$(readlink -n /proc/cygdrive)/*)
22874             # We are in Cygwin using Windows php, so the path must be translated
22875             dir=\$(cygpath -m "\$dir");
22876             ;;
22877     esac
22878 fi
22879
22880 "\${dir}/$binFile" "\$@"
22881
22882 PROXY;
22883
22884 return $proxyCode;
22885 }
22886 }
22887 <?php
22888
22889
22890
22891
22892
22893
22894
22895
22896
22897
22898
22899 namespace Composer\Installer;
22900
22901 use Composer\Package\PackageInterface;
22902
22903
22904
22905
22906
22907
22908 interface BinaryPresenceInterface
22909 {
22910
22911
22912
22913
22914
22915 public function ensureBinariesPresence(PackageInterface $package);
22916 }
22917 <?php
22918
22919
22920
22921
22922
22923
22924
22925
22926
22927
22928
22929 namespace Composer\Installer;
22930
22931 use Composer\IO\IOInterface;
22932 use Composer\Package\PackageInterface;
22933 use Composer\Package\AliasPackage;
22934 use Composer\Repository\RepositoryInterface;
22935 use Composer\Repository\InstalledRepositoryInterface;
22936 use Composer\DependencyResolver\Operation\OperationInterface;
22937 use Composer\DependencyResolver\Operation\InstallOperation;
22938 use Composer\DependencyResolver\Operation\UpdateOperation;
22939 use Composer\DependencyResolver\Operation\UninstallOperation;
22940 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
22941 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
22942 use Composer\Util\StreamContextFactory;
22943
22944
22945
22946
22947
22948
22949
22950
22951 class InstallationManager
22952 {
22953 private $installers = array();
22954 private $cache = array();
22955 private $notifiablePackages = array();
22956
22957 public function reset()
22958 {
22959 $this->notifiablePackages = array();
22960 }
22961
22962
22963
22964
22965
22966
22967 public function addInstaller(InstallerInterface $installer)
22968 {
22969 array_unshift($this->installers, $installer);
22970 $this->cache = array();
22971 }
22972
22973
22974
22975
22976
22977
22978 public function removeInstaller(InstallerInterface $installer)
22979 {
22980 if (false !== ($key = array_search($installer, $this->installers, true))) {
22981 array_splice($this->installers, $key, 1);
22982 $this->cache = array();
22983 }
22984 }
22985
22986
22987
22988
22989
22990
22991
22992
22993 public function disablePlugins()
22994 {
22995 foreach ($this->installers as $i => $installer) {
22996 if (!$installer instanceof PluginInstaller) {
22997 continue;
22998 }
22999
23000 unset($this->installers[$i]);
23001 }
23002 }
23003
23004
23005
23006
23007
23008
23009
23010
23011
23012 public function getInstaller($type)
23013 {
23014 $type = strtolower($type);
23015
23016 if (isset($this->cache[$type])) {
23017 return $this->cache[$type];
23018 }
23019
23020 foreach ($this->installers as $installer) {
23021 if ($installer->supports($type)) {
23022 return $this->cache[$type] = $installer;
23023 }
23024 }
23025
23026 throw new \InvalidArgumentException('Unknown installer type: '.$type);
23027 }
23028
23029
23030
23031
23032
23033
23034
23035
23036
23037 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23038 {
23039 if ($package instanceof AliasPackage) {
23040 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
23041 }
23042
23043 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
23044 }
23045
23046
23047
23048
23049
23050
23051
23052 public function ensureBinariesPresence(PackageInterface $package)
23053 {
23054 try {
23055 $installer = $this->getInstaller($package->getType());
23056 } catch (\InvalidArgumentException $e) {
23057
23058  return;
23059 }
23060
23061
23062  if ($installer instanceof BinaryPresenceInterface) {
23063 $installer->ensureBinariesPresence($package);
23064 }
23065 }
23066
23067
23068
23069
23070
23071
23072
23073 public function execute(RepositoryInterface $repo, OperationInterface $operation)
23074 {
23075 $method = $operation->getJobType();
23076 $this->$method($repo, $operation);
23077 }
23078
23079
23080
23081
23082
23083
23084
23085 public function install(RepositoryInterface $repo, InstallOperation $operation)
23086 {
23087 $package = $operation->getPackage();
23088 $installer = $this->getInstaller($package->getType());
23089 $installer->install($repo, $package);
23090 $this->markForNotification($package);
23091 }
23092
23093
23094
23095
23096
23097
23098
23099 public function update(RepositoryInterface $repo, UpdateOperation $operation)
23100 {
23101 $initial = $operation->getInitialPackage();
23102 $target = $operation->getTargetPackage();
23103
23104 $initialType = $initial->getType();
23105 $targetType = $target->getType();
23106
23107 if ($initialType === $targetType) {
23108 $installer = $this->getInstaller($initialType);
23109 $installer->update($repo, $initial, $target);
23110 $this->markForNotification($target);
23111 } else {
23112 $this->getInstaller($initialType)->uninstall($repo, $initial);
23113 $this->getInstaller($targetType)->install($repo, $target);
23114 }
23115 }
23116
23117
23118
23119
23120
23121
23122
23123 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
23124 {
23125 $package = $operation->getPackage();
23126 $installer = $this->getInstaller($package->getType());
23127 $installer->uninstall($repo, $package);
23128 }
23129
23130
23131
23132
23133
23134
23135
23136 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
23137 {
23138 $package = $operation->getPackage();
23139
23140 if (!$repo->hasPackage($package)) {
23141 $repo->addPackage(clone $package);
23142 }
23143 }
23144
23145
23146
23147
23148
23149
23150
23151 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
23152 {
23153 $package = $operation->getPackage();
23154
23155 $repo->removePackage($package);
23156 }
23157
23158
23159
23160
23161
23162
23163
23164 public function getInstallPath(PackageInterface $package)
23165 {
23166 $installer = $this->getInstaller($package->getType());
23167
23168 return $installer->getInstallPath($package);
23169 }
23170
23171 public function notifyInstalls(IOInterface $io)
23172 {
23173 foreach ($this->notifiablePackages as $repoUrl => $packages) {
23174 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
23175 if ($io->hasAuthentication($repositoryName)) {
23176 $auth = $io->getAuthentication($repositoryName);
23177 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
23178 $authHeader = 'Authorization: Basic '.$authStr;
23179 }
23180
23181
23182  if (strpos($repoUrl, '%package%')) {
23183 foreach ($packages as $package) {
23184 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
23185
23186 $params = array(
23187 'version' => $package->getPrettyVersion(),
23188 'version_normalized' => $package->getVersion(),
23189 );
23190 $opts = array('http' =>
23191 array(
23192 'method' => 'POST',
23193 'header' => array('Content-type: application/x-www-form-urlencoded'),
23194 'content' => http_build_query($params, '', '&'),
23195 'timeout' => 3,
23196 ),
23197 );
23198 if (isset($authHeader)) {
23199 $opts['http']['header'][] = $authHeader;
23200 }
23201
23202 $context = StreamContextFactory::getContext($url, $opts);
23203 @file_get_contents($url, false, $context);
23204 }
23205
23206 continue;
23207 }
23208
23209 $postData = array('downloads' => array());
23210 foreach ($packages as $package) {
23211 $postData['downloads'][] = array(
23212 'name' => $package->getPrettyName(),
23213 'version' => $package->getVersion(),
23214 );
23215 }
23216
23217 $opts = array('http' =>
23218 array(
23219 'method' => 'POST',
23220 'header' => array('Content-Type: application/json'),
23221 'content' => json_encode($postData),
23222 'timeout' => 6,
23223 ),
23224 );
23225 if (isset($authHeader)) {
23226 $opts['http']['header'][] = $authHeader;
23227 }
23228
23229 $context = StreamContextFactory::getContext($repoUrl, $opts);
23230 @file_get_contents($repoUrl, false, $context);
23231 }
23232
23233 $this->reset();
23234 }
23235
23236 private function markForNotification(PackageInterface $package)
23237 {
23238 if ($package->getNotificationUrl()) {
23239 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
23240 }
23241 }
23242 }
23243 <?php
23244
23245
23246
23247
23248
23249
23250
23251
23252
23253
23254
23255 namespace Composer\Installer;
23256
23257 use Composer\Composer;
23258 use Composer\DependencyResolver\PolicyInterface;
23259 use Composer\DependencyResolver\Operation\OperationInterface;
23260 use Composer\DependencyResolver\Pool;
23261 use Composer\DependencyResolver\Request;
23262 use Composer\EventDispatcher\Event;
23263 use Composer\IO\IOInterface;
23264 use Composer\Repository\CompositeRepository;
23265
23266
23267
23268
23269
23270
23271 class InstallerEvent extends Event
23272 {
23273
23274
23275
23276 private $composer;
23277
23278
23279
23280
23281 private $io;
23282
23283
23284
23285
23286 private $devMode;
23287
23288
23289
23290
23291 private $policy;
23292
23293
23294
23295
23296 private $pool;
23297
23298
23299
23300
23301 private $installedRepo;
23302
23303
23304
23305
23306 private $request;
23307
23308
23309
23310
23311 private $operations;
23312
23313
23314
23315
23316
23317
23318
23319
23320
23321
23322
23323
23324
23325
23326 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
23327 {
23328 parent::__construct($eventName);
23329
23330 $this->composer = $composer;
23331 $this->io = $io;
23332 $this->devMode = $devMode;
23333 $this->policy = $policy;
23334 $this->pool = $pool;
23335 $this->installedRepo = $installedRepo;
23336 $this->request = $request;
23337 $this->operations = $operations;
23338 }
23339
23340
23341
23342
23343 public function getComposer()
23344 {
23345 return $this->composer;
23346 }
23347
23348
23349
23350
23351 public function getIO()
23352 {
23353 return $this->io;
23354 }
23355
23356
23357
23358
23359 public function isDevMode()
23360 {
23361 return $this->devMode;
23362 }
23363
23364
23365
23366
23367 public function getPolicy()
23368 {
23369 return $this->policy;
23370 }
23371
23372
23373
23374
23375 public function getPool()
23376 {
23377 return $this->pool;
23378 }
23379
23380
23381
23382
23383 public function getInstalledRepo()
23384 {
23385 return $this->installedRepo;
23386 }
23387
23388
23389
23390
23391 public function getRequest()
23392 {
23393 return $this->request;
23394 }
23395
23396
23397
23398
23399 public function getOperations()
23400 {
23401 return $this->operations;
23402 }
23403 }
23404 <?php
23405
23406
23407
23408
23409
23410
23411
23412
23413
23414
23415
23416 namespace Composer\Installer;
23417
23418
23419
23420
23421
23422
23423 class InstallerEvents
23424 {
23425
23426
23427
23428
23429
23430
23431
23432
23433
23434 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
23435
23436
23437
23438
23439
23440
23441
23442
23443
23444
23445 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
23446 }
23447 <?php
23448
23449
23450
23451
23452
23453
23454
23455
23456
23457
23458
23459 namespace Composer\Installer;
23460
23461 use Composer\Package\PackageInterface;
23462 use Composer\Repository\InstalledRepositoryInterface;
23463 use InvalidArgumentException;
23464
23465
23466
23467
23468
23469
23470
23471 interface InstallerInterface
23472 {
23473
23474
23475
23476
23477
23478
23479 public function supports($packageType);
23480
23481
23482
23483
23484
23485
23486
23487
23488
23489 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
23490
23491
23492
23493
23494
23495
23496
23497 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
23498
23499
23500
23501
23502
23503
23504
23505
23506
23507
23508 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
23509
23510
23511
23512
23513
23514
23515
23516 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
23517
23518
23519
23520
23521
23522
23523
23524 public function getInstallPath(PackageInterface $package);
23525 }
23526 <?php
23527
23528
23529
23530
23531
23532
23533
23534
23535
23536
23537
23538 namespace Composer\Installer;
23539
23540 use Composer\Composer;
23541 use Composer\IO\IOInterface;
23542 use Composer\Repository\InstalledRepositoryInterface;
23543 use Composer\Package\PackageInterface;
23544 use Composer\Util\Filesystem;
23545 use Composer\Util\Silencer;
23546 use Composer\Util\Platform;
23547
23548
23549
23550
23551
23552
23553
23554 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
23555 {
23556 protected $composer;
23557 protected $vendorDir;
23558 protected $binDir;
23559 protected $downloadManager;
23560 protected $io;
23561 protected $type;
23562 protected $filesystem;
23563 protected $binCompat;
23564 protected $binaryInstaller;
23565
23566
23567
23568
23569
23570
23571
23572
23573
23574
23575 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
23576 {
23577 $this->composer = $composer;
23578 $this->downloadManager = $composer->getDownloadManager();
23579 $this->io = $io;
23580 $this->type = $type;
23581
23582 $this->filesystem = $filesystem ?: new Filesystem();
23583 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
23584 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
23585 }
23586
23587
23588
23589
23590 public function supports($packageType)
23591 {
23592 return $packageType === $this->type || null === $this->type;
23593 }
23594
23595
23596
23597
23598 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23599 {
23600 if (!$repo->hasPackage($package)) {
23601 return false;
23602 }
23603
23604 $installPath = $this->getInstallPath($package);
23605
23606 if (is_readable($installPath)) {
23607 return true;
23608 }
23609
23610 return (Platform::isWindows() && $this->filesystem->isJunction($installPath)) || is_link($installPath);
23611 }
23612
23613
23614
23615
23616 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23617 {
23618 $this->initializeVendorDir();
23619 $downloadPath = $this->getInstallPath($package);
23620
23621
23622  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
23623 $this->binaryInstaller->removeBinaries($package);
23624 }
23625
23626 $this->installCode($package);
23627 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
23628 if (!$repo->hasPackage($package)) {
23629 $repo->addPackage(clone $package);
23630 }
23631 }
23632
23633
23634
23635
23636 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23637 {
23638 if (!$repo->hasPackage($initial)) {
23639 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23640 }
23641
23642 $this->initializeVendorDir();
23643
23644 $this->binaryInstaller->removeBinaries($initial);
23645 $this->updateCode($initial, $target);
23646 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
23647 $repo->removePackage($initial);
23648 if (!$repo->hasPackage($target)) {
23649 $repo->addPackage(clone $target);
23650 }
23651 }
23652
23653
23654
23655
23656 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23657 {
23658 if (!$repo->hasPackage($package)) {
23659 throw new \InvalidArgumentException('Package is not installed: '.$package);
23660 }
23661
23662 $this->removeCode($package);
23663 $this->binaryInstaller->removeBinaries($package);
23664 $repo->removePackage($package);
23665
23666 $downloadPath = $this->getPackageBasePath($package);
23667 if (strpos($package->getName(), '/')) {
23668 $packageVendorDir = dirname($downloadPath);
23669 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
23670 Silencer::call('rmdir', $packageVendorDir);
23671 }
23672 }
23673 }
23674
23675
23676
23677
23678 public function getInstallPath(PackageInterface $package)
23679 {
23680 $this->initializeVendorDir();
23681
23682 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
23683 $targetDir = $package->getTargetDir();
23684
23685 return $basePath . ($targetDir ? '/'.$targetDir : '');
23686 }
23687
23688
23689
23690
23691
23692
23693 public function ensureBinariesPresence(PackageInterface $package)
23694 {
23695 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
23696 }
23697
23698
23699
23700
23701
23702
23703
23704
23705
23706
23707 protected function getPackageBasePath(PackageInterface $package)
23708 {
23709 $installPath = $this->getInstallPath($package);
23710 $targetDir = $package->getTargetDir();
23711
23712 if ($targetDir) {
23713 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
23714 }
23715
23716 return $installPath;
23717 }
23718
23719 protected function installCode(PackageInterface $package)
23720 {
23721 $downloadPath = $this->getInstallPath($package);
23722 $this->downloadManager->download($package, $downloadPath);
23723 }
23724
23725 protected function updateCode(PackageInterface $initial, PackageInterface $target)
23726 {
23727 $initialDownloadPath = $this->getInstallPath($initial);
23728 $targetDownloadPath = $this->getInstallPath($target);
23729 if ($targetDownloadPath !== $initialDownloadPath) {
23730
23731  
23732  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
23733 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
23734 ) {
23735 $this->removeCode($initial);
23736 $this->installCode($target);
23737
23738 return;
23739 }
23740
23741 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
23742 }
23743 $this->downloadManager->update($initial, $target, $targetDownloadPath);
23744 }
23745
23746 protected function removeCode(PackageInterface $package)
23747 {
23748 $downloadPath = $this->getPackageBasePath($package);
23749 $this->downloadManager->remove($package, $downloadPath);
23750 }
23751
23752 protected function initializeVendorDir()
23753 {
23754 $this->filesystem->ensureDirectoryExists($this->vendorDir);
23755 $this->vendorDir = realpath($this->vendorDir);
23756 }
23757 }
23758 <?php
23759
23760
23761
23762
23763
23764
23765
23766
23767
23768
23769
23770 namespace Composer\Installer;
23771
23772 use Composer\Repository\InstalledRepositoryInterface;
23773 use Composer\Package\PackageInterface;
23774 use Composer\Package\Version\VersionParser;
23775 use Composer\IO\IOInterface;
23776
23777
23778
23779
23780
23781
23782 class MetapackageInstaller implements InstallerInterface
23783 {
23784 private $io;
23785
23786 public function __construct(IOInterface $io)
23787 {
23788 $this->io = $io;
23789 }
23790
23791
23792
23793
23794 public function supports($packageType)
23795 {
23796 return $packageType === 'metapackage';
23797 }
23798
23799
23800
23801
23802 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23803 {
23804 return $repo->hasPackage($package);
23805 }
23806
23807
23808
23809
23810 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23811 {
23812 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
23813
23814 $repo->addPackage(clone $package);
23815 }
23816
23817
23818
23819
23820 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23821 {
23822 if (!$repo->hasPackage($initial)) {
23823 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23824 }
23825
23826 $name = $target->getName();
23827 $from = $initial->getFullPrettyVersion();
23828 $to = $target->getFullPrettyVersion();
23829 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
23830 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>)");
23831
23832 $repo->removePackage($initial);
23833 $repo->addPackage(clone $target);
23834 }
23835
23836
23837
23838
23839 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23840 {
23841 if (!$repo->hasPackage($package)) {
23842 throw new \InvalidArgumentException('Package is not installed: '.$package);
23843 }
23844
23845 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
23846
23847 $repo->removePackage($package);
23848 }
23849
23850
23851
23852
23853 public function getInstallPath(PackageInterface $package)
23854 {
23855 return '';
23856 }
23857 }
23858 <?php
23859
23860
23861
23862
23863
23864
23865
23866
23867
23868
23869
23870 namespace Composer\Installer;
23871
23872 use Composer\Repository\InstalledRepositoryInterface;
23873 use Composer\Package\PackageInterface;
23874
23875
23876
23877
23878
23879
23880
23881
23882 class NoopInstaller implements InstallerInterface
23883 {
23884
23885
23886
23887 public function supports($packageType)
23888 {
23889 return true;
23890 }
23891
23892
23893
23894
23895 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23896 {
23897 return $repo->hasPackage($package);
23898 }
23899
23900
23901
23902
23903 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23904 {
23905 if (!$repo->hasPackage($package)) {
23906 $repo->addPackage(clone $package);
23907 }
23908 }
23909
23910
23911
23912
23913 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23914 {
23915 if (!$repo->hasPackage($initial)) {
23916 throw new \InvalidArgumentException('Package is not installed: '.$initial);
23917 }
23918
23919 $repo->removePackage($initial);
23920 if (!$repo->hasPackage($target)) {
23921 $repo->addPackage(clone $target);
23922 }
23923 }
23924
23925
23926
23927
23928 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23929 {
23930 if (!$repo->hasPackage($package)) {
23931 throw new \InvalidArgumentException('Package is not installed: '.$package);
23932 }
23933 $repo->removePackage($package);
23934 }
23935
23936
23937
23938
23939 public function getInstallPath(PackageInterface $package)
23940 {
23941 $targetDir = $package->getTargetDir();
23942
23943 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
23944 }
23945 }
23946 <?php
23947
23948
23949
23950
23951
23952
23953
23954
23955
23956
23957
23958 namespace Composer\Installer;
23959
23960 use Composer\Composer;
23961 use Composer\IO\IOInterface;
23962 use Composer\DependencyResolver\Operation\OperationInterface;
23963 use Composer\DependencyResolver\PolicyInterface;
23964 use Composer\DependencyResolver\Pool;
23965 use Composer\DependencyResolver\Request;
23966 use Composer\Repository\CompositeRepository;
23967
23968
23969
23970
23971
23972
23973 class PackageEvent extends InstallerEvent
23974 {
23975
23976
23977
23978 private $operation;
23979
23980
23981
23982
23983
23984
23985
23986
23987
23988
23989
23990
23991
23992
23993
23994 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
23995 {
23996 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
23997
23998 $this->operation = $operation;
23999 }
24000
24001
24002
24003
24004
24005
24006 public function getOperation()
24007 {
24008 return $this->operation;
24009 }
24010 }
24011 <?php
24012
24013
24014
24015
24016
24017
24018
24019
24020
24021
24022
24023 namespace Composer\Installer;
24024
24025
24026
24027
24028
24029
24030 class PackageEvents
24031 {
24032
24033
24034
24035
24036
24037
24038
24039 const PRE_PACKAGE_INSTALL = 'pre-package-install';
24040
24041
24042
24043
24044
24045
24046
24047
24048 const POST_PACKAGE_INSTALL = 'post-package-install';
24049
24050
24051
24052
24053
24054
24055
24056
24057 const PRE_PACKAGE_UPDATE = 'pre-package-update';
24058
24059
24060
24061
24062
24063
24064
24065
24066 const POST_PACKAGE_UPDATE = 'post-package-update';
24067
24068
24069
24070
24071
24072
24073
24074
24075 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
24076
24077
24078
24079
24080
24081
24082
24083
24084 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
24085 }
24086 <?php
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097
24098 namespace Composer\Installer;
24099
24100 use Composer\IO\IOInterface;
24101 use Composer\Package\PackageInterface;
24102 use Composer\Util\Filesystem;
24103 use Composer\Util\ProcessExecutor;
24104
24105
24106
24107
24108
24109
24110 class PearBinaryInstaller extends BinaryInstaller
24111 {
24112 private $installer;
24113 private $vendorDir;
24114
24115
24116
24117
24118
24119
24120
24121
24122
24123 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
24124 {
24125 parent::__construct($io, $binDir, $binCompat, $filesystem);
24126 $this->installer = $installer;
24127 $this->vendorDir = $vendorDir;
24128 }
24129
24130 protected function getBinaries(PackageInterface $package)
24131 {
24132 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
24133 $binaries = array();
24134 if (file_exists($binariesPath)) {
24135 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
24136 if (!$value->isDir()) {
24137 $binaries[] = 'bin/'.$fileName;
24138 }
24139 }
24140 }
24141
24142 return $binaries;
24143 }
24144
24145 protected function initializeBinDir()
24146 {
24147 parent::initializeBinDir();
24148 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
24149 @chmod($this->binDir.'/composer-php', 0777 & ~umask());
24150 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
24151 @chmod($this->binDir.'/composer-php.bat', 0777 & ~umask());
24152 }
24153
24154 protected function generateWindowsProxyCode($bin, $link)
24155 {
24156 $binPath = $this->filesystem->findShortestPath($link, $bin);
24157 if ('.bat' === substr($bin, -4)) {
24158 $caller = 'call';
24159 } else {
24160 $handle = fopen($bin, 'r');
24161 $line = fgets($handle);
24162 fclose($handle);
24163 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
24164 $caller = trim($match[1]);
24165 } else {
24166 $caller = 'php';
24167 }
24168
24169 if ($caller === 'php') {
24170 return "@echo off\r\n".
24171 "pushd .\r\n".
24172 "cd %~dp0\r\n".
24173 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
24174 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
24175 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
24176 "popd\r\n".
24177 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
24178 }
24179 }
24180
24181 return "@echo off\r\n".
24182 "pushd .\r\n".
24183 "cd %~dp0\r\n".
24184 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
24185 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
24186 "popd\r\n".
24187 $caller." \"%BIN_TARGET%\" %*\r\n";
24188 }
24189
24190 private function generateWindowsPhpProxyCode()
24191 {
24192 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
24193
24194 return
24195 "@echo off\r\n" .
24196 "setlocal enabledelayedexpansion\r\n" .
24197 "set BIN_DIR=%~dp0\r\n" .
24198 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
24199 "set DIRS=.\r\n" .
24200 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
24201 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
24202 "        set DIRS=!DIRS!;%%~fP\r\n" .
24203 "    )\r\n" .
24204 ")\r\n" .
24205 "php.exe -d include_path=!DIRS! %*\r\n";
24206 }
24207
24208 private function generateUnixyPhpProxyCode()
24209 {
24210 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
24211
24212 return
24213 "#!/usr/bin/env sh\n".
24214 "SRC_DIR=`pwd`\n".
24215 "BIN_DIR=`dirname $0`\n".
24216 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
24217 "DIRS=\"\"\n".
24218 "for vendor in \$VENDOR_DIR/*; do\n".
24219 "    if [ -d \"\$vendor\" ]; then\n".
24220 "        for package in \$vendor/*; do\n".
24221 "            if [ -d \"\$package\" ]; then\n".
24222 "                DIRS=\"\${DIRS}:\${package}\"\n".
24223 "            fi\n".
24224 "        done\n".
24225 "    fi\n".
24226 "done\n".
24227 "php -d include_path=\".\$DIRS\" $@\n";
24228 }
24229 }
24230 <?php
24231
24232
24233
24234
24235
24236
24237
24238
24239
24240
24241
24242 namespace Composer\Installer;
24243
24244 use Composer\IO\IOInterface;
24245 use Composer\Composer;
24246 use Composer\Downloader\PearPackageExtractor;
24247 use Composer\Repository\InstalledRepositoryInterface;
24248 use Composer\Package\PackageInterface;
24249 use Composer\Util\Platform;
24250 use Composer\Util\Filesystem;
24251
24252
24253
24254
24255
24256
24257
24258 class PearInstaller extends LibraryInstaller
24259 {
24260
24261
24262
24263
24264
24265
24266
24267 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
24268 {
24269 $filesystem = new Filesystem();
24270 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
24271
24272 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
24273 }
24274
24275
24276
24277
24278 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24279 {
24280 $this->uninstall($repo, $initial);
24281 $this->install($repo, $target);
24282 }
24283
24284 protected function installCode(PackageInterface $package)
24285 {
24286 parent::installCode($package);
24287
24288 $isWindows = Platform::isWindows();
24289 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
24290
24291 if (!$isWindows) {
24292 $php_bin = '/usr/bin/env ' . $php_bin;
24293 }
24294
24295 $installPath = $this->getInstallPath($package);
24296 $vars = array(
24297 'os' => $isWindows ? 'windows' : 'linux',
24298 'php_bin' => $php_bin,
24299 'pear_php' => $installPath,
24300 'php_dir' => $installPath,
24301 'bin_dir' => $installPath . '/bin',
24302 'data_dir' => $installPath . '/data',
24303 'version' => $package->getPrettyVersion(),
24304 );
24305
24306 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
24307 $pearExtractor = new PearPackageExtractor($packageArchive);
24308 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
24309
24310 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
24311 $this->filesystem->unlink($packageArchive);
24312 }
24313 }
24314 <?php
24315
24316
24317
24318
24319
24320
24321
24322
24323
24324
24325
24326 namespace Composer\Installer;
24327
24328 use Composer\Composer;
24329 use Composer\IO\IOInterface;
24330 use Composer\Repository\InstalledRepositoryInterface;
24331 use Composer\Package\PackageInterface;
24332
24333
24334
24335
24336
24337
24338
24339 class PluginInstaller extends LibraryInstaller
24340 {
24341 private $installationManager;
24342
24343
24344
24345
24346
24347
24348
24349 public function __construct(IOInterface $io, Composer $composer)
24350 {
24351 parent::__construct($io, $composer, 'composer-plugin');
24352 $this->installationManager = $composer->getInstallationManager();
24353 }
24354
24355
24356
24357
24358 public function supports($packageType)
24359 {
24360 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
24361 }
24362
24363
24364
24365
24366 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24367 {
24368 $extra = $package->getExtra();
24369 if (empty($extra['class'])) {
24370 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
24371 }
24372
24373 parent::install($repo, $package);
24374 try {
24375 $this->composer->getPluginManager()->registerPackage($package, true);
24376 } catch (\Exception $e) {
24377
24378  $this->io->writeError('Plugin installation failed, rolling back');
24379 parent::uninstall($repo, $package);
24380 throw $e;
24381 }
24382 }
24383
24384
24385
24386
24387 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24388 {
24389 $extra = $target->getExtra();
24390 if (empty($extra['class'])) {
24391 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
24392 }
24393
24394 parent::update($repo, $initial, $target);
24395 $this->composer->getPluginManager()->registerPackage($target, true);
24396 }
24397 }
24398 <?php
24399
24400
24401
24402
24403
24404
24405
24406
24407
24408
24409
24410 namespace Composer\Installer;
24411
24412 use Composer\Package\PackageInterface;
24413 use Composer\Downloader\DownloadManager;
24414 use Composer\Repository\InstalledRepositoryInterface;
24415 use Composer\Util\Filesystem;
24416
24417
24418
24419
24420
24421
24422
24423 class ProjectInstaller implements InstallerInterface
24424 {
24425 private $installPath;
24426 private $downloadManager;
24427 private $filesystem;
24428
24429 public function __construct($installPath, DownloadManager $dm)
24430 {
24431 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
24432 $this->downloadManager = $dm;
24433 $this->filesystem = new Filesystem;
24434 }
24435
24436
24437
24438
24439
24440
24441
24442 public function supports($packageType)
24443 {
24444 return true;
24445 }
24446
24447
24448
24449
24450 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24451 {
24452 return false;
24453 }
24454
24455
24456
24457
24458 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24459 {
24460 $installPath = $this->installPath;
24461 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
24462 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
24463 }
24464 if (!is_dir($installPath)) {
24465 mkdir($installPath, 0777, true);
24466 }
24467 $this->downloadManager->download($package, $installPath);
24468 }
24469
24470
24471
24472
24473 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24474 {
24475 throw new \InvalidArgumentException("not supported");
24476 }
24477
24478
24479
24480
24481 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
24482 {
24483 throw new \InvalidArgumentException("not supported");
24484 }
24485
24486
24487
24488
24489
24490
24491
24492 public function getInstallPath(PackageInterface $package)
24493 {
24494 return $this->installPath;
24495 }
24496 }
24497 <?php
24498
24499
24500
24501
24502
24503
24504
24505
24506
24507
24508
24509 namespace Composer\Installer;
24510
24511 use Composer\IO\IOInterface;
24512 use Composer\Package\PackageInterface;
24513 use Composer\Repository\RepositoryInterface;
24514 use Symfony\Component\Console\Formatter\OutputFormatter;
24515
24516
24517
24518
24519
24520
24521 class SuggestedPackagesReporter
24522 {
24523
24524
24525
24526 protected $suggestedPackages = array();
24527
24528
24529
24530
24531 private $io;
24532
24533 public function __construct(IOInterface $io)
24534 {
24535 $this->io = $io;
24536 }
24537
24538
24539
24540
24541 public function getPackages()
24542 {
24543 return $this->suggestedPackages;
24544 }
24545
24546
24547
24548
24549
24550
24551
24552
24553
24554
24555
24556
24557 public function addPackage($source, $target, $reason)
24558 {
24559 $this->suggestedPackages[] = array(
24560 'source' => $source,
24561 'target' => $target,
24562 'reason' => $reason,
24563 );
24564
24565 return $this;
24566 }
24567
24568
24569
24570
24571
24572
24573
24574 public function addSuggestionsFromPackage(PackageInterface $package)
24575 {
24576 $source = $package->getPrettyName();
24577 foreach ($package->getSuggests() as $target => $reason) {
24578 $this->addPackage(
24579 $source,
24580 $target,
24581 $reason
24582 );
24583 }
24584
24585 return $this;
24586 }
24587
24588
24589
24590
24591
24592
24593
24594
24595 public function output(RepositoryInterface $installedRepo = null)
24596 {
24597 $suggestedPackages = $this->getPackages();
24598 $installedPackages = array();
24599 if (null !== $installedRepo && ! empty($suggestedPackages)) {
24600 foreach ($installedRepo->getPackages() as $package) {
24601 $installedPackages = array_merge(
24602 $installedPackages,
24603 $package->getNames()
24604 );
24605 }
24606 }
24607
24608 foreach ($suggestedPackages as $suggestion) {
24609 if (in_array($suggestion['target'], $installedPackages)) {
24610 continue;
24611 }
24612
24613 $this->io->writeError(sprintf(
24614 '%s suggests installing %s%s',
24615 $suggestion['source'],
24616 $this->escapeOutput($suggestion['target']),
24617 $this->escapeOutput('' !== $suggestion['reason'] ? ' ('.$suggestion['reason'].')' : '')
24618 ));
24619 }
24620
24621 return $this;
24622 }
24623
24624
24625
24626
24627
24628 private function escapeOutput($string)
24629 {
24630 return OutputFormatter::escape(
24631 $this->removeControlCharacters($string)
24632 );
24633 }
24634
24635
24636
24637
24638
24639 private function removeControlCharacters($string)
24640 {
24641 return preg_replace(
24642 '/[[:cntrl:]]/',
24643 '',
24644 str_replace("\n", ' ', $string)
24645 );
24646 }
24647 }
24648 <?php
24649
24650
24651
24652
24653
24654
24655
24656
24657
24658
24659
24660 namespace Composer\Json;
24661
24662 use JsonSchema\Validator;
24663 use Seld\JsonLint\JsonParser;
24664 use Seld\JsonLint\ParsingException;
24665 use Composer\Util\RemoteFilesystem;
24666 use Composer\IO\IOInterface;
24667 use Composer\Downloader\TransportException;
24668
24669
24670
24671
24672
24673
24674
24675 class JsonFile
24676 {
24677 const LAX_SCHEMA = 1;
24678 const STRICT_SCHEMA = 2;
24679
24680 const JSON_UNESCAPED_SLASHES = 64;
24681 const JSON_PRETTY_PRINT = 128;
24682 const JSON_UNESCAPED_UNICODE = 256;
24683
24684 const COMPOSER_SCHEMA_PATH = '/../../../res/composer-schema.json';
24685
24686 private $path;
24687 private $rfs;
24688 private $io;
24689
24690
24691
24692
24693
24694
24695
24696
24697
24698 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
24699 {
24700 $this->path = $path;
24701
24702 if (null === $rfs && preg_match('{^https?://}i', $path)) {
24703 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
24704 }
24705 $this->rfs = $rfs;
24706 $this->io = $io;
24707 }
24708
24709
24710
24711
24712 public function getPath()
24713 {
24714 return $this->path;
24715 }
24716
24717
24718
24719
24720
24721
24722 public function exists()
24723 {
24724 return is_file($this->path);
24725 }
24726
24727
24728
24729
24730
24731
24732
24733 public function read()
24734 {
24735 try {
24736 if ($this->rfs) {
24737 $json = $this->rfs->getContents($this->path, $this->path, false);
24738 } else {
24739 if ($this->io && $this->io->isDebug()) {
24740 $this->io->writeError('Reading ' . $this->path);
24741 }
24742 $json = file_get_contents($this->path);
24743 }
24744 } catch (TransportException $e) {
24745 throw new \RuntimeException($e->getMessage(), 0, $e);
24746 } catch (\Exception $e) {
24747 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
24748 }
24749
24750 return static::parseJson($json, $this->path);
24751 }
24752
24753
24754
24755
24756
24757
24758
24759
24760 public function write(array $hash, $options = 448)
24761 {
24762 $dir = dirname($this->path);
24763 if (!is_dir($dir)) {
24764 if (file_exists($dir)) {
24765 throw new \UnexpectedValueException(
24766 $dir.' exists and is not a directory.'
24767 );
24768 }
24769 if (!@mkdir($dir, 0777, true)) {
24770 throw new \UnexpectedValueException(
24771 $dir.' does not exist and could not be created.'
24772 );
24773 }
24774 }
24775
24776 $retries = 3;
24777 while ($retries--) {
24778 try {
24779 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
24780 break;
24781 } catch (\Exception $e) {
24782 if ($retries) {
24783 usleep(500000);
24784 continue;
24785 }
24786
24787 throw $e;
24788 }
24789 }
24790 }
24791
24792
24793
24794
24795
24796
24797
24798
24799
24800 public function validateSchema($schema = self::STRICT_SCHEMA, $schemaFile = null)
24801 {
24802 $content = file_get_contents($this->path);
24803 $data = json_decode($content);
24804
24805 if (null === $data && 'null' !== $content) {
24806 self::validateSyntax($content, $this->path);
24807 }
24808
24809 if (null === $schemaFile) {
24810 $schemaFile = __DIR__ . self::COMPOSER_SCHEMA_PATH;
24811 }
24812
24813
24814  if (false === strpos($schemaFile, '://')) {
24815 $schemaFile = 'file://' . $schemaFile;
24816 }
24817
24818 $schemaData = (object) array('$ref' => $schemaFile);
24819
24820 if ($schema === self::LAX_SCHEMA) {
24821 $schemaData->additionalProperties = true;
24822 $schemaData->required = array();
24823 }
24824
24825 $validator = new Validator();
24826 $validator->check($data, $schemaData);
24827
24828
24829
24830 if (!$validator->isValid()) {
24831 $errors = array();
24832 foreach ((array) $validator->getErrors() as $error) {
24833 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
24834 }
24835 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
24836 }
24837
24838 return true;
24839 }
24840
24841
24842
24843
24844
24845
24846
24847
24848 public static function encode($data, $options = 448)
24849 {
24850 if (PHP_VERSION_ID >= 50400) {
24851 $json = json_encode($data, $options);
24852 if (false === $json) {
24853 self::throwEncodeError(json_last_error());
24854 }
24855
24856
24857  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
24858 $json = preg_replace('/\[\s+\]/', '[]', $json);
24859 $json = preg_replace('/\{\s+\}/', '{}', $json);
24860 }
24861
24862 return $json;
24863 }
24864
24865 $json = json_encode($data);
24866 if (false === $json) {
24867 self::throwEncodeError(json_last_error());
24868 }
24869
24870 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
24871 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
24872 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
24873
24874 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
24875 return $json;
24876 }
24877
24878 return JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
24879 }
24880
24881
24882
24883
24884
24885
24886
24887 private static function throwEncodeError($code)
24888 {
24889 switch ($code) {
24890 case JSON_ERROR_DEPTH:
24891 $msg = 'Maximum stack depth exceeded';
24892 break;
24893 case JSON_ERROR_STATE_MISMATCH:
24894 $msg = 'Underflow or the modes mismatch';
24895 break;
24896 case JSON_ERROR_CTRL_CHAR:
24897 $msg = 'Unexpected control character found';
24898 break;
24899 case JSON_ERROR_UTF8:
24900 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
24901 break;
24902 default:
24903 $msg = 'Unknown error';
24904 }
24905
24906 throw new \RuntimeException('JSON encoding failed: '.$msg);
24907 }
24908
24909
24910
24911
24912
24913
24914
24915
24916
24917 public static function parseJson($json, $file = null)
24918 {
24919 if (null === $json) {
24920 return;
24921 }
24922 $data = json_decode($json, true);
24923 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
24924 self::validateSyntax($json, $file);
24925 }
24926
24927 return $data;
24928 }
24929
24930
24931
24932
24933
24934
24935
24936
24937
24938
24939 protected static function validateSyntax($json, $file = null)
24940 {
24941 $parser = new JsonParser();
24942 $result = $parser->lint($json);
24943 if (null === $result) {
24944 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
24945 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
24946 }
24947
24948 return true;
24949 }
24950
24951 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
24952 }
24953 }
24954 <?php
24955
24956
24957
24958
24959
24960
24961
24962
24963
24964
24965
24966 namespace Composer\Json;
24967
24968
24969
24970
24971
24972
24973
24974
24975
24976 class JsonFormatter
24977 {
24978
24979
24980
24981
24982
24983
24984
24985
24986
24987
24988
24989
24990 public static function format($json, $unescapeUnicode, $unescapeSlashes)
24991 {
24992 $result = '';
24993 $pos = 0;
24994 $strLen = strlen($json);
24995 $indentStr = '    ';
24996 $newLine = "\n";
24997 $outOfQuotes = true;
24998 $buffer = '';
24999 $noescape = true;
25000
25001 for ($i = 0; $i < $strLen; $i++) {
25002
25003  $char = substr($json, $i, 1);
25004
25005
25006  if ('"' === $char && $noescape) {
25007 $outOfQuotes = !$outOfQuotes;
25008 }
25009
25010 if (!$outOfQuotes) {
25011 $buffer .= $char;
25012 $noescape = '\\' === $char ? !$noescape : true;
25013 continue;
25014 } elseif ('' !== $buffer) {
25015 if ($unescapeSlashes) {
25016 $buffer = str_replace('\\/', '/', $buffer);
25017 }
25018
25019 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
25020
25021  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
25022 $l = strlen($match[1]);
25023
25024 if ($l % 2) {
25025 $code = hexdec($match[2]);
25026
25027  
25028  if (0xD800 <= $code && 0xDFFF >= $code) {
25029 return $match[0];
25030 }
25031
25032 return str_repeat('\\', $l - 1) . mb_convert_encoding(
25033 pack('H*', $match[2]),
25034 'UTF-8',
25035 'UCS-2BE'
25036 );
25037 }
25038
25039 return $match[0];
25040 }, $buffer);
25041 }
25042
25043 $result .= $buffer.$char;
25044 $buffer = '';
25045 continue;
25046 }
25047
25048 if (':' === $char) {
25049
25050  $char .= ' ';
25051 } elseif ('}' === $char || ']' === $char) {
25052 $pos--;
25053 $prevChar = substr($json, $i - 1, 1);
25054
25055 if ('{' !== $prevChar && '[' !== $prevChar) {
25056
25057  
25058  $result .= $newLine;
25059 for ($j = 0; $j < $pos; $j++) {
25060 $result .= $indentStr;
25061 }
25062 } else {
25063
25064  $result = rtrim($result);
25065 }
25066 }
25067
25068 $result .= $char;
25069
25070
25071  
25072  if (',' === $char || '{' === $char || '[' === $char) {
25073 $result .= $newLine;
25074
25075 if ('{' === $char || '[' === $char) {
25076 $pos++;
25077 }
25078
25079 for ($j = 0; $j < $pos; $j++) {
25080 $result .= $indentStr;
25081 }
25082 }
25083 }
25084
25085 return $result;
25086 }
25087 }
25088 <?php
25089
25090
25091
25092
25093
25094
25095
25096
25097
25098
25099
25100 namespace Composer\Json;
25101
25102 use Composer\Repository\PlatformRepository;
25103
25104
25105
25106
25107 class JsonManipulator
25108 {
25109 private static $DEFINES = '(?(DEFINE)
25110        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
25111        (?<boolean>   true | false | null )
25112        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
25113        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
25114        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
25115        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
25116        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
25117     )';
25118
25119 private $contents;
25120 private $newline;
25121 private $indent;
25122
25123 public function __construct($contents)
25124 {
25125 $contents = trim($contents);
25126 if ($contents === '') {
25127 $contents = '{}';
25128 }
25129 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
25130 throw new \InvalidArgumentException('The json file must be an object ({})');
25131 }
25132 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
25133 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
25134 $this->detectIndenting();
25135 }
25136
25137 public function getContents()
25138 {
25139 return $this->contents . $this->newline;
25140 }
25141
25142 public function addLink($type, $package, $constraint, $sortPackages = false)
25143 {
25144 $decoded = JsonFile::parseJson($this->contents);
25145
25146
25147  if (!isset($decoded[$type])) {
25148 return $this->addMainKey($type, array($package => $constraint));
25149 }
25150
25151 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
25152 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
25153 if (!$this->pregMatch($regex, $this->contents, $matches)) {
25154 return false;
25155 }
25156
25157 $links = $matches['value'];
25158
25159
25160  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
25161 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
25162 if ($this->pregMatch($regex, $links, $packageMatches)) {
25163
25164  $existingPackage = $packageMatches['package'];
25165 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
25166 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
25167 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
25168 }, $links);
25169 } else {
25170 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
25171
25172  $links = preg_replace(
25173 '{'.preg_quote($match[1]).'$}',
25174
25175  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
25176 $links
25177 );
25178 } else {
25179
25180  $links = '{' . $this->newline .
25181 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
25182 $this->indent . '}';
25183 }
25184 }
25185
25186 if (true === $sortPackages) {
25187 $requirements = json_decode($links, true);
25188 $this->sortPackages($requirements);
25189 $links = $this->format($requirements);
25190 }
25191
25192 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
25193
25194 return true;
25195 }
25196
25197
25198
25199
25200
25201
25202
25203
25204 private function sortPackages(array &$packages = array())
25205 {
25206 $prefix = function ($requirement) {
25207 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
25208 return preg_replace(
25209 array(
25210 '/^php/',
25211 '/^hhvm/',
25212 '/^ext/',
25213 '/^lib/',
25214 '/^\D/',
25215 ),
25216 array(
25217 '0-$0',
25218 '1-$0',
25219 '2-$0',
25220 '3-$0',
25221 '4-$0',
25222 ),
25223 $requirement
25224 );
25225 }
25226
25227 return '5-'.$requirement;
25228 };
25229
25230 uksort($packages, function ($a, $b) use ($prefix) {
25231 return strnatcmp($prefix($a), $prefix($b));
25232 });
25233 }
25234
25235 public function addRepository($name, $config)
25236 {
25237 return $this->addSubNode('repositories', $name, $config);
25238 }
25239
25240 public function removeRepository($name)
25241 {
25242 return $this->removeSubNode('repositories', $name);
25243 }
25244
25245 public function addConfigSetting($name, $value)
25246 {
25247 return $this->addSubNode('config', $name, $value);
25248 }
25249
25250 public function removeConfigSetting($name)
25251 {
25252 return $this->removeSubNode('config', $name);
25253 }
25254
25255 public function addProperty($name, $value)
25256 {
25257 if (substr($name, 0, 6) === 'extra.') {
25258 return $this->addSubNode('extra', substr($name, 6), $value);
25259 }
25260
25261 if (substr($name, 0, 8) === 'scripts.') {
25262 return $this->addSubNode('scripts', substr($name, 8), $value);
25263 }
25264
25265 return $this->addMainKey($name, $value);
25266 }
25267
25268 public function removeProperty($name)
25269 {
25270 if (substr($name, 0, 6) === 'extra.') {
25271 return $this->removeSubNode('extra', substr($name, 6));
25272 }
25273
25274 if (substr($name, 0, 8) === 'scripts.') {
25275 return $this->removeSubNode('scripts', substr($name, 8));
25276 }
25277
25278 return $this->removeMainKey($name);
25279 }
25280
25281 public function addSubNode($mainNode, $name, $value)
25282 {
25283 $decoded = JsonFile::parseJson($this->contents);
25284
25285 $subName = null;
25286 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
25287 list($name, $subName) = explode('.', $name, 2);
25288 }
25289
25290
25291  if (!isset($decoded[$mainNode])) {
25292 if ($subName !== null) {
25293 $this->addMainKey($mainNode, array($name => array($subName => $value)));
25294 } else {
25295 $this->addMainKey($mainNode, array($name => $value));
25296 }
25297
25298 return true;
25299 }
25300
25301
25302  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
25303 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
25304
25305 try {
25306 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
25307 return false;
25308 }
25309 } catch (\RuntimeException $e) {
25310 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
25311 return false;
25312 }
25313 throw $e;
25314 }
25315
25316 $children = $match['content'];
25317
25318  if (!@json_decode($children)) {
25319 return false;
25320 }
25321
25322 $that = $this;
25323
25324
25325  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
25326 if ($this->pregMatch($childRegex, $children, $matches)) {
25327 $children = preg_replace_callback($childRegex, function ($matches) use ($subName, $value, $that) {
25328 if ($subName !== null) {
25329 $curVal = json_decode($matches['content'], true);
25330 if (!is_array($curVal)) {
25331 $curVal = array();
25332 }
25333 $curVal[$subName] = $value;
25334 $value = $curVal;
25335 }
25336
25337 return $matches['start'] . $that->format($value, 1) . $matches['end'];
25338 }, $children);
25339 } else {
25340 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
25341
25342 $whitespace = '';
25343 if (!empty($match['trailingspace'])) {
25344 $whitespace = $match['trailingspace'];
25345 }
25346
25347 if (!empty($match['content'])) {
25348 if ($subName !== null) {
25349 $value = array($subName => $value);
25350 }
25351
25352
25353  $children = preg_replace(
25354 '#'.$whitespace.'}$#',
25355 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
25356 $children
25357 );
25358 } else {
25359 if ($subName !== null) {
25360 $value = array($subName => $value);
25361 }
25362
25363
25364  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
25365 }
25366 }
25367
25368 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
25369 return $m['start'] . $children . $m['end'];
25370 }, $this->contents);
25371
25372 return true;
25373 }
25374
25375 public function removeSubNode($mainNode, $name)
25376 {
25377 $decoded = JsonFile::parseJson($this->contents);
25378
25379
25380  if (empty($decoded[$mainNode])) {
25381 return true;
25382 }
25383
25384
25385  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
25386 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
25387 try {
25388 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
25389 return false;
25390 }
25391 } catch (\RuntimeException $e) {
25392 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
25393 return false;
25394 }
25395 throw $e;
25396 }
25397
25398 $children = $match['content'];
25399
25400
25401  if (!@json_decode($children, true)) {
25402 return false;
25403 }
25404
25405 $subName = null;
25406 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
25407 list($name, $subName) = explode('.', $name, 2);
25408 }
25409
25410
25411  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
25412 return true;
25413 }
25414
25415
25416  $keyRegex = str_replace('/', '\\\\?/', preg_quote($name));
25417 if ($this->pregMatch('{"'.$keyRegex.'"\s*:}i', $children)) {
25418
25419  if (preg_match_all('{'.self::$DEFINES.'"'.$keyRegex.'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
25420 $bestMatch = '';
25421 foreach ($matches[0] as $match) {
25422 if (strlen($bestMatch) < strlen($match)) {
25423 $bestMatch = $match;
25424 }
25425 }
25426 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
25427 if (1 !== $count) {
25428 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
25429 if (1 !== $count) {
25430 return false;
25431 }
25432 }
25433 }
25434 } else {
25435 $childrenClean = $children;
25436 }
25437
25438
25439  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
25440 if (empty($match['content'])) {
25441 $newline = $this->newline;
25442 $indent = $this->indent;
25443
25444 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
25445 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
25446 }, $this->contents);
25447
25448
25449  if ($subName !== null) {
25450 $curVal = json_decode($children, true);
25451 unset($curVal[$name][$subName]);
25452 $this->addSubNode($mainNode, $name, $curVal[$name]);
25453 }
25454
25455 return true;
25456 }
25457
25458 $that = $this;
25459 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
25460 if ($subName !== null) {
25461 $curVal = json_decode($matches['content'], true);
25462 unset($curVal[$name][$subName]);
25463 $childrenClean = $that->format($curVal, 0);
25464 }
25465
25466 return $matches['start'] . $childrenClean . $matches['end'];
25467 }, $this->contents);
25468
25469 return true;
25470 }
25471
25472 public function addMainKey($key, $content)
25473 {
25474 $decoded = JsonFile::parseJson($this->contents);
25475 $content = $this->format($content);
25476
25477
25478  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
25479 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
25480 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
25481
25482  if (!@json_decode('{'.$matches['key'].'}')) {
25483 return false;
25484 }
25485
25486 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
25487
25488 return true;
25489 }
25490
25491
25492  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
25493 $this->contents = preg_replace(
25494 '#'.$match[1].'\}$#',
25495 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
25496 $this->contents
25497 );
25498
25499 return true;
25500 }
25501
25502
25503  $this->contents = preg_replace(
25504 '#\}$#',
25505 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
25506 $this->contents
25507 );
25508
25509 return true;
25510 }
25511
25512 public function removeMainKey($key)
25513 {
25514 $decoded = JsonFile::parseJson($this->contents);
25515
25516 if (!array_key_exists($key, $decoded)) {
25517 return true;
25518 }
25519
25520
25521  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
25522 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
25523 if ($this->pregMatch($regex, $this->contents, $matches)) {
25524
25525  if (!@json_decode('{'.$matches['removal'].'}')) {
25526 return false;
25527 }
25528
25529
25530  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
25531 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
25532 }
25533
25534 $this->contents = $matches['start'] . $matches['end'];
25535 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
25536 $this->contents = "{\n}";
25537 }
25538
25539 return true;
25540 }
25541
25542 return false;
25543 }
25544
25545 public function format($data, $depth = 0)
25546 {
25547 if (is_array($data)) {
25548 reset($data);
25549
25550 if (is_numeric(key($data))) {
25551 foreach ($data as $key => $val) {
25552 $data[$key] = $this->format($val, $depth + 1);
25553 }
25554
25555 return '['.implode(', ', $data).']';
25556 }
25557
25558 $out = '{' . $this->newline;
25559 $elems = array();
25560 foreach ($data as $key => $val) {
25561 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
25562 }
25563
25564 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
25565 }
25566
25567 return JsonFile::encode($data);
25568 }
25569
25570 protected function detectIndenting()
25571 {
25572 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
25573 $this->indent = $match[1];
25574 } else {
25575 $this->indent = '    ';
25576 }
25577 }
25578
25579 protected function pregMatch($re, $str, &$matches = array())
25580 {
25581 $count = preg_match($re, $str, $matches);
25582
25583 if ($count === false) {
25584 switch (preg_last_error()) {
25585 case PREG_NO_ERROR:
25586 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
25587 case PREG_INTERNAL_ERROR:
25588 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
25589 case PREG_BACKTRACK_LIMIT_ERROR:
25590 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
25591 case PREG_RECURSION_LIMIT_ERROR:
25592 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
25593 case PREG_BAD_UTF8_ERROR:
25594 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
25595 case PREG_BAD_UTF8_OFFSET_ERROR:
25596 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
25597 case 6: 
25598  if (PHP_VERSION_ID > 70000) {
25599 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
25600 }
25601
25602  default:
25603 throw new \RuntimeException('Failed to execute regex: Unknown error');
25604 }
25605 }
25606
25607 return $count;
25608 }
25609 }
25610 <?php
25611
25612
25613
25614
25615
25616
25617
25618
25619
25620
25621
25622 namespace Composer\Json;
25623
25624 use Exception;
25625
25626
25627
25628
25629 class JsonValidationException extends Exception
25630 {
25631 protected $errors;
25632
25633 public function __construct($message, $errors = array(), Exception $previous = null)
25634 {
25635 $this->errors = $errors;
25636 parent::__construct($message, 0, $previous);
25637 }
25638
25639 public function getErrors()
25640 {
25641 return $this->errors;
25642 }
25643 }
25644 <?php
25645
25646
25647
25648
25649
25650
25651
25652
25653
25654
25655
25656 namespace Composer\Package;
25657
25658 use Composer\Semver\Constraint\Constraint;
25659 use Composer\Package\Version\VersionParser;
25660
25661
25662
25663
25664 class AliasPackage extends BasePackage implements CompletePackageInterface
25665 {
25666 protected $version;
25667 protected $prettyVersion;
25668 protected $dev;
25669 protected $rootPackageAlias = false;
25670 protected $stability;
25671
25672
25673 protected $aliasOf;
25674
25675 protected $requires;
25676
25677 protected $devRequires;
25678
25679 protected $conflicts;
25680
25681 protected $provides;
25682
25683 protected $replaces;
25684
25685
25686
25687
25688
25689
25690
25691
25692 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
25693 {
25694 parent::__construct($aliasOf->getName());
25695
25696 $this->version = $version;
25697 $this->prettyVersion = $prettyVersion;
25698 $this->aliasOf = $aliasOf;
25699 $this->stability = VersionParser::parseStability($version);
25700 $this->dev = $this->stability === 'dev';
25701
25702 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
25703 $links = $aliasOf->{'get' . ucfirst($type)}();
25704 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
25705 }
25706 }
25707
25708
25709
25710
25711 public function getAliasOf()
25712 {
25713 return $this->aliasOf;
25714 }
25715
25716
25717
25718
25719 public function getVersion()
25720 {
25721 return $this->version;
25722 }
25723
25724
25725
25726
25727 public function getStability()
25728 {
25729 return $this->stability;
25730 }
25731
25732
25733
25734
25735 public function getPrettyVersion()
25736 {
25737 return $this->prettyVersion;
25738 }
25739
25740
25741
25742
25743 public function isDev()
25744 {
25745 return $this->dev;
25746 }
25747
25748
25749
25750
25751 public function getRequires()
25752 {
25753 return $this->requires;
25754 }
25755
25756
25757
25758
25759 public function getConflicts()
25760 {
25761 return $this->conflicts;
25762 }
25763
25764
25765
25766
25767 public function getProvides()
25768 {
25769 return $this->provides;
25770 }
25771
25772
25773
25774
25775 public function getReplaces()
25776 {
25777 return $this->replaces;
25778 }
25779
25780
25781
25782
25783 public function getDevRequires()
25784 {
25785 return $this->devRequires;
25786 }
25787
25788
25789
25790
25791
25792
25793
25794
25795
25796
25797 public function setRootPackageAlias($value)
25798 {
25799 return $this->rootPackageAlias = $value;
25800 }
25801
25802
25803
25804
25805
25806 public function isRootPackageAlias()
25807 {
25808 return $this->rootPackageAlias;
25809 }
25810
25811
25812
25813
25814
25815
25816
25817 protected function replaceSelfVersionDependencies(array $links, $linkType)
25818 {
25819 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
25820 $newLinks = array();
25821 foreach ($links as $link) {
25822
25823  if ('self.version' === $link->getPrettyConstraint()) {
25824 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
25825 }
25826 }
25827 $links = array_merge($links, $newLinks);
25828 } else {
25829 foreach ($links as $index => $link) {
25830 if ('self.version' === $link->getPrettyConstraint()) {
25831 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
25832 }
25833 }
25834 }
25835
25836 return $links;
25837 }
25838
25839
25840
25841
25842
25843 public function getType()
25844 {
25845 return $this->aliasOf->getType();
25846 }
25847
25848 public function getTargetDir()
25849 {
25850 return $this->aliasOf->getTargetDir();
25851 }
25852
25853 public function getExtra()
25854 {
25855 return $this->aliasOf->getExtra();
25856 }
25857
25858 public function setInstallationSource($type)
25859 {
25860 $this->aliasOf->setInstallationSource($type);
25861 }
25862
25863 public function getInstallationSource()
25864 {
25865 return $this->aliasOf->getInstallationSource();
25866 }
25867
25868 public function getSourceType()
25869 {
25870 return $this->aliasOf->getSourceType();
25871 }
25872
25873 public function getSourceUrl()
25874 {
25875 return $this->aliasOf->getSourceUrl();
25876 }
25877
25878 public function getSourceUrls()
25879 {
25880 return $this->aliasOf->getSourceUrls();
25881 }
25882
25883 public function getSourceReference()
25884 {
25885 return $this->aliasOf->getSourceReference();
25886 }
25887
25888 public function setSourceReference($reference)
25889 {
25890 return $this->aliasOf->setSourceReference($reference);
25891 }
25892
25893 public function setSourceMirrors($mirrors)
25894 {
25895 return $this->aliasOf->setSourceMirrors($mirrors);
25896 }
25897
25898 public function getSourceMirrors()
25899 {
25900 return $this->aliasOf->getSourceMirrors();
25901 }
25902
25903 public function getDistType()
25904 {
25905 return $this->aliasOf->getDistType();
25906 }
25907
25908 public function getDistUrl()
25909 {
25910 return $this->aliasOf->getDistUrl();
25911 }
25912
25913 public function getDistUrls()
25914 {
25915 return $this->aliasOf->getDistUrls();
25916 }
25917
25918 public function getDistReference()
25919 {
25920 return $this->aliasOf->getDistReference();
25921 }
25922
25923 public function setDistReference($reference)
25924 {
25925 return $this->aliasOf->setDistReference($reference);
25926 }
25927
25928 public function getDistSha1Checksum()
25929 {
25930 return $this->aliasOf->getDistSha1Checksum();
25931 }
25932
25933 public function setTransportOptions(array $options)
25934 {
25935 return $this->aliasOf->setTransportOptions($options);
25936 }
25937
25938 public function getTransportOptions()
25939 {
25940 return $this->aliasOf->getTransportOptions();
25941 }
25942
25943 public function setDistMirrors($mirrors)
25944 {
25945 return $this->aliasOf->setDistMirrors($mirrors);
25946 }
25947
25948 public function getDistMirrors()
25949 {
25950 return $this->aliasOf->getDistMirrors();
25951 }
25952
25953 public function getScripts()
25954 {
25955 return $this->aliasOf->getScripts();
25956 }
25957
25958 public function getLicense()
25959 {
25960 return $this->aliasOf->getLicense();
25961 }
25962
25963 public function getAutoload()
25964 {
25965 return $this->aliasOf->getAutoload();
25966 }
25967
25968 public function getDevAutoload()
25969 {
25970 return $this->aliasOf->getDevAutoload();
25971 }
25972
25973 public function getIncludePaths()
25974 {
25975 return $this->aliasOf->getIncludePaths();
25976 }
25977
25978 public function getRepositories()
25979 {
25980 return $this->aliasOf->getRepositories();
25981 }
25982
25983 public function getReleaseDate()
25984 {
25985 return $this->aliasOf->getReleaseDate();
25986 }
25987
25988 public function getBinaries()
25989 {
25990 return $this->aliasOf->getBinaries();
25991 }
25992
25993 public function getKeywords()
25994 {
25995 return $this->aliasOf->getKeywords();
25996 }
25997
25998 public function getDescription()
25999 {
26000 return $this->aliasOf->getDescription();
26001 }
26002
26003 public function getHomepage()
26004 {
26005 return $this->aliasOf->getHomepage();
26006 }
26007
26008 public function getSuggests()
26009 {
26010 return $this->aliasOf->getSuggests();
26011 }
26012
26013 public function getAuthors()
26014 {
26015 return $this->aliasOf->getAuthors();
26016 }
26017
26018 public function getSupport()
26019 {
26020 return $this->aliasOf->getSupport();
26021 }
26022
26023 public function getNotificationUrl()
26024 {
26025 return $this->aliasOf->getNotificationUrl();
26026 }
26027
26028 public function getArchiveExcludes()
26029 {
26030 return $this->aliasOf->getArchiveExcludes();
26031 }
26032
26033 public function isAbandoned()
26034 {
26035 return $this->aliasOf->isAbandoned();
26036 }
26037
26038 public function getReplacementPackage()
26039 {
26040 return $this->aliasOf->getReplacementPackage();
26041 }
26042
26043 public function __toString()
26044 {
26045 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
26046 }
26047
26048 public function setDistUrl($url)
26049 {
26050 return $this->aliasOf->setDistUrl($url);
26051 }
26052
26053 public function setDistType($type)
26054 {
26055 return $this->aliasOf->setDistType($type);
26056 }
26057 }
26058 <?php
26059
26060
26061
26062
26063
26064
26065
26066
26067
26068
26069
26070 namespace Composer\Package\Archiver;
26071
26072 use FilterIterator;
26073 use PharData;
26074
26075 class ArchivableFilesFilter extends FilterIterator
26076 {
26077 private $dirs = array();
26078
26079
26080
26081
26082 public function accept()
26083 {
26084 $file = $this->getInnerIterator()->current();
26085 if ($file->isDir()) {
26086 $this->dirs[] = (string) $file;
26087
26088 return false;
26089 }
26090
26091 return true;
26092 }
26093
26094 public function addEmptyDir(PharData $phar, $sources)
26095 {
26096 foreach ($this->dirs as $filepath) {
26097 $localname = str_replace($sources . "/", '', $filepath);
26098 $phar->addEmptyDir($localname);
26099 }
26100 }
26101 }
26102 <?php
26103
26104
26105
26106
26107
26108
26109
26110
26111
26112
26113
26114 namespace Composer\Package\Archiver;
26115
26116 use Composer\Util\Filesystem;
26117 use FilesystemIterator;
26118 use Symfony\Component\Finder\Finder;
26119 use Symfony\Component\Finder\SplFileInfo;
26120
26121
26122
26123
26124
26125
26126
26127
26128
26129 class ArchivableFilesFinder extends \FilterIterator
26130 {
26131
26132
26133
26134 protected $finder;
26135
26136
26137
26138
26139
26140
26141
26142
26143 public function __construct($sources, array $excludes, $ignoreFilters = false)
26144 {
26145 $fs = new Filesystem();
26146
26147 $sources = $fs->normalizePath($sources);
26148
26149 if ($ignoreFilters) {
26150 $filters = array();
26151 } else {
26152 $filters = array(
26153 new HgExcludeFilter($sources),
26154 new GitExcludeFilter($sources),
26155 new ComposerExcludeFilter($sources, $excludes),
26156 );
26157 }
26158
26159 $this->finder = new Finder();
26160
26161 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
26162 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
26163 return false;
26164 }
26165
26166 $relativePath = preg_replace(
26167 '#^'.preg_quote($sources, '#').'#',
26168 '',
26169 $fs->normalizePath($file->getRealPath())
26170 );
26171
26172 $exclude = false;
26173 foreach ($filters as $filter) {
26174 $exclude = $filter->filter($relativePath, $exclude);
26175 }
26176
26177 return !$exclude;
26178 };
26179
26180 if (method_exists($filter, 'bindTo')) {
26181 $filter = $filter->bindTo(null);
26182 }
26183
26184 $this->finder
26185 ->in($sources)
26186 ->filter($filter)
26187 ->ignoreVCS(true)
26188 ->ignoreDotFiles(false);
26189
26190 parent::__construct($this->finder->getIterator());
26191 }
26192
26193 public function accept()
26194 {
26195
26196 $current = $this->getInnerIterator()->current();
26197
26198 if (!$current->isDir()) {
26199 return true;
26200 }
26201
26202 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
26203
26204 return !$iterator->valid();
26205 }
26206 }
26207 <?php
26208
26209
26210
26211
26212
26213
26214
26215
26216
26217
26218
26219 namespace Composer\Package\Archiver;
26220
26221 use Composer\Downloader\DownloadManager;
26222 use Composer\Package\PackageInterface;
26223 use Composer\Package\RootPackageInterface;
26224 use Composer\Util\Filesystem;
26225 use Composer\Json\JsonFile;
26226
26227
26228
26229
26230
26231 class ArchiveManager
26232 {
26233 protected $downloadManager;
26234
26235 protected $archivers = array();
26236
26237
26238
26239
26240 protected $overwriteFiles = true;
26241
26242
26243
26244
26245 public function __construct(DownloadManager $downloadManager)
26246 {
26247 $this->downloadManager = $downloadManager;
26248 }
26249
26250
26251
26252
26253 public function addArchiver(ArchiverInterface $archiver)
26254 {
26255 $this->archivers[] = $archiver;
26256 }
26257
26258
26259
26260
26261
26262
26263
26264
26265 public function setOverwriteFiles($overwriteFiles)
26266 {
26267 $this->overwriteFiles = $overwriteFiles;
26268
26269 return $this;
26270 }
26271
26272
26273
26274
26275
26276
26277
26278
26279 public function getPackageFilename(PackageInterface $package)
26280 {
26281 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
26282
26283 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
26284 array_push($nameParts, $package->getDistReference(), $package->getDistType());
26285 } else {
26286 array_push($nameParts, $package->getPrettyVersion(), $package->getDistReference());
26287 }
26288
26289 if ($package->getSourceReference()) {
26290 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
26291 }
26292
26293 $name = implode('-', array_filter($nameParts, function ($p) {
26294 return !empty($p);
26295 }));
26296
26297 return str_replace('/', '-', $name);
26298 }
26299
26300
26301
26302
26303
26304
26305
26306
26307
26308
26309
26310
26311
26312
26313 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
26314 {
26315 if (empty($format)) {
26316 throw new \InvalidArgumentException('Format must be specified');
26317 }
26318
26319
26320  $usableArchiver = null;
26321 foreach ($this->archivers as $archiver) {
26322 if ($archiver->supports($format, $package->getSourceType())) {
26323 $usableArchiver = $archiver;
26324 break;
26325 }
26326 }
26327
26328
26329  if (null === $usableArchiver) {
26330 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
26331 }
26332
26333 $filesystem = new Filesystem();
26334 if (null === $fileName) {
26335 $packageName = $this->getPackageFilename($package);
26336 } else {
26337 $packageName = $fileName;
26338 }
26339
26340
26341  $filesystem->ensureDirectoryExists($targetDir);
26342 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
26343 $filesystem->ensureDirectoryExists(dirname($target));
26344
26345 if (!$this->overwriteFiles && file_exists($target)) {
26346 return $target;
26347 }
26348
26349 if ($package instanceof RootPackageInterface) {
26350 $sourcePath = realpath('.');
26351 } else {
26352
26353  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
26354 $filesystem->ensureDirectoryExists($sourcePath);
26355
26356 try {
26357
26358  $this->downloadManager->download($package, $sourcePath);
26359 } catch (\Exception $e) {
26360 $filesystem->removeDirectory($sourcePath);
26361 throw $e;
26362 }
26363
26364
26365  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
26366 $jsonFile = new JsonFile($composerJsonPath);
26367 $jsonData = $jsonFile->read();
26368 if (!empty($jsonData['archive']['exclude'])) {
26369 $package->setArchiveExcludes($jsonData['archive']['exclude']);
26370 }
26371 }
26372 }
26373
26374
26375  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
26376 $filesystem->ensureDirectoryExists(dirname($tempTarget));
26377
26378 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
26379 $filesystem->rename($archivePath, $target);
26380
26381
26382  if (!$package instanceof RootPackageInterface) {
26383 $filesystem->removeDirectory($sourcePath);
26384 }
26385 $filesystem->remove($tempTarget);
26386
26387 return $target;
26388 }
26389 }
26390 <?php
26391
26392
26393
26394
26395
26396
26397
26398
26399
26400
26401
26402 namespace Composer\Package\Archiver;
26403
26404
26405
26406
26407
26408
26409 interface ArchiverInterface
26410 {
26411
26412
26413
26414
26415
26416
26417
26418
26419
26420
26421 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
26422
26423
26424
26425
26426
26427
26428
26429
26430
26431 public function supports($format, $sourceType);
26432 }
26433 <?php
26434
26435
26436
26437
26438
26439
26440
26441
26442
26443
26444
26445 namespace Composer\Package\Archiver;
26446
26447 use Symfony\Component\Finder;
26448
26449
26450
26451
26452 abstract class BaseExcludeFilter
26453 {
26454
26455
26456
26457 protected $sourcePath;
26458
26459
26460
26461
26462 protected $excludePatterns;
26463
26464
26465
26466
26467 public function __construct($sourcePath)
26468 {
26469 $this->sourcePath = $sourcePath;
26470 $this->excludePatterns = array();
26471 }
26472
26473
26474
26475
26476
26477
26478
26479
26480
26481
26482
26483 public function filter($relativePath, $exclude)
26484 {
26485 foreach ($this->excludePatterns as $patternData) {
26486 list($pattern, $negate, $stripLeadingSlash) = $patternData;
26487
26488 if ($stripLeadingSlash) {
26489 $path = substr($relativePath, 1);
26490 } else {
26491 $path = $relativePath;
26492 }
26493
26494 if (preg_match($pattern, $path)) {
26495 $exclude = !$negate;
26496 }
26497 }
26498
26499 return $exclude;
26500 }
26501
26502
26503
26504
26505
26506
26507
26508
26509
26510 protected function parseLines(array $lines, $lineParser)
26511 {
26512 return array_filter(
26513 array_map(
26514 function ($line) use ($lineParser) {
26515 $line = trim($line);
26516
26517 if (!$line || 0 === strpos($line, '#')) {
26518 return null;
26519 }
26520
26521 return call_user_func($lineParser, $line);
26522 },
26523 $lines
26524 ),
26525 function ($pattern) {
26526 return $pattern !== null;
26527 }
26528 );
26529 }
26530
26531
26532
26533
26534
26535
26536
26537
26538 protected function generatePatterns($rules)
26539 {
26540 $patterns = array();
26541 foreach ($rules as $rule) {
26542 $patterns[] = $this->generatePattern($rule);
26543 }
26544
26545 return $patterns;
26546 }
26547
26548
26549
26550
26551
26552
26553
26554
26555 protected function generatePattern($rule)
26556 {
26557 $negate = false;
26558 $pattern = '{';
26559
26560 if (strlen($rule) && $rule[0] === '!') {
26561 $negate = true;
26562 $rule = substr($rule, 1);
26563 }
26564
26565 if (strlen($rule) && $rule[0] === '/') {
26566 $pattern .= '^/';
26567 $rule = substr($rule, 1);
26568 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
26569 $pattern .= '/';
26570 $rule = substr($rule, 0, -1);
26571 } elseif (false === strpos($rule, '/')) {
26572 $pattern .= '/';
26573 }
26574
26575
26576  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
26577
26578 return array($pattern . '}', $negate, false);
26579 }
26580 }
26581 <?php
26582
26583
26584
26585
26586
26587
26588
26589
26590
26591
26592
26593 namespace Composer\Package\Archiver;
26594
26595
26596
26597
26598
26599
26600 class ComposerExcludeFilter extends BaseExcludeFilter
26601 {
26602
26603
26604
26605
26606 public function __construct($sourcePath, array $excludeRules)
26607 {
26608 parent::__construct($sourcePath);
26609 $this->excludePatterns = $this->generatePatterns($excludeRules);
26610 }
26611 }
26612 <?php
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622
26623
26624 namespace Composer\Package\Archiver;
26625
26626
26627
26628
26629
26630
26631
26632
26633 class GitExcludeFilter extends BaseExcludeFilter
26634 {
26635
26636
26637
26638
26639
26640 public function __construct($sourcePath)
26641 {
26642 parent::__construct($sourcePath);
26643
26644 if (file_exists($sourcePath.'/.gitignore')) {
26645 $this->excludePatterns = $this->parseLines(
26646 file($sourcePath.'/.gitignore'),
26647 array($this, 'parseGitIgnoreLine')
26648 );
26649 }
26650 if (file_exists($sourcePath.'/.gitattributes')) {
26651 $this->excludePatterns = array_merge(
26652 $this->excludePatterns,
26653 $this->parseLines(
26654 file($sourcePath.'/.gitattributes'),
26655 array($this, 'parseGitAttributesLine')
26656 )
26657 );
26658 }
26659 }
26660
26661
26662
26663
26664
26665
26666
26667
26668 public function parseGitIgnoreLine($line)
26669 {
26670 return $this->generatePattern($line);
26671 }
26672
26673
26674
26675
26676
26677
26678
26679
26680 public function parseGitAttributesLine($line)
26681 {
26682 $parts = preg_split('#\s+#', $line);
26683
26684 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
26685 return $this->generatePattern($parts[0]);
26686 }
26687
26688 return null;
26689 }
26690 }
26691 <?php
26692
26693
26694
26695
26696
26697
26698
26699
26700
26701
26702
26703 namespace Composer\Package\Archiver;
26704
26705 use Symfony\Component\Finder;
26706
26707
26708
26709
26710
26711
26712 class HgExcludeFilter extends BaseExcludeFilter
26713 {
26714 const HG_IGNORE_REGEX = 1;
26715 const HG_IGNORE_GLOB = 2;
26716
26717
26718
26719
26720
26721 protected $patternMode;
26722
26723
26724
26725
26726
26727
26728 public function __construct($sourcePath)
26729 {
26730 parent::__construct($sourcePath);
26731
26732 $this->patternMode = self::HG_IGNORE_REGEX;
26733
26734 if (file_exists($sourcePath.'/.hgignore')) {
26735 $this->excludePatterns = $this->parseLines(
26736 file($sourcePath.'/.hgignore'),
26737 array($this, 'parseHgIgnoreLine')
26738 );
26739 }
26740 }
26741
26742
26743
26744
26745
26746
26747
26748
26749 public function parseHgIgnoreLine($line)
26750 {
26751 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
26752 if ($matches[1] === 'glob') {
26753 $this->patternMode = self::HG_IGNORE_GLOB;
26754 } else {
26755 $this->patternMode = self::HG_IGNORE_REGEX;
26756 }
26757
26758 return null;
26759 }
26760
26761 if ($this->patternMode == self::HG_IGNORE_GLOB) {
26762 return $this->patternFromGlob($line);
26763 }
26764
26765 return $this->patternFromRegex($line);
26766 }
26767
26768
26769
26770
26771
26772
26773
26774
26775 protected function patternFromGlob($line)
26776 {
26777 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
26778 $pattern = str_replace('[^/]*', '.*', $pattern);
26779
26780 return array($pattern, false, true);
26781 }
26782
26783
26784
26785
26786
26787
26788
26789
26790 public function patternFromRegex($line)
26791 {
26792
26793  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
26794
26795 return array($pattern, false, true);
26796 }
26797 }
26798 <?php
26799
26800
26801
26802
26803
26804
26805
26806
26807
26808
26809
26810 namespace Composer\Package\Archiver;
26811
26812
26813
26814
26815
26816
26817 class PharArchiver implements ArchiverInterface
26818 {
26819 protected static $formats = array(
26820 'zip' => \Phar::ZIP,
26821 'tar' => \Phar::TAR,
26822 'tar.gz' => \Phar::TAR,
26823 'tar.bz2' => \Phar::TAR,
26824 );
26825
26826 protected static $compressFormats = array(
26827 'tar.gz' => \Phar::GZ,
26828 'tar.bz2' => \Phar::BZ2,
26829 );
26830
26831
26832
26833
26834 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
26835 {
26836 $sources = realpath($sources);
26837
26838
26839  if (file_exists($target)) {
26840 unlink($target);
26841 }
26842
26843 try {
26844 $filename = substr($target, 0, strrpos($target, $format) - 1);
26845
26846
26847  if (isset(static::$compressFormats[$format])) {
26848
26849  $target = $filename . '.tar';
26850 }
26851
26852 $phar = new \PharData($target, null, null, static::$formats[$format]);
26853 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
26854 $filesOnly = new ArchivableFilesFilter($files);
26855 $phar->buildFromIterator($filesOnly, $sources);
26856 $filesOnly->addEmptyDir($phar, $sources);
26857
26858 if (isset(static::$compressFormats[$format])) {
26859
26860  if (!$phar->canCompress(static::$compressFormats[$format])) {
26861 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
26862 }
26863
26864
26865  unlink($target);
26866
26867
26868  $phar->compress(static::$compressFormats[$format]);
26869
26870
26871  $target = $filename . '.' . $format;
26872 }
26873
26874 return $target;
26875 } catch (\UnexpectedValueException $e) {
26876 $message = sprintf(
26877 "Could not create archive '%s' from '%s': %s",
26878 $target,
26879 $sources,
26880 $e->getMessage()
26881 );
26882
26883 throw new \RuntimeException($message, $e->getCode(), $e);
26884 }
26885 }
26886
26887
26888
26889
26890 public function supports($format, $sourceType)
26891 {
26892 return isset(static::$formats[$format]);
26893 }
26894 }
26895 <?php
26896
26897
26898
26899
26900
26901
26902
26903
26904
26905
26906
26907 namespace Composer\Package\Archiver;
26908
26909 use ZipArchive;
26910 use Composer\Util\Filesystem;
26911
26912
26913
26914
26915 class ZipArchiver implements ArchiverInterface
26916 {
26917 protected static $formats = array(
26918 'zip' => 1,
26919 );
26920
26921
26922
26923
26924 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
26925 {
26926 $fs = new Filesystem();
26927 $sources = $fs->normalizePath($sources);
26928
26929 $zip = new ZipArchive();
26930 $res = $zip->open($target, ZipArchive::CREATE);
26931 if ($res === true) {
26932 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
26933 foreach ($files as $file) {
26934
26935 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
26936 $localname = str_replace($sources.'/', '', $filepath);
26937 if ($file->isDir()) {
26938 $zip->addEmptyDir($localname);
26939 } else {
26940 $zip->addFile($filepath, $localname);
26941 }
26942 }
26943 if ($zip->close()) {
26944 return $target;
26945 }
26946 }
26947 $message = sprintf(
26948 "Could not create archive '%s' from '%s': %s",
26949 $target,
26950 $sources,
26951 $zip->getStatusString()
26952 );
26953 throw new \RuntimeException($message);
26954 }
26955
26956
26957
26958
26959 public function supports($format, $sourceType)
26960 {
26961 return isset(static::$formats[$format]) && $this->compressionAvailable();
26962 }
26963
26964 private function compressionAvailable()
26965 {
26966 return class_exists('ZipArchive');
26967 }
26968 }
26969 <?php
26970
26971
26972
26973
26974
26975
26976
26977
26978
26979
26980
26981 namespace Composer\Package;
26982
26983 use Composer\Repository\RepositoryInterface;
26984 use Composer\Repository\PlatformRepository;
26985
26986
26987
26988
26989
26990
26991 abstract class BasePackage implements PackageInterface
26992 {
26993 public static $supportedLinkTypes = array(
26994 'require' => array('description' => 'requires', 'method' => 'requires'),
26995 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
26996 'provide' => array('description' => 'provides', 'method' => 'provides'),
26997 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
26998 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
26999 );
27000
27001 const STABILITY_STABLE = 0;
27002 const STABILITY_RC = 5;
27003 const STABILITY_BETA = 10;
27004 const STABILITY_ALPHA = 15;
27005 const STABILITY_DEV = 20;
27006
27007 public static $stabilities = array(
27008 'stable' => self::STABILITY_STABLE,
27009 'RC' => self::STABILITY_RC,
27010 'beta' => self::STABILITY_BETA,
27011 'alpha' => self::STABILITY_ALPHA,
27012 'dev' => self::STABILITY_DEV,
27013 );
27014
27015
27016
27017
27018
27019 public $id;
27020
27021 protected $name;
27022
27023 protected $prettyName;
27024
27025 protected $repository;
27026
27027 protected $transportOptions = array();
27028
27029
27030
27031
27032
27033
27034 public function __construct($name)
27035 {
27036 $this->prettyName = $name;
27037 $this->name = strtolower($name);
27038 $this->id = -1;
27039 }
27040
27041
27042
27043
27044 public function getName()
27045 {
27046 return $this->name;
27047 }
27048
27049
27050
27051
27052 public function getPrettyName()
27053 {
27054 return $this->prettyName;
27055 }
27056
27057
27058
27059
27060 public function getNames()
27061 {
27062 $names = array(
27063 $this->getName() => true,
27064 );
27065
27066 foreach ($this->getProvides() as $link) {
27067 $names[$link->getTarget()] = true;
27068 }
27069
27070 foreach ($this->getReplaces() as $link) {
27071 $names[$link->getTarget()] = true;
27072 }
27073
27074 return array_keys($names);
27075 }
27076
27077
27078
27079
27080 public function setId($id)
27081 {
27082 $this->id = $id;
27083 }
27084
27085
27086
27087
27088 public function getId()
27089 {
27090 return $this->id;
27091 }
27092
27093
27094
27095
27096 public function setRepository(RepositoryInterface $repository)
27097 {
27098 if ($this->repository && $repository !== $this->repository) {
27099 throw new \LogicException('A package can only be added to one repository');
27100 }
27101 $this->repository = $repository;
27102 }
27103
27104
27105
27106
27107 public function getRepository()
27108 {
27109 return $this->repository;
27110 }
27111
27112
27113
27114
27115 public function getTransportOptions()
27116 {
27117 return $this->transportOptions;
27118 }
27119
27120
27121
27122
27123
27124
27125 public function setTransportOptions(array $options)
27126 {
27127 $this->transportOptions = $options;
27128 }
27129
27130
27131
27132
27133
27134
27135 public function isPlatform()
27136 {
27137 return $this->getRepository() instanceof PlatformRepository;
27138 }
27139
27140
27141
27142
27143
27144
27145 public function getUniqueName()
27146 {
27147 return $this->getName().'-'.$this->getVersion();
27148 }
27149
27150 public function equals(PackageInterface $package)
27151 {
27152 $self = $this;
27153 if ($this instanceof AliasPackage) {
27154 $self = $this->getAliasOf();
27155 }
27156 if ($package instanceof AliasPackage) {
27157 $package = $package->getAliasOf();
27158 }
27159
27160 return $package === $self;
27161 }
27162
27163
27164
27165
27166
27167
27168 public function __toString()
27169 {
27170 return $this->getUniqueName();
27171 }
27172
27173 public function getPrettyString()
27174 {
27175 return $this->getPrettyName().' '.$this->getPrettyVersion();
27176 }
27177
27178
27179
27180
27181 public function getFullPrettyVersion($truncate = true)
27182 {
27183 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
27184 return $this->getPrettyVersion();
27185 }
27186
27187
27188  if ($truncate && strlen($this->getSourceReference()) === 40) {
27189 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
27190 }
27191
27192 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
27193 }
27194
27195 public function getStabilityPriority()
27196 {
27197 return self::$stabilities[$this->getStability()];
27198 }
27199
27200 public function __clone()
27201 {
27202 $this->repository = null;
27203 $this->id = -1;
27204 }
27205
27206
27207
27208
27209
27210
27211
27212
27213 public static function packageNameToRegexp($whiteListedPattern, $wrap = '{^%s$}i')
27214 {
27215 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
27216
27217 return sprintf($wrap, $cleanedWhiteListedPattern);
27218 }
27219 }
27220 <?php
27221
27222
27223
27224
27225
27226
27227
27228
27229
27230
27231
27232 namespace Composer\Package\Comparer;
27233
27234
27235
27236
27237
27238
27239 class Comparer
27240 {
27241 private $source;
27242 private $update;
27243 private $changed;
27244
27245 public function setSource($source)
27246 {
27247 $this->source = $source;
27248 }
27249
27250 public function setUpdate($update)
27251 {
27252 $this->update = $update;
27253 }
27254
27255 public function getChanged($toString = false, $explicated = false)
27256 {
27257 $changed = $this->changed;
27258 if (!count($changed)) {
27259 return false;
27260 }
27261 if ($explicated) {
27262 foreach ($changed as $sectionKey => $itemSection) {
27263 foreach ($itemSection as $itemKey => $item) {
27264 $changed[$sectionKey][$itemKey] = $item.' ('.$sectionKey.')';
27265 }
27266 }
27267 }
27268
27269 if ($toString) {
27270 foreach ($changed as $sectionKey => $itemSection) {
27271 foreach ($itemSection as $itemKey => $item) {
27272 $changed['string'][] = $item."\r\n";
27273 }
27274 }
27275 $changed = implode("\r\n", $changed['string']);
27276 }
27277
27278 return $changed;
27279 }
27280
27281 public function doCompare()
27282 {
27283 $source = array();
27284 $destination = array();
27285 $this->changed = array();
27286 $currentDirectory = getcwd();
27287 chdir($this->source);
27288 $source = $this->doTree('.', $source);
27289 if (!is_array($source)) {
27290 return;
27291 }
27292 chdir($currentDirectory);
27293 chdir($this->update);
27294 $destination = $this->doTree('.', $destination);
27295 if (!is_array($destination)) {
27296 exit;
27297 }
27298 chdir($currentDirectory);
27299 foreach ($source as $dir => $value) {
27300 foreach ($value as $file => $hash) {
27301 if (isset($destination[$dir][$file])) {
27302 if ($hash !== $destination[$dir][$file]) {
27303 $this->changed['changed'][] = $dir.'/'.$file;
27304 }
27305 } else {
27306 $this->changed['removed'][] = $dir.'/'.$file;
27307 }
27308 }
27309 }
27310 foreach ($destination as $dir => $value) {
27311 foreach ($value as $file => $hash) {
27312 if (!isset($source[$dir][$file])) {
27313 $this->changed['added'][] = $dir.'/'.$file;
27314 }
27315 }
27316 }
27317 }
27318
27319 private function doTree($dir, &$array)
27320 {
27321 if ($dh = opendir($dir)) {
27322 while ($file = readdir($dh)) {
27323 if ($file !== '.' && $file !== '..') {
27324 if (is_dir($dir.'/'.$file)) {
27325 if (!count($array)) {
27326 $array[0] = 'Temp';
27327 }
27328 if (!$this->doTree($dir.'/'.$file, $array)) {
27329 return false;
27330 }
27331 } else {
27332 if (filesize($dir.'/'.$file)) {
27333 set_time_limit(30);
27334 $array[$dir][$file] = md5_file($dir.'/'.$file);
27335 }
27336 }
27337 }
27338 }
27339 if (count($array) > 1 && isset($array['0'])) {
27340 unset($array['0']);
27341 }
27342
27343 return $array;
27344 }
27345
27346 return false;
27347 }
27348 }
27349 <?php
27350
27351
27352
27353
27354
27355
27356
27357
27358
27359
27360
27361 namespace Composer\Package;
27362
27363
27364
27365
27366
27367
27368 class CompletePackage extends Package implements CompletePackageInterface
27369 {
27370 protected $repositories;
27371 protected $license = array();
27372 protected $keywords;
27373 protected $authors;
27374 protected $description;
27375 protected $homepage;
27376 protected $scripts = array();
27377 protected $support = array();
27378 protected $abandoned = false;
27379
27380
27381
27382
27383 public function setScripts(array $scripts)
27384 {
27385 $this->scripts = $scripts;
27386 }
27387
27388
27389
27390
27391 public function getScripts()
27392 {
27393 return $this->scripts;
27394 }
27395
27396
27397
27398
27399
27400
27401 public function setRepositories($repositories)
27402 {
27403 $this->repositories = $repositories;
27404 }
27405
27406
27407
27408
27409 public function getRepositories()
27410 {
27411 return $this->repositories;
27412 }
27413
27414
27415
27416
27417
27418
27419 public function setLicense(array $license)
27420 {
27421 $this->license = $license;
27422 }
27423
27424
27425
27426
27427 public function getLicense()
27428 {
27429 return $this->license;
27430 }
27431
27432
27433
27434
27435
27436
27437 public function setKeywords(array $keywords)
27438 {
27439 $this->keywords = $keywords;
27440 }
27441
27442
27443
27444
27445 public function getKeywords()
27446 {
27447 return $this->keywords;
27448 }
27449
27450
27451
27452
27453
27454
27455 public function setAuthors(array $authors)
27456 {
27457 $this->authors = $authors;
27458 }
27459
27460
27461
27462
27463 public function getAuthors()
27464 {
27465 return $this->authors;
27466 }
27467
27468
27469
27470
27471
27472
27473 public function setDescription($description)
27474 {
27475 $this->description = $description;
27476 }
27477
27478
27479
27480
27481 public function getDescription()
27482 {
27483 return $this->description;
27484 }
27485
27486
27487
27488
27489
27490
27491 public function setHomepage($homepage)
27492 {
27493 $this->homepage = $homepage;
27494 }
27495
27496
27497
27498
27499 public function getHomepage()
27500 {
27501 return $this->homepage;
27502 }
27503
27504
27505
27506
27507
27508
27509 public function setSupport(array $support)
27510 {
27511 $this->support = $support;
27512 }
27513
27514
27515
27516
27517 public function getSupport()
27518 {
27519 return $this->support;
27520 }
27521
27522
27523
27524
27525 public function isAbandoned()
27526 {
27527 return (bool) $this->abandoned;
27528 }
27529
27530
27531
27532
27533 public function setAbandoned($abandoned)
27534 {
27535 $this->abandoned = $abandoned;
27536 }
27537
27538
27539
27540
27541
27542
27543 public function getReplacementPackage()
27544 {
27545 return is_string($this->abandoned) ? $this->abandoned : null;
27546 }
27547 }
27548 <?php
27549
27550
27551
27552
27553
27554
27555
27556
27557
27558
27559
27560 namespace Composer\Package;
27561
27562
27563
27564
27565
27566
27567 interface CompletePackageInterface extends PackageInterface
27568 {
27569
27570
27571
27572
27573
27574 public function getScripts();
27575
27576
27577
27578
27579
27580
27581
27582
27583 public function getRepositories();
27584
27585
27586
27587
27588
27589
27590 public function getLicense();
27591
27592
27593
27594
27595
27596
27597 public function getKeywords();
27598
27599
27600
27601
27602
27603
27604 public function getDescription();
27605
27606
27607
27608
27609
27610
27611 public function getHomepage();
27612
27613
27614
27615
27616
27617
27618
27619
27620 public function getAuthors();
27621
27622
27623
27624
27625
27626
27627 public function getSupport();
27628
27629
27630
27631
27632
27633
27634 public function isAbandoned();
27635
27636
27637
27638
27639
27640
27641 public function getReplacementPackage();
27642 }
27643 <?php
27644
27645
27646
27647
27648
27649
27650
27651
27652
27653
27654
27655 namespace Composer\Package\Dumper;
27656
27657 use Composer\Package\BasePackage;
27658 use Composer\Package\PackageInterface;
27659 use Composer\Package\CompletePackageInterface;
27660 use Composer\Package\RootPackageInterface;
27661
27662
27663
27664
27665
27666 class ArrayDumper
27667 {
27668 public function dump(PackageInterface $package)
27669 {
27670 $keys = array(
27671 'binaries' => 'bin',
27672 'type',
27673 'extra',
27674 'installationSource' => 'installation-source',
27675 'autoload',
27676 'devAutoload' => 'autoload-dev',
27677 'notificationUrl' => 'notification-url',
27678 'includePaths' => 'include-path',
27679 );
27680
27681 $data = array();
27682 $data['name'] = $package->getPrettyName();
27683 $data['version'] = $package->getPrettyVersion();
27684 $data['version_normalized'] = $package->getVersion();
27685
27686 if ($package->getTargetDir()) {
27687 $data['target-dir'] = $package->getTargetDir();
27688 }
27689
27690 if ($package->getSourceType()) {
27691 $data['source']['type'] = $package->getSourceType();
27692 $data['source']['url'] = $package->getSourceUrl();
27693 if (null !== ($value = $package->getSourceReference())) {
27694 $data['source']['reference'] = $value;
27695 }
27696 if ($mirrors = $package->getSourceMirrors()) {
27697 $data['source']['mirrors'] = $mirrors;
27698 }
27699 }
27700
27701 if ($package->getDistType()) {
27702 $data['dist']['type'] = $package->getDistType();
27703 $data['dist']['url'] = $package->getDistUrl();
27704 if (null !== ($value = $package->getDistReference())) {
27705 $data['dist']['reference'] = $value;
27706 }
27707 if (null !== ($value = $package->getDistSha1Checksum())) {
27708 $data['dist']['shasum'] = $value;
27709 }
27710 if ($mirrors = $package->getDistMirrors()) {
27711 $data['dist']['mirrors'] = $mirrors;
27712 }
27713 }
27714
27715 if ($package->getArchiveExcludes()) {
27716 $data['archive']['exclude'] = $package->getArchiveExcludes();
27717 }
27718
27719 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
27720 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
27721 foreach ($links as $link) {
27722 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
27723 }
27724 ksort($data[$type]);
27725 }
27726 }
27727
27728 if ($packages = $package->getSuggests()) {
27729 ksort($packages);
27730 $data['suggest'] = $packages;
27731 }
27732
27733 if ($package->getReleaseDate()) {
27734 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
27735 }
27736
27737 $data = $this->dumpValues($package, $keys, $data);
27738
27739 if ($package instanceof CompletePackageInterface) {
27740 $keys = array(
27741 'scripts',
27742 'license',
27743 'authors',
27744 'description',
27745 'homepage',
27746 'keywords',
27747 'repositories',
27748 'support',
27749 );
27750
27751 $data = $this->dumpValues($package, $keys, $data);
27752
27753 if (isset($data['keywords']) && is_array($data['keywords'])) {
27754 sort($data['keywords']);
27755 }
27756
27757 if ($package->isAbandoned()) {
27758 $data['abandoned'] = $package->getReplacementPackage() ?: true;
27759 }
27760 }
27761
27762 if ($package instanceof RootPackageInterface) {
27763 $minimumStability = $package->getMinimumStability();
27764 if ($minimumStability) {
27765 $data['minimum-stability'] = $minimumStability;
27766 }
27767 }
27768
27769 if (count($package->getTransportOptions()) > 0) {
27770 $data['transport-options'] = $package->getTransportOptions();
27771 }
27772
27773 return $data;
27774 }
27775
27776 private function dumpValues(PackageInterface $package, array $keys, array $data)
27777 {
27778 foreach ($keys as $method => $key) {
27779 if (is_numeric($method)) {
27780 $method = $key;
27781 }
27782
27783 $getter = 'get'.ucfirst($method);
27784 $value = $package->$getter();
27785
27786 if (null !== $value && !(is_array($value) && 0 === count($value))) {
27787 $data[$key] = $value;
27788 }
27789 }
27790
27791 return $data;
27792 }
27793 }
27794 <?php
27795
27796
27797
27798
27799
27800
27801
27802
27803
27804
27805
27806 namespace Composer\Package;
27807
27808 use Composer\Semver\Constraint\ConstraintInterface;
27809
27810
27811
27812
27813
27814
27815 class Link
27816 {
27817
27818
27819
27820 protected $source;
27821
27822
27823
27824
27825 protected $target;
27826
27827
27828
27829
27830 protected $constraint;
27831
27832
27833
27834
27835 protected $description;
27836
27837
27838
27839
27840 protected $prettyConstraint;
27841
27842
27843
27844
27845
27846
27847
27848
27849
27850
27851 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
27852 {
27853 $this->source = strtolower($source);
27854 $this->target = strtolower($target);
27855 $this->constraint = $constraint;
27856 $this->description = $description;
27857 $this->prettyConstraint = $prettyConstraint;
27858 }
27859
27860
27861
27862
27863 public function getDescription()
27864 {
27865 return $this->description;
27866 }
27867
27868
27869
27870
27871 public function getSource()
27872 {
27873 return $this->source;
27874 }
27875
27876
27877
27878
27879 public function getTarget()
27880 {
27881 return $this->target;
27882 }
27883
27884
27885
27886
27887 public function getConstraint()
27888 {
27889 return $this->constraint;
27890 }
27891
27892
27893
27894
27895
27896 public function getPrettyConstraint()
27897 {
27898 if (null === $this->prettyConstraint) {
27899 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
27900 }
27901
27902 return $this->prettyConstraint;
27903 }
27904
27905
27906
27907
27908 public function __toString()
27909 {
27910 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
27911 }
27912
27913
27914
27915
27916
27917 public function getPrettyString(PackageInterface $sourcePackage)
27918 {
27919 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
27920 }
27921 }
27922 <?php
27923
27924
27925
27926
27927
27928
27929
27930
27931
27932
27933
27934 namespace Composer\Package\LinkConstraint;
27935
27936 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
27937
27938 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
27939
27940
27941
27942
27943 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
27944 {
27945 }
27946 <?php
27947
27948
27949
27950
27951
27952
27953
27954
27955
27956
27957
27958 namespace Composer\Package\LinkConstraint;
27959
27960 use Composer\Semver\Constraint\ConstraintInterface;
27961
27962 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
27963
27964
27965
27966
27967 interface LinkConstraintInterface extends ConstraintInterface
27968 {
27969 }
27970 <?php
27971
27972
27973
27974
27975
27976
27977
27978
27979
27980
27981
27982 namespace Composer\Package\LinkConstraint;
27983
27984 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
27985
27986 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
27987
27988
27989
27990
27991 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
27992 {
27993 }
27994 <?php
27995
27996
27997
27998
27999
28000
28001
28002
28003
28004
28005
28006 namespace Composer\Package\LinkConstraint;
28007
28008 use Composer\Semver\Constraint\AbstractConstraint;
28009
28010 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
28011
28012
28013
28014
28015 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
28016 {
28017 }
28018 <?php
28019
28020
28021
28022
28023
28024
28025
28026
28027
28028
28029
28030 namespace Composer\Package\LinkConstraint;
28031
28032 use Composer\Semver\Constraint\Constraint;
28033
28034 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
28035
28036
28037
28038
28039 class VersionConstraint extends Constraint implements LinkConstraintInterface
28040 {
28041 }
28042 <?php
28043
28044
28045
28046
28047
28048
28049
28050
28051
28052
28053
28054 namespace Composer\Package\Loader;
28055
28056 use Composer\Package;
28057 use Composer\Package\AliasPackage;
28058 use Composer\Package\Link;
28059 use Composer\Package\RootAliasPackage;
28060 use Composer\Package\RootPackageInterface;
28061 use Composer\Package\Version\VersionParser;
28062 use Composer\Semver\VersionParser as SemverVersionParser;
28063
28064
28065
28066
28067
28068 class ArrayLoader implements LoaderInterface
28069 {
28070 protected $versionParser;
28071 protected $loadOptions;
28072
28073 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
28074 {
28075 if (!$parser) {
28076 $parser = new VersionParser;
28077 }
28078 $this->versionParser = $parser;
28079 $this->loadOptions = $loadOptions;
28080 }
28081
28082 public function load(array $config, $class = 'Composer\Package\CompletePackage')
28083 {
28084 if (!isset($config['name'])) {
28085 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
28086 }
28087 if (!isset($config['version'])) {
28088 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
28089 }
28090
28091
28092  if (isset($config['version_normalized'])) {
28093 $version = $config['version_normalized'];
28094 } else {
28095 $version = $this->versionParser->normalize($config['version']);
28096 }
28097 $package = new $class($config['name'], $version, $config['version']);
28098 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
28099
28100 if (isset($config['target-dir'])) {
28101 $package->setTargetDir($config['target-dir']);
28102 }
28103
28104 if (isset($config['extra']) && is_array($config['extra'])) {
28105 $package->setExtra($config['extra']);
28106 }
28107
28108 if (isset($config['bin'])) {
28109 foreach ((array) $config['bin'] as $key => $bin) {
28110 $config['bin'][$key] = ltrim($bin, '/');
28111 }
28112 $package->setBinaries((array) $config['bin']);
28113 }
28114
28115 if (isset($config['installation-source'])) {
28116 $package->setInstallationSource($config['installation-source']);
28117 }
28118
28119 if (isset($config['source'])) {
28120 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
28121 throw new \UnexpectedValueException(sprintf(
28122 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
28123 $config['name'],
28124 json_encode($config['source'])
28125 ));
28126 }
28127 $package->setSourceType($config['source']['type']);
28128 $package->setSourceUrl($config['source']['url']);
28129 $package->setSourceReference(isset($config['source']['reference']) ? $config['source']['reference'] : null);
28130 if (isset($config['source']['mirrors'])) {
28131 $package->setSourceMirrors($config['source']['mirrors']);
28132 }
28133 }
28134
28135 if (isset($config['dist'])) {
28136 if (!isset($config['dist']['type'])
28137 || !isset($config['dist']['url'])) {
28138 throw new \UnexpectedValueException(sprintf(
28139 "Package %s's dist key should be specified as ".
28140 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
28141 $config['name'],
28142 json_encode($config['dist'])
28143 ));
28144 }
28145 $package->setDistType($config['dist']['type']);
28146 $package->setDistUrl($config['dist']['url']);
28147 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
28148 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
28149 if (isset($config['dist']['mirrors'])) {
28150 $package->setDistMirrors($config['dist']['mirrors']);
28151 }
28152 }
28153
28154 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
28155 if (isset($config[$type])) {
28156 $method = 'set'.ucfirst($opts['method']);
28157 $package->{$method}(
28158 $this->parseLinks(
28159 $package->getName(),
28160 $package->getPrettyVersion(),
28161 $opts['description'],
28162 $config[$type]
28163 )
28164 );
28165 }
28166 }
28167
28168 if (isset($config['suggest']) && is_array($config['suggest'])) {
28169 foreach ($config['suggest'] as $target => $reason) {
28170 if ('self.version' === trim($reason)) {
28171 $config['suggest'][$target] = $package->getPrettyVersion();
28172 }
28173 }
28174 $package->setSuggests($config['suggest']);
28175 }
28176
28177 if (isset($config['autoload'])) {
28178 $package->setAutoload($config['autoload']);
28179 }
28180
28181 if (isset($config['autoload-dev'])) {
28182 $package->setDevAutoload($config['autoload-dev']);
28183 }
28184
28185 if (isset($config['include-path'])) {
28186 $package->setIncludePaths($config['include-path']);
28187 }
28188
28189 if (!empty($config['time'])) {
28190 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
28191
28192 try {
28193 $date = new \DateTime($time, new \DateTimeZone('UTC'));
28194 $package->setReleaseDate($date);
28195 } catch (\Exception $e) {
28196 }
28197 }
28198
28199 if (!empty($config['notification-url'])) {
28200 $package->setNotificationUrl($config['notification-url']);
28201 }
28202
28203 if (!empty($config['archive']['exclude'])) {
28204 $package->setArchiveExcludes($config['archive']['exclude']);
28205 }
28206
28207 if ($package instanceof Package\CompletePackageInterface) {
28208 if (isset($config['scripts']) && is_array($config['scripts'])) {
28209 foreach ($config['scripts'] as $event => $listeners) {
28210 $config['scripts'][$event] = (array) $listeners;
28211 }
28212 if (isset($config['scripts']['composer'])) {
28213 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
28214 }
28215 $package->setScripts($config['scripts']);
28216 }
28217
28218 if (!empty($config['description']) && is_string($config['description'])) {
28219 $package->setDescription($config['description']);
28220 }
28221
28222 if (!empty($config['homepage']) && is_string($config['homepage'])) {
28223 $package->setHomepage($config['homepage']);
28224 }
28225
28226 if (!empty($config['keywords']) && is_array($config['keywords'])) {
28227 $package->setKeywords($config['keywords']);
28228 }
28229
28230 if (!empty($config['license'])) {
28231 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
28232 }
28233
28234 if (!empty($config['authors']) && is_array($config['authors'])) {
28235 $package->setAuthors($config['authors']);
28236 }
28237
28238 if (isset($config['support'])) {
28239 $package->setSupport($config['support']);
28240 }
28241
28242 if (isset($config['abandoned'])) {
28243 $package->setAbandoned($config['abandoned']);
28244 }
28245 }
28246
28247 if ($aliasNormalized = $this->getBranchAlias($config)) {
28248 if ($package instanceof RootPackageInterface) {
28249 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
28250 } else {
28251 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
28252 }
28253 }
28254
28255 if ($this->loadOptions && isset($config['transport-options'])) {
28256 $package->setTransportOptions($config['transport-options']);
28257 }
28258
28259 return $package;
28260 }
28261
28262
28263
28264
28265
28266
28267
28268
28269 public function parseLinks($source, $sourceVersion, $description, $links)
28270 {
28271 $res = array();
28272 foreach ($links as $target => $constraint) {
28273 if (!is_string($constraint)) {
28274 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
28275 }
28276 if ('self.version' === $constraint) {
28277 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
28278 } else {
28279 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
28280 }
28281
28282 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
28283 }
28284
28285 return $res;
28286 }
28287
28288
28289
28290
28291
28292
28293
28294 public function getBranchAlias(array $config)
28295 {
28296 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
28297 || !isset($config['extra']['branch-alias'])
28298 || !is_array($config['extra']['branch-alias'])
28299 ) {
28300 return;
28301 }
28302
28303 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
28304
28305  if ('-dev' !== substr($targetBranch, -4)) {
28306 continue;
28307 }
28308
28309
28310  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
28311 if ('-dev' !== substr($validatedTargetBranch, -4)) {
28312 continue;
28313 }
28314
28315
28316  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
28317 continue;
28318 }
28319
28320
28321  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
28322 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
28323 && (stripos($targetPrefix, $sourcePrefix) !== 0)
28324 ) {
28325 continue;
28326 }
28327
28328 return $validatedTargetBranch;
28329 }
28330 }
28331 }
28332 <?php
28333
28334
28335
28336
28337
28338
28339
28340
28341
28342
28343
28344 namespace Composer\Package\Loader;
28345
28346
28347
28348
28349 class InvalidPackageException extends \Exception
28350 {
28351 private $errors;
28352 private $warnings;
28353 private $data;
28354
28355 public function __construct(array $errors, array $warnings, array $data)
28356 {
28357 $this->errors = $errors;
28358 $this->warnings = $warnings;
28359 $this->data = $data;
28360 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
28361 }
28362
28363 public function getData()
28364 {
28365 return $this->data;
28366 }
28367
28368 public function getErrors()
28369 {
28370 return $this->errors;
28371 }
28372
28373 public function getWarnings()
28374 {
28375 return $this->warnings;
28376 }
28377 }
28378 <?php
28379
28380
28381
28382
28383
28384
28385
28386
28387
28388
28389
28390 namespace Composer\Package\Loader;
28391
28392 use Composer\Json\JsonFile;
28393
28394
28395
28396
28397 class JsonLoader
28398 {
28399 private $loader;
28400
28401 public function __construct(LoaderInterface $loader)
28402 {
28403 $this->loader = $loader;
28404 }
28405
28406
28407
28408
28409
28410 public function load($json)
28411 {
28412 if ($json instanceof JsonFile) {
28413 $config = $json->read();
28414 } elseif (file_exists($json)) {
28415 $config = JsonFile::parseJson(file_get_contents($json), $json);
28416 } elseif (is_string($json)) {
28417 $config = JsonFile::parseJson($json);
28418 }
28419
28420 return $this->loader->load($config);
28421 }
28422 }
28423 <?php
28424
28425
28426
28427
28428
28429
28430
28431
28432
28433
28434
28435 namespace Composer\Package\Loader;
28436
28437
28438
28439
28440
28441
28442 interface LoaderInterface
28443 {
28444
28445
28446
28447
28448
28449
28450
28451 public function load(array $package, $class = 'Composer\Package\CompletePackage');
28452 }
28453 <?php
28454
28455
28456
28457
28458
28459
28460
28461
28462
28463
28464
28465 namespace Composer\Package\Loader;
28466
28467 use Composer\Package\BasePackage;
28468 use Composer\Package\AliasPackage;
28469 use Composer\Config;
28470 use Composer\IO\IOInterface;
28471 use Composer\Package\RootPackageInterface;
28472 use Composer\Repository\RepositoryFactory;
28473 use Composer\Package\Version\VersionGuesser;
28474 use Composer\Package\Version\VersionParser;
28475 use Composer\Repository\RepositoryManager;
28476 use Composer\Util\ProcessExecutor;
28477
28478
28479
28480
28481
28482
28483
28484
28485 class RootPackageLoader extends ArrayLoader
28486 {
28487
28488
28489
28490 private $manager;
28491
28492
28493
28494
28495 private $config;
28496
28497
28498
28499
28500 private $versionGuesser;
28501
28502
28503
28504
28505 private $io;
28506
28507 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null, IOInterface $io = null)
28508 {
28509 parent::__construct($parser);
28510
28511 $this->manager = $manager;
28512 $this->config = $config;
28513 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
28514 $this->io = $io;
28515 }
28516
28517
28518
28519
28520
28521
28522
28523 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
28524 {
28525 if (!isset($config['name'])) {
28526 $config['name'] = '__root__';
28527 } elseif ($this->io) {
28528 if ($err = ValidatingArrayLoader::hasPackageNamingError($config['name'])) {
28529 $this->io->writeError('<warning>Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
28530 }
28531 }
28532 $autoVersioned = false;
28533 if (!isset($config['version'])) {
28534 $commit = null;
28535
28536
28537  if (getenv('COMPOSER_ROOT_VERSION')) {
28538 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
28539 } else {
28540 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
28541 if ($versionData) {
28542 $config['version'] = $versionData['pretty_version'];
28543 $config['version_normalized'] = $versionData['version'];
28544 $commit = $versionData['commit'];
28545 }
28546 }
28547
28548 if (!isset($config['version'])) {
28549 $config['version'] = '1.0.0';
28550 $autoVersioned = true;
28551 }
28552
28553 if ($commit) {
28554 $config['source'] = array(
28555 'type' => '',
28556 'url' => '',
28557 'reference' => $commit,
28558 );
28559 $config['dist'] = array(
28560 'type' => '',
28561 'url' => '',
28562 'reference' => $commit,
28563 );
28564 }
28565 }
28566
28567 $realPackage = $package = parent::load($config, $class);
28568 if ($realPackage instanceof AliasPackage) {
28569 $realPackage = $package->getAliasOf();
28570 }
28571
28572 if ($autoVersioned) {
28573 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
28574 }
28575
28576 if (isset($config['minimum-stability'])) {
28577 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
28578 }
28579
28580 $aliases = array();
28581 $stabilityFlags = array();
28582 $references = array();
28583 foreach (array('require', 'require-dev') as $linkType) {
28584 if (isset($config[$linkType])) {
28585 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
28586 $method = 'get'.ucfirst($linkInfo['method']);
28587 $links = array();
28588 foreach ($realPackage->$method() as $link) {
28589 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
28590 }
28591 $aliases = $this->extractAliases($links, $aliases);
28592 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
28593 $references = $this->extractReferences($links, $references);
28594 }
28595 }
28596
28597 if ($this->io) {
28598 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
28599 if (isset($config[$linkType])) {
28600 foreach ($config[$linkType] as $linkName => $constraint) {
28601 if ($err = ValidatingArrayLoader::hasPackageNamingError($linkName, true)) {
28602 $this->io->writeError('<warning>Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
28603 }
28604 }
28605 }
28606 }
28607 }
28608
28609 if (isset($links[$config['name']])) {
28610 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
28611 'Did you accidentally name your root package after an external package?', $config['name']));
28612 }
28613
28614 $realPackage->setAliases($aliases);
28615 $realPackage->setStabilityFlags($stabilityFlags);
28616 $realPackage->setReferences($references);
28617
28618 if (isset($config['prefer-stable'])) {
28619 $realPackage->setPreferStable((bool) $config['prefer-stable']);
28620 }
28621
28622 if (isset($config['config'])) {
28623 $realPackage->setConfig($config['config']);
28624 }
28625
28626 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
28627 foreach ($repos as $repo) {
28628 $this->manager->addRepository($repo);
28629 }
28630 $realPackage->setRepositories($this->config->getRepositories());
28631
28632 return $package;
28633 }
28634
28635 private function extractAliases(array $requires, array $aliases)
28636 {
28637 foreach ($requires as $reqName => $reqVersion) {
28638 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
28639 $aliases[] = array(
28640 'package' => strtolower($reqName),
28641 'version' => $this->versionParser->normalize($match[1], $reqVersion),
28642 'alias' => $match[2],
28643 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
28644 );
28645 }
28646 }
28647
28648 return $aliases;
28649 }
28650
28651 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
28652 {
28653 $stabilities = BasePackage::$stabilities;
28654 $minimumStability = $stabilities[$minimumStability];
28655 foreach ($requires as $reqName => $reqVersion) {
28656 $constraints = array();
28657
28658
28659  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
28660 foreach ($orSplit as $orConstraint) {
28661 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
28662 foreach ($andSplit as $andConstraint) {
28663 $constraints[] = $andConstraint;
28664 }
28665 }
28666
28667
28668  $match = false;
28669 foreach ($constraints as $constraint) {
28670 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
28671 $name = strtolower($reqName);
28672 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
28673
28674 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
28675 continue;
28676 }
28677 $stabilityFlags[$name] = $stability;
28678 $match = true;
28679 }
28680 }
28681
28682 if ($match) {
28683 continue;
28684 }
28685
28686 foreach ($constraints as $constraint) {
28687
28688  
28689  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
28690 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
28691 $name = strtolower($reqName);
28692 $stability = $stabilities[$stabilityName];
28693 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
28694 continue;
28695 }
28696 $stabilityFlags[$name] = $stability;
28697 }
28698 }
28699 }
28700
28701 return $stabilityFlags;
28702 }
28703
28704 private function extractReferences(array $requires, array $references)
28705 {
28706 foreach ($requires as $reqName => $reqVersion) {
28707 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
28708 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) {
28709 $name = strtolower($reqName);
28710 $references[$name] = $match[1];
28711 }
28712 }
28713
28714 return $references;
28715 }
28716 }
28717 <?php
28718
28719
28720
28721
28722
28723
28724
28725
28726
28727
28728
28729 namespace Composer\Package\Loader;
28730
28731 use Composer\Package\BasePackage;
28732 use Composer\Semver\Constraint\Constraint;
28733 use Composer\Package\Version\VersionParser;
28734 use Composer\Repository\PlatformRepository;
28735 use Composer\Spdx\SpdxLicenses;
28736
28737
28738
28739
28740 class ValidatingArrayLoader implements LoaderInterface
28741 {
28742 const CHECK_ALL = 3;
28743 const CHECK_UNBOUND_CONSTRAINTS = 1;
28744 const CHECK_STRICT_CONSTRAINTS = 2;
28745
28746 private $loader;
28747 private $versionParser;
28748 private $errors;
28749 private $warnings;
28750 private $config;
28751 private $strictName;
28752 private $flags;
28753
28754 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
28755 {
28756 $this->loader = $loader;
28757 $this->versionParser = $parser ?: new VersionParser();
28758 $this->strictName = $strictName;
28759 $this->flags = $flags;
28760 }
28761
28762 public function load(array $config, $class = 'Composer\Package\CompletePackage')
28763 {
28764 $this->errors = array();
28765 $this->warnings = array();
28766 $this->config = $config;
28767
28768 if ($err = self::hasPackageNamingError($config['name'])) {
28769 $this->warnings[] = 'Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.';
28770 }
28771
28772 if ($this->strictName) {
28773 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
28774 } else {
28775 $this->validateString('name', true);
28776 }
28777
28778 if (!empty($this->config['version'])) {
28779 try {
28780 $this->versionParser->normalize($this->config['version']);
28781 } catch (\Exception $e) {
28782 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
28783 unset($this->config['version']);
28784 }
28785 }
28786
28787 if (!empty($this->config['config']['platform'])) {
28788 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
28789 try {
28790 $this->versionParser->normalize($platform);
28791 } catch (\Exception $e) {
28792 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
28793 }
28794 }
28795 }
28796
28797 $this->validateRegex('type', '[A-Za-z0-9-]+');
28798 $this->validateString('target-dir');
28799 $this->validateArray('extra');
28800
28801 if (isset($this->config['bin'])) {
28802 if (is_string($this->config['bin'])) {
28803 $this->validateString('bin');
28804 } else {
28805 $this->validateFlatArray('bin');
28806 }
28807 }
28808
28809 $this->validateArray('scripts'); 
28810  $this->validateString('description');
28811 $this->validateUrl('homepage');
28812 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
28813
28814 $releaseDate = null;
28815 $this->validateString('time');
28816 if (!empty($this->config['time'])) {
28817 try {
28818 $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
28819 } catch (\Exception $e) {
28820 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
28821 unset($this->config['time']);
28822 }
28823 }
28824
28825
28826  if (isset($this->config['license']) && (!$releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days'))) {
28827 if (is_array($this->config['license']) || is_string($this->config['license'])) {
28828 $licenses = (array) $this->config['license'];
28829
28830
28831  foreach ($licenses as $key => $license) {
28832 if ('proprietary' === $license) {
28833 unset($licenses[$key]);
28834 }
28835 }
28836
28837 $licenseValidator = new SpdxLicenses();
28838 if (count($licenses) === 1 && !$licenseValidator->validate($licenses) && $licenseValidator->validate(trim($licenses[0]))) {
28839 $this->warnings[] = sprintf(
28840 'License %s must not contain extra spaces, make sure to trim it.',
28841 json_encode($this->config['license'])
28842 );
28843 } elseif (array() !== $licenses && !$licenseValidator->validate($licenses)) {
28844 $this->warnings[] = sprintf(
28845 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
28846 'If the software is closed-source, you may use "proprietary" as license.',
28847 json_encode($this->config['license'])
28848 );
28849 }
28850 }
28851 }
28852
28853 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
28854 foreach ($this->config['authors'] as $key => $author) {
28855 if (!is_array($author)) {
28856 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
28857 unset($this->config['authors'][$key]);
28858 continue;
28859 }
28860 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
28861 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
28862 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
28863 unset($this->config['authors'][$key][$authorData]);
28864 }
28865 }
28866 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
28867 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
28868 unset($this->config['authors'][$key]['homepage']);
28869 }
28870 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
28871 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
28872 unset($this->config['authors'][$key]['email']);
28873 }
28874 if (empty($this->config['authors'][$key])) {
28875 unset($this->config['authors'][$key]);
28876 }
28877 }
28878 if (empty($this->config['authors'])) {
28879 unset($this->config['authors']);
28880 }
28881 }
28882
28883 if ($this->validateArray('support') && !empty($this->config['support'])) {
28884 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss', 'chat') as $key) {
28885 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
28886 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
28887 unset($this->config['support'][$key]);
28888 }
28889 }
28890
28891 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
28892 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
28893 unset($this->config['support']['email']);
28894 }
28895
28896 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
28897 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
28898 unset($this->config['support']['irc']);
28899 }
28900
28901 foreach (array('issues', 'forum', 'wiki', 'source', 'docs', 'chat') as $key) {
28902 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
28903 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
28904 unset($this->config['support'][$key]);
28905 }
28906 }
28907 if (empty($this->config['support'])) {
28908 unset($this->config['support']);
28909 }
28910 }
28911
28912 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
28913 $stableConstraint = new Constraint('=', '1.0.0');
28914
28915 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
28916 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
28917 foreach ($this->config[$linkType] as $package => $constraint) {
28918 if ($err = self::hasPackageNamingError($package, true)) {
28919 $this->warnings[] = 'Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.';
28920 } elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
28921 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
28922 }
28923 if (!is_string($constraint)) {
28924 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
28925 unset($this->config[$linkType][$package]);
28926 } elseif ('self.version' !== $constraint) {
28927 try {
28928 $linkConstraint = $this->versionParser->parseConstraints($constraint);
28929 } catch (\Exception $e) {
28930 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
28931 unset($this->config[$linkType][$package]);
28932 continue;
28933 }
28934
28935
28936  if (
28937 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
28938 && 'require' === $linkType
28939 && $linkConstraint->matches($unboundConstraint)
28940 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
28941 ) {
28942 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
28943 } elseif (
28944
28945  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
28946 && 'require' === $linkType
28947 && substr($linkConstraint, 0, 1) === '='
28948 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
28949 ) {
28950 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
28951 }
28952 }
28953 }
28954 }
28955 }
28956
28957 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
28958 foreach ($this->config['suggest'] as $package => $description) {
28959 if (!is_string($description)) {
28960 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
28961 unset($this->config['suggest'][$package]);
28962 }
28963 }
28964 }
28965
28966 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
28967 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
28968 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
28969 unset($this->config['minimum-stability']);
28970 }
28971 }
28972
28973 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
28974 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
28975 foreach ($this->config['autoload'] as $type => $typeConfig) {
28976 if (!in_array($type, $types)) {
28977 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
28978 unset($this->config['autoload'][$type]);
28979 }
28980 if ($type === 'psr-4') {
28981 foreach ($typeConfig as $namespace => $dirs) {
28982 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
28983 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
28984 }
28985 }
28986 }
28987 }
28988 }
28989
28990 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
28991 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
28992
28993  
28994  unset($this->config['autoload']['psr-4']);
28995 }
28996
28997
28998  
28999
29000
29001  
29002
29003 $this->validateFlatArray('include-path');
29004 $this->validateArray('transport-options');
29005
29006
29007  if (isset($this->config['extra']['branch-alias'])) {
29008 if (!is_array($this->config['extra']['branch-alias'])) {
29009 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
29010 } else {
29011 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
29012
29013  if ('-dev' !== substr($targetBranch, -4)) {
29014 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
29015 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29016
29017 continue;
29018 }
29019
29020
29021  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
29022 if ('-dev' !== substr($validatedTargetBranch, -4)) {
29023 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
29024 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29025
29026 continue;
29027 }
29028
29029
29030  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
29031 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
29032 && (stripos($targetPrefix, $sourcePrefix) !== 0)
29033 ) {
29034 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
29035 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29036 }
29037 }
29038 }
29039 }
29040
29041 if ($this->errors) {
29042 throw new InvalidPackageException($this->errors, $this->warnings, $config);
29043 }
29044
29045 $package = $this->loader->load($this->config, $class);
29046 $this->config = null;
29047
29048 return $package;
29049 }
29050
29051 public function getWarnings()
29052 {
29053 return $this->warnings;
29054 }
29055
29056 public function getErrors()
29057 {
29058 return $this->errors;
29059 }
29060
29061 public static function hasPackageNamingError($name, $isLink = false)
29062 {
29063 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
29064 return;
29065 }
29066
29067 if (!preg_match('{^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9]([_.-]?[a-z0-9]+)*$}iD', $name)) {
29068 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]+)*".';
29069 }
29070
29071 $reservedNames = array('nul', 'con', 'prn', 'aux', 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9', 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9');
29072 $bits = explode('/', strtolower($name));
29073 if (in_array($bits[0], $reservedNames, true) || in_array($bits[1], $reservedNames, true)) {
29074 return $name.' is reserved, package and vendor names can not match any of: '.implode(', ', $reservedNames).'.';
29075 }
29076
29077 if (preg_match('{\.json$}', $name)) {
29078 return $name.' is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.';
29079 }
29080
29081 if (preg_match('{[A-Z]}', $name)) {
29082 if ($isLink) {
29083 return $name.' is invalid, it should not contain uppercase characters. Please use '.strtolower($name).' instead.';
29084 }
29085
29086 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
29087 $suggestName = strtolower($suggestName);
29088
29089 return $name.' is invalid, it should not contain uppercase characters. We suggest using '.$suggestName.' instead.';
29090 }
29091 }
29092
29093 private function validateRegex($property, $regex, $mandatory = false)
29094 {
29095 if (!$this->validateString($property, $mandatory)) {
29096 return false;
29097 }
29098
29099 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
29100 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
29101 if ($mandatory) {
29102 $this->errors[] = $message;
29103 } else {
29104 $this->warnings[] = $message;
29105 }
29106 unset($this->config[$property]);
29107
29108 return false;
29109 }
29110
29111 return true;
29112 }
29113
29114 private function validateString($property, $mandatory = false)
29115 {
29116 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
29117 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
29118 unset($this->config[$property]);
29119
29120 return false;
29121 }
29122
29123 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
29124 if ($mandatory) {
29125 $this->errors[] = $property.' : must be present';
29126 }
29127 unset($this->config[$property]);
29128
29129 return false;
29130 }
29131
29132 return true;
29133 }
29134
29135 private function validateArray($property, $mandatory = false)
29136 {
29137 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
29138 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
29139 unset($this->config[$property]);
29140
29141 return false;
29142 }
29143
29144 if (!isset($this->config[$property]) || !count($this->config[$property])) {
29145 if ($mandatory) {
29146 $this->errors[] = $property.' : must be present and contain at least one element';
29147 }
29148 unset($this->config[$property]);
29149
29150 return false;
29151 }
29152
29153 return true;
29154 }
29155
29156 private function validateFlatArray($property, $regex = null, $mandatory = false)
29157 {
29158 if (!$this->validateArray($property, $mandatory)) {
29159 return false;
29160 }
29161
29162 $pass = true;
29163 foreach ($this->config[$property] as $key => $value) {
29164 if (!is_string($value) && !is_numeric($value)) {
29165 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
29166 unset($this->config[$property][$key]);
29167 $pass = false;
29168
29169 continue;
29170 }
29171
29172 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
29173 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
29174 unset($this->config[$property][$key]);
29175 $pass = false;
29176 }
29177 }
29178
29179 return $pass;
29180 }
29181
29182 private function validateUrl($property, $mandatory = false)
29183 {
29184 if (!$this->validateString($property, $mandatory)) {
29185 return false;
29186 }
29187
29188 if (!$this->filterUrl($this->config[$property])) {
29189 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
29190 unset($this->config[$property]);
29191
29192 return false;
29193 }
29194
29195 return true;
29196 }
29197
29198 private function filterUrl($value, array $schemes = array('http', 'https'))
29199 {
29200 if ($value === '') {
29201 return true;
29202 }
29203
29204 $bits = parse_url($value);
29205 if (empty($bits['scheme']) || empty($bits['host'])) {
29206 return false;
29207 }
29208
29209 if (!in_array($bits['scheme'], $schemes, true)) {
29210 return false;
29211 }
29212
29213 return true;
29214 }
29215 }
29216 <?php
29217
29218
29219
29220
29221
29222
29223
29224
29225
29226
29227
29228 namespace Composer\Package;
29229
29230 use Composer\Json\JsonFile;
29231 use Composer\Installer\InstallationManager;
29232 use Composer\Repository\RepositoryManager;
29233 use Composer\Util\ProcessExecutor;
29234 use Composer\Repository\ArrayRepository;
29235 use Composer\Package\Dumper\ArrayDumper;
29236 use Composer\Package\Loader\ArrayLoader;
29237 use Composer\Util\Git as GitUtil;
29238 use Composer\IO\IOInterface;
29239 use Seld\JsonLint\ParsingException;
29240
29241
29242
29243
29244
29245
29246
29247 class Locker
29248 {
29249 private $lockFile;
29250 private $repositoryManager;
29251 private $installationManager;
29252 private $hash;
29253 private $contentHash;
29254 private $loader;
29255 private $dumper;
29256 private $process;
29257 private $lockDataCache;
29258
29259
29260
29261
29262
29263
29264
29265
29266
29267
29268 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
29269 {
29270 $this->lockFile = $lockFile;
29271 $this->repositoryManager = $repositoryManager;
29272 $this->installationManager = $installationManager;
29273 $this->hash = md5($composerFileContents);
29274 $this->contentHash = self::getContentHash($composerFileContents);
29275 $this->loader = new ArrayLoader(null, true);
29276 $this->dumper = new ArrayDumper();
29277 $this->process = new ProcessExecutor($io);
29278 }
29279
29280
29281
29282
29283
29284
29285
29286
29287 public static function getContentHash($composerFileContents)
29288 {
29289 $content = json_decode($composerFileContents, true);
29290
29291 $relevantKeys = array(
29292 'name',
29293 'version',
29294 'require',
29295 'require-dev',
29296 'conflict',
29297 'replace',
29298 'provide',
29299 'minimum-stability',
29300 'prefer-stable',
29301 'repositories',
29302 'extra',
29303 );
29304
29305 $relevantContent = array();
29306
29307 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
29308 $relevantContent[$key] = $content[$key];
29309 }
29310 if (isset($content['config']['platform'])) {
29311 $relevantContent['config']['platform'] = $content['config']['platform'];
29312 }
29313
29314 ksort($relevantContent);
29315
29316 return md5(json_encode($relevantContent));
29317 }
29318
29319
29320
29321
29322
29323
29324 public function isLocked()
29325 {
29326 if (!$this->lockFile->exists()) {
29327 return false;
29328 }
29329
29330 $data = $this->getLockData();
29331
29332 return isset($data['packages']);
29333 }
29334
29335
29336
29337
29338
29339
29340 public function isFresh()
29341 {
29342 $lock = $this->lockFile->read();
29343
29344 if (!empty($lock['content-hash'])) {
29345
29346  return $this->contentHash === $lock['content-hash'];
29347 }
29348
29349
29350  if (!empty($lock['hash'])) {
29351 return $this->hash === $lock['hash'];
29352 }
29353
29354
29355  return false;
29356 }
29357
29358
29359
29360
29361
29362
29363
29364
29365 public function getLockedRepository($withDevReqs = false)
29366 {
29367 $lockData = $this->getLockData();
29368 $packages = new ArrayRepository();
29369
29370 $lockedPackages = $lockData['packages'];
29371 if ($withDevReqs) {
29372 if (isset($lockData['packages-dev'])) {
29373 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
29374 } else {
29375 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.');
29376 }
29377 }
29378
29379 if (empty($lockedPackages)) {
29380 return $packages;
29381 }
29382
29383 if (isset($lockedPackages[0]['name'])) {
29384 foreach ($lockedPackages as $info) {
29385 $packages->addPackage($this->loader->load($info));
29386 }
29387
29388 return $packages;
29389 }
29390
29391 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.');
29392 }
29393
29394
29395
29396
29397
29398
29399
29400 public function getPlatformRequirements($withDevReqs = false)
29401 {
29402 $lockData = $this->getLockData();
29403 $requirements = array();
29404
29405 if (!empty($lockData['platform'])) {
29406 $requirements = $this->loader->parseLinks(
29407 '__ROOT__',
29408 '1.0.0',
29409 'requires',
29410 isset($lockData['platform']) ? $lockData['platform'] : array()
29411 );
29412 }
29413
29414 if ($withDevReqs && !empty($lockData['platform-dev'])) {
29415 $devRequirements = $this->loader->parseLinks(
29416 '__ROOT__',
29417 '1.0.0',
29418 'requires',
29419 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
29420 );
29421
29422 $requirements = array_merge($requirements, $devRequirements);
29423 }
29424
29425 return $requirements;
29426 }
29427
29428 public function getMinimumStability()
29429 {
29430 $lockData = $this->getLockData();
29431
29432 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
29433 }
29434
29435 public function getStabilityFlags()
29436 {
29437 $lockData = $this->getLockData();
29438
29439 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
29440 }
29441
29442 public function getPreferStable()
29443 {
29444 $lockData = $this->getLockData();
29445
29446
29447  
29448  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
29449 }
29450
29451 public function getPreferLowest()
29452 {
29453 $lockData = $this->getLockData();
29454
29455
29456  
29457  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
29458 }
29459
29460 public function getPlatformOverrides()
29461 {
29462 $lockData = $this->getLockData();
29463
29464 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
29465 }
29466
29467 public function getAliases()
29468 {
29469 $lockData = $this->getLockData();
29470
29471 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
29472 }
29473
29474 public function getLockData()
29475 {
29476 if (null !== $this->lockDataCache) {
29477 return $this->lockDataCache;
29478 }
29479
29480 if (!$this->lockFile->exists()) {
29481 throw new \LogicException('No lockfile found. Unable to read locked packages');
29482 }
29483
29484 return $this->lockDataCache = $this->lockFile->read();
29485 }
29486
29487
29488
29489
29490
29491
29492
29493
29494
29495
29496
29497
29498
29499
29500
29501
29502
29503 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
29504 {
29505 $lock = array(
29506 '_readme' => array('This file locks the dependencies of your project to a known state',
29507 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies',
29508 'This file is @gener'.'ated automatically', ),
29509 'content-hash' => $this->contentHash,
29510 'packages' => null,
29511 'packages-dev' => null,
29512 'aliases' => array(),
29513 'minimum-stability' => $minimumStability,
29514 'stability-flags' => $stabilityFlags,
29515 'prefer-stable' => $preferStable,
29516 'prefer-lowest' => $preferLowest,
29517 );
29518
29519 foreach ($aliases as $package => $versions) {
29520 foreach ($versions as $version => $alias) {
29521 $lock['aliases'][] = array(
29522 'alias' => $alias['alias'],
29523 'alias_normalized' => $alias['alias_normalized'],
29524 'version' => $version,
29525 'package' => $package,
29526 );
29527 }
29528 }
29529
29530 $lock['packages'] = $this->lockPackages($packages);
29531 if (null !== $devPackages) {
29532 $lock['packages-dev'] = $this->lockPackages($devPackages);
29533 }
29534
29535 $lock['platform'] = $platformReqs;
29536 $lock['platform-dev'] = $platformDevReqs;
29537 if ($platformOverrides) {
29538 $lock['platform-overrides'] = $platformOverrides;
29539 }
29540
29541 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
29542 if ($this->lockFile->exists()) {
29543 unlink($this->lockFile->getPath());
29544 }
29545
29546 return false;
29547 }
29548
29549 try {
29550 $isLocked = $this->isLocked();
29551 } catch (ParsingException $e) {
29552 $isLocked = false;
29553 }
29554 if (!$isLocked || $lock !== $this->getLockData()) {
29555 $this->lockFile->write($lock);
29556 $this->lockDataCache = null;
29557
29558 return true;
29559 }
29560
29561 return false;
29562 }
29563
29564 private function lockPackages(array $packages)
29565 {
29566 $locked = array();
29567
29568 foreach ($packages as $package) {
29569 if ($package instanceof AliasPackage) {
29570 continue;
29571 }
29572
29573 $name = $package->getPrettyName();
29574 $version = $package->getPrettyVersion();
29575
29576 if (!$name || !$version) {
29577 throw new \LogicException(sprintf(
29578 'Package "%s" has no version or name and can not be locked',
29579 $package
29580 ));
29581 }
29582
29583 $spec = $this->dumper->dump($package);
29584 unset($spec['version_normalized']);
29585
29586
29587  $time = isset($spec['time']) ? $spec['time'] : null;
29588 unset($spec['time']);
29589 if ($package->isDev() && $package->getInstallationSource() === 'source') {
29590
29591  $time = $this->getPackageTime($package) ?: $time;
29592 }
29593 if (null !== $time) {
29594 $spec['time'] = $time;
29595 }
29596
29597 unset($spec['installation-source']);
29598
29599 $locked[] = $spec;
29600 }
29601
29602 usort($locked, function ($a, $b) {
29603 $comparison = strcmp($a['name'], $b['name']);
29604
29605 if (0 !== $comparison) {
29606 return $comparison;
29607 }
29608
29609
29610  return strcmp($a['version'], $b['version']);
29611 });
29612
29613 return $locked;
29614 }
29615
29616
29617
29618
29619
29620
29621
29622 private function getPackageTime(PackageInterface $package)
29623 {
29624 if (!function_exists('proc_open')) {
29625 return null;
29626 }
29627
29628 $path = realpath($this->installationManager->getInstallPath($package));
29629 $sourceType = $package->getSourceType();
29630 $datetime = null;
29631
29632 if ($path && in_array($sourceType, array('git', 'hg'))) {
29633 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
29634 switch ($sourceType) {
29635 case 'git':
29636 GitUtil::cleanEnv();
29637
29638 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
29639 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
29640 }
29641 break;
29642
29643 case 'hg':
29644 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
29645 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
29646 }
29647 break;
29648 }
29649 }
29650
29651 return $datetime ? $datetime->format(DATE_RFC3339) : null;
29652 }
29653 }
29654 <?php
29655
29656
29657
29658
29659
29660
29661
29662
29663
29664
29665
29666 namespace Composer\Package;
29667
29668 use Composer\Package\Version\VersionParser;
29669 use Composer\Util\ComposerMirror;
29670
29671
29672
29673
29674
29675
29676 class Package extends BasePackage
29677 {
29678 protected $type;
29679 protected $targetDir;
29680 protected $installationSource;
29681 protected $sourceType;
29682 protected $sourceUrl;
29683 protected $sourceReference;
29684 protected $sourceMirrors;
29685 protected $distType;
29686 protected $distUrl;
29687 protected $distReference;
29688 protected $distSha1Checksum;
29689 protected $distMirrors;
29690 protected $version;
29691 protected $prettyVersion;
29692 protected $releaseDate;
29693 protected $extra = array();
29694 protected $binaries = array();
29695 protected $dev;
29696 protected $stability;
29697 protected $notificationUrl;
29698
29699
29700 protected $requires = array();
29701
29702 protected $conflicts = array();
29703
29704 protected $provides = array();
29705
29706 protected $replaces = array();
29707
29708 protected $devRequires = array();
29709 protected $suggests = array();
29710 protected $autoload = array();
29711 protected $devAutoload = array();
29712 protected $includePaths = array();
29713 protected $archiveExcludes = array();
29714
29715
29716
29717
29718
29719
29720
29721
29722 public function __construct($name, $version, $prettyVersion)
29723 {
29724 parent::__construct($name);
29725
29726 $this->version = $version;
29727 $this->prettyVersion = $prettyVersion;
29728
29729 $this->stability = VersionParser::parseStability($version);
29730 $this->dev = $this->stability === 'dev';
29731 }
29732
29733
29734
29735
29736 public function isDev()
29737 {
29738 return $this->dev;
29739 }
29740
29741
29742
29743
29744 public function setType($type)
29745 {
29746 $this->type = $type;
29747 }
29748
29749
29750
29751
29752 public function getType()
29753 {
29754 return $this->type ?: 'library';
29755 }
29756
29757
29758
29759
29760 public function getStability()
29761 {
29762 return $this->stability;
29763 }
29764
29765
29766
29767
29768 public function setTargetDir($targetDir)
29769 {
29770 $this->targetDir = $targetDir;
29771 }
29772
29773
29774
29775
29776 public function getTargetDir()
29777 {
29778 if (null === $this->targetDir) {
29779 return;
29780 }
29781
29782 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
29783 }
29784
29785
29786
29787
29788 public function setExtra(array $extra)
29789 {
29790 $this->extra = $extra;
29791 }
29792
29793
29794
29795
29796 public function getExtra()
29797 {
29798 return $this->extra;
29799 }
29800
29801
29802
29803
29804 public function setBinaries(array $binaries)
29805 {
29806 $this->binaries = $binaries;
29807 }
29808
29809
29810
29811
29812 public function getBinaries()
29813 {
29814 return $this->binaries;
29815 }
29816
29817
29818
29819
29820 public function setInstallationSource($type)
29821 {
29822 $this->installationSource = $type;
29823 }
29824
29825
29826
29827
29828 public function getInstallationSource()
29829 {
29830 return $this->installationSource;
29831 }
29832
29833
29834
29835
29836 public function setSourceType($type)
29837 {
29838 $this->sourceType = $type;
29839 }
29840
29841
29842
29843
29844 public function getSourceType()
29845 {
29846 return $this->sourceType;
29847 }
29848
29849
29850
29851
29852 public function setSourceUrl($url)
29853 {
29854 $this->sourceUrl = $url;
29855 }
29856
29857
29858
29859
29860 public function getSourceUrl()
29861 {
29862 return $this->sourceUrl;
29863 }
29864
29865
29866
29867
29868 public function setSourceReference($reference)
29869 {
29870 $this->sourceReference = $reference;
29871 }
29872
29873
29874
29875
29876 public function getSourceReference()
29877 {
29878 return $this->sourceReference;
29879 }
29880
29881
29882
29883
29884 public function setSourceMirrors($mirrors)
29885 {
29886 $this->sourceMirrors = $mirrors;
29887 }
29888
29889
29890
29891
29892 public function getSourceMirrors()
29893 {
29894 return $this->sourceMirrors;
29895 }
29896
29897
29898
29899
29900 public function getSourceUrls()
29901 {
29902 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
29903 }
29904
29905
29906
29907
29908 public function setDistType($type)
29909 {
29910 $this->distType = $type;
29911 }
29912
29913
29914
29915
29916 public function getDistType()
29917 {
29918 return $this->distType;
29919 }
29920
29921
29922
29923
29924 public function setDistUrl($url)
29925 {
29926 $this->distUrl = $url;
29927 }
29928
29929
29930
29931
29932 public function getDistUrl()
29933 {
29934 return $this->distUrl;
29935 }
29936
29937
29938
29939
29940 public function setDistReference($reference)
29941 {
29942 $this->distReference = $reference;
29943 }
29944
29945
29946
29947
29948 public function getDistReference()
29949 {
29950 return $this->distReference;
29951 }
29952
29953
29954
29955
29956 public function setDistSha1Checksum($sha1checksum)
29957 {
29958 $this->distSha1Checksum = $sha1checksum;
29959 }
29960
29961
29962
29963
29964 public function getDistSha1Checksum()
29965 {
29966 return $this->distSha1Checksum;
29967 }
29968
29969
29970
29971
29972 public function setDistMirrors($mirrors)
29973 {
29974 $this->distMirrors = $mirrors;
29975 }
29976
29977
29978
29979
29980 public function getDistMirrors()
29981 {
29982 return $this->distMirrors;
29983 }
29984
29985
29986
29987
29988 public function getDistUrls()
29989 {
29990 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
29991 }
29992
29993
29994
29995
29996 public function getVersion()
29997 {
29998 return $this->version;
29999 }
30000
30001
30002
30003
30004 public function getPrettyVersion()
30005 {
30006 return $this->prettyVersion;
30007 }
30008
30009
30010
30011
30012
30013
30014 public function setReleaseDate(\DateTime $releaseDate)
30015 {
30016 $this->releaseDate = $releaseDate;
30017 }
30018
30019
30020
30021
30022 public function getReleaseDate()
30023 {
30024 return $this->releaseDate;
30025 }
30026
30027
30028
30029
30030
30031
30032 public function setRequires(array $requires)
30033 {
30034 $this->requires = $requires;
30035 }
30036
30037
30038
30039
30040 public function getRequires()
30041 {
30042 return $this->requires;
30043 }
30044
30045
30046
30047
30048
30049
30050 public function setConflicts(array $conflicts)
30051 {
30052 $this->conflicts = $conflicts;
30053 }
30054
30055
30056
30057
30058 public function getConflicts()
30059 {
30060 return $this->conflicts;
30061 }
30062
30063
30064
30065
30066
30067
30068 public function setProvides(array $provides)
30069 {
30070 $this->provides = $provides;
30071 }
30072
30073
30074
30075
30076 public function getProvides()
30077 {
30078 return $this->provides;
30079 }
30080
30081
30082
30083
30084
30085
30086 public function setReplaces(array $replaces)
30087 {
30088 $this->replaces = $replaces;
30089 }
30090
30091
30092
30093
30094 public function getReplaces()
30095 {
30096 return $this->replaces;
30097 }
30098
30099
30100
30101
30102
30103
30104 public function setDevRequires(array $devRequires)
30105 {
30106 $this->devRequires = $devRequires;
30107 }
30108
30109
30110
30111
30112 public function getDevRequires()
30113 {
30114 return $this->devRequires;
30115 }
30116
30117
30118
30119
30120
30121
30122 public function setSuggests(array $suggests)
30123 {
30124 $this->suggests = $suggests;
30125 }
30126
30127
30128
30129
30130 public function getSuggests()
30131 {
30132 return $this->suggests;
30133 }
30134
30135
30136
30137
30138
30139
30140 public function setAutoload(array $autoload)
30141 {
30142 $this->autoload = $autoload;
30143 }
30144
30145
30146
30147
30148 public function getAutoload()
30149 {
30150 return $this->autoload;
30151 }
30152
30153
30154
30155
30156
30157
30158 public function setDevAutoload(array $devAutoload)
30159 {
30160 $this->devAutoload = $devAutoload;
30161 }
30162
30163
30164
30165
30166 public function getDevAutoload()
30167 {
30168 return $this->devAutoload;
30169 }
30170
30171
30172
30173
30174
30175
30176 public function setIncludePaths(array $includePaths)
30177 {
30178 $this->includePaths = $includePaths;
30179 }
30180
30181
30182
30183
30184 public function getIncludePaths()
30185 {
30186 return $this->includePaths;
30187 }
30188
30189
30190
30191
30192
30193
30194 public function setNotificationUrl($notificationUrl)
30195 {
30196 $this->notificationUrl = $notificationUrl;
30197 }
30198
30199
30200
30201
30202 public function getNotificationUrl()
30203 {
30204 return $this->notificationUrl;
30205 }
30206
30207
30208
30209
30210
30211
30212 public function setArchiveExcludes(array $excludes)
30213 {
30214 $this->archiveExcludes = $excludes;
30215 }
30216
30217
30218
30219
30220 public function getArchiveExcludes()
30221 {
30222 return $this->archiveExcludes;
30223 }
30224
30225
30226
30227
30228
30229
30230
30231
30232 public function replaceVersion($version, $prettyVersion)
30233 {
30234 $this->version = $version;
30235 $this->prettyVersion = $prettyVersion;
30236
30237 $this->stability = VersionParser::parseStability($version);
30238 $this->dev = $this->stability === 'dev';
30239 }
30240
30241 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
30242 {
30243 if (!$url) {
30244 return array();
30245 }
30246 $urls = array($url);
30247 if ($mirrors) {
30248 foreach ($mirrors as $mirror) {
30249 if ($urlType === 'dist') {
30250 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
30251 } elseif ($urlType === 'source' && $type === 'git') {
30252 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
30253 } elseif ($urlType === 'source' && $type === 'hg') {
30254 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
30255 }
30256 if (!in_array($mirrorUrl, $urls)) {
30257 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
30258 $func($urls, $mirrorUrl);
30259 }
30260 }
30261 }
30262
30263 return $urls;
30264 }
30265 }
30266 <?php
30267
30268
30269
30270
30271
30272
30273
30274
30275
30276
30277
30278 namespace Composer\Package;
30279
30280 use Composer\Repository\RepositoryInterface;
30281
30282
30283
30284
30285
30286
30287 interface PackageInterface
30288 {
30289
30290
30291
30292
30293
30294 public function getName();
30295
30296
30297
30298
30299
30300
30301 public function getPrettyName();
30302
30303
30304
30305
30306
30307
30308
30309
30310
30311 public function getNames();
30312
30313
30314
30315
30316
30317
30318 public function setId($id);
30319
30320
30321
30322
30323
30324
30325 public function getId();
30326
30327
30328
30329
30330
30331
30332 public function isDev();
30333
30334
30335
30336
30337
30338
30339 public function getType();
30340
30341
30342
30343
30344
30345
30346 public function getTargetDir();
30347
30348
30349
30350
30351
30352
30353 public function getExtra();
30354
30355
30356
30357
30358
30359
30360 public function setInstallationSource($type);
30361
30362
30363
30364
30365
30366
30367 public function getInstallationSource();
30368
30369
30370
30371
30372
30373
30374 public function getSourceType();
30375
30376
30377
30378
30379
30380
30381 public function getSourceUrl();
30382
30383
30384
30385
30386
30387
30388 public function getSourceUrls();
30389
30390
30391
30392
30393
30394
30395 public function getSourceReference();
30396
30397
30398
30399
30400
30401
30402 public function getSourceMirrors();
30403
30404
30405
30406
30407
30408
30409 public function getDistType();
30410
30411
30412
30413
30414
30415
30416 public function getDistUrl();
30417
30418
30419
30420
30421
30422
30423 public function getDistUrls();
30424
30425
30426
30427
30428
30429
30430 public function getDistReference();
30431
30432
30433
30434
30435
30436
30437 public function getDistSha1Checksum();
30438
30439
30440
30441
30442
30443
30444 public function getDistMirrors();
30445
30446
30447
30448
30449
30450
30451 public function getVersion();
30452
30453
30454
30455
30456
30457
30458 public function getPrettyVersion();
30459
30460
30461
30462
30463
30464
30465
30466
30467
30468 public function getFullPrettyVersion($truncate = true);
30469
30470
30471
30472
30473
30474
30475 public function getReleaseDate();
30476
30477
30478
30479
30480
30481
30482 public function getStability();
30483
30484
30485
30486
30487
30488
30489
30490 public function getRequires();
30491
30492
30493
30494
30495
30496
30497
30498 public function getConflicts();
30499
30500
30501
30502
30503
30504
30505
30506 public function getProvides();
30507
30508
30509
30510
30511
30512
30513
30514 public function getReplaces();
30515
30516
30517
30518
30519
30520
30521
30522 public function getDevRequires();
30523
30524
30525
30526
30527
30528
30529
30530 public function getSuggests();
30531
30532
30533
30534
30535
30536
30537
30538
30539
30540
30541
30542 public function getAutoload();
30543
30544
30545
30546
30547
30548
30549
30550
30551
30552
30553
30554 public function getDevAutoload();
30555
30556
30557
30558
30559
30560
30561
30562 public function getIncludePaths();
30563
30564
30565
30566
30567
30568
30569 public function setRepository(RepositoryInterface $repository);
30570
30571
30572
30573
30574
30575
30576 public function getRepository();
30577
30578
30579
30580
30581
30582
30583 public function getBinaries();
30584
30585
30586
30587
30588
30589
30590 public function getUniqueName();
30591
30592
30593
30594
30595
30596
30597 public function getNotificationUrl();
30598
30599
30600
30601
30602
30603
30604 public function __toString();
30605
30606
30607
30608
30609
30610
30611 public function getPrettyString();
30612
30613
30614
30615
30616
30617
30618 public function getArchiveExcludes();
30619
30620
30621
30622
30623
30624
30625 public function getTransportOptions();
30626
30627
30628
30629
30630
30631
30632 public function setSourceReference($reference);
30633
30634
30635
30636
30637
30638
30639 public function setDistUrl($url);
30640
30641
30642
30643
30644
30645
30646 public function setDistType($type);
30647
30648
30649
30650
30651
30652
30653 public function setDistReference($reference);
30654 }
30655 <?php
30656
30657
30658
30659
30660
30661
30662
30663
30664
30665
30666
30667 namespace Composer\Package;
30668
30669
30670
30671
30672 class RootAliasPackage extends AliasPackage implements RootPackageInterface
30673 {
30674 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
30675 {
30676 parent::__construct($aliasOf, $version, $prettyVersion);
30677 }
30678
30679
30680
30681
30682 public function getAliases()
30683 {
30684 return $this->aliasOf->getAliases();
30685 }
30686
30687
30688
30689
30690 public function getMinimumStability()
30691 {
30692 return $this->aliasOf->getMinimumStability();
30693 }
30694
30695
30696
30697
30698 public function getStabilityFlags()
30699 {
30700 return $this->aliasOf->getStabilityFlags();
30701 }
30702
30703
30704
30705
30706 public function getReferences()
30707 {
30708 return $this->aliasOf->getReferences();
30709 }
30710
30711
30712
30713
30714 public function getPreferStable()
30715 {
30716 return $this->aliasOf->getPreferStable();
30717 }
30718
30719
30720
30721
30722 public function getConfig()
30723 {
30724 return $this->aliasOf->getConfig();
30725 }
30726
30727
30728
30729
30730 public function setRequires(array $require)
30731 {
30732 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
30733
30734 $this->aliasOf->setRequires($require);
30735 }
30736
30737
30738
30739
30740 public function setDevRequires(array $devRequire)
30741 {
30742 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
30743
30744 $this->aliasOf->setDevRequires($devRequire);
30745 }
30746
30747
30748
30749
30750 public function setConflicts(array $conflicts)
30751 {
30752 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
30753 $this->aliasOf->setConflicts($conflicts);
30754 }
30755
30756
30757
30758
30759 public function setProvides(array $provides)
30760 {
30761 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
30762 $this->aliasOf->setProvides($provides);
30763 }
30764
30765
30766
30767
30768 public function setReplaces(array $replaces)
30769 {
30770 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
30771 $this->aliasOf->setReplaces($replaces);
30772 }
30773
30774
30775
30776
30777 public function setRepositories($repositories)
30778 {
30779 $this->aliasOf->setRepositories($repositories);
30780 }
30781
30782
30783
30784
30785 public function setAutoload(array $autoload)
30786 {
30787 $this->aliasOf->setAutoload($autoload);
30788 }
30789
30790
30791
30792
30793 public function setDevAutoload(array $devAutoload)
30794 {
30795 $this->aliasOf->setDevAutoload($devAutoload);
30796 }
30797
30798
30799
30800
30801 public function setStabilityFlags(array $stabilityFlags)
30802 {
30803 $this->aliasOf->setStabilityFlags($stabilityFlags);
30804 }
30805
30806
30807
30808
30809 public function setSuggests(array $suggests)
30810 {
30811 $this->aliasOf->setSuggests($suggests);
30812 }
30813
30814
30815
30816
30817 public function setExtra(array $extra)
30818 {
30819 $this->aliasOf->setExtra($extra);
30820 }
30821
30822 public function __clone()
30823 {
30824 parent::__clone();
30825 $this->aliasOf = clone $this->aliasOf;
30826 }
30827 }
30828 <?php
30829
30830
30831
30832
30833
30834
30835
30836
30837
30838
30839
30840 namespace Composer\Package;
30841
30842
30843
30844
30845
30846
30847 class RootPackage extends CompletePackage implements RootPackageInterface
30848 {
30849 protected $minimumStability = 'stable';
30850 protected $preferStable = false;
30851 protected $stabilityFlags = array();
30852 protected $config = array();
30853 protected $references = array();
30854 protected $aliases = array();
30855
30856
30857
30858
30859
30860
30861 public function setMinimumStability($minimumStability)
30862 {
30863 $this->minimumStability = $minimumStability;
30864 }
30865
30866
30867
30868
30869 public function getMinimumStability()
30870 {
30871 return $this->minimumStability;
30872 }
30873
30874
30875
30876
30877
30878
30879 public function setStabilityFlags(array $stabilityFlags)
30880 {
30881 $this->stabilityFlags = $stabilityFlags;
30882 }
30883
30884
30885
30886
30887 public function getStabilityFlags()
30888 {
30889 return $this->stabilityFlags;
30890 }
30891
30892
30893
30894
30895
30896
30897 public function setPreferStable($preferStable)
30898 {
30899 $this->preferStable = $preferStable;
30900 }
30901
30902
30903
30904
30905 public function getPreferStable()
30906 {
30907 return $this->preferStable;
30908 }
30909
30910
30911
30912
30913
30914
30915 public function setConfig(array $config)
30916 {
30917 $this->config = $config;
30918 }
30919
30920
30921
30922
30923 public function getConfig()
30924 {
30925 return $this->config;
30926 }
30927
30928
30929
30930
30931
30932
30933 public function setReferences(array $references)
30934 {
30935 $this->references = $references;
30936 }
30937
30938
30939
30940
30941 public function getReferences()
30942 {
30943 return $this->references;
30944 }
30945
30946
30947
30948
30949
30950
30951 public function setAliases(array $aliases)
30952 {
30953 $this->aliases = $aliases;
30954 }
30955
30956
30957
30958
30959 public function getAliases()
30960 {
30961 return $this->aliases;
30962 }
30963 }
30964 <?php
30965
30966
30967
30968
30969
30970
30971
30972
30973
30974
30975
30976 namespace Composer\Package;
30977
30978
30979
30980
30981
30982
30983 interface RootPackageInterface extends CompletePackageInterface
30984 {
30985
30986
30987
30988
30989
30990 public function getAliases();
30991
30992
30993
30994
30995
30996
30997 public function getMinimumStability();
30998
30999
31000
31001
31002
31003
31004
31005
31006 public function getStabilityFlags();
31007
31008
31009
31010
31011
31012
31013
31014
31015 public function getReferences();
31016
31017
31018
31019
31020
31021
31022 public function getPreferStable();
31023
31024
31025
31026
31027
31028
31029 public function getConfig();
31030
31031
31032
31033
31034
31035
31036 public function setRequires(array $requires);
31037
31038
31039
31040
31041
31042
31043 public function setDevRequires(array $devRequires);
31044
31045
31046
31047
31048
31049
31050 public function setConflicts(array $conflicts);
31051
31052
31053
31054
31055
31056
31057 public function setProvides(array $provides);
31058
31059
31060
31061
31062
31063
31064 public function setReplaces(array $replaces);
31065
31066
31067
31068
31069
31070
31071 public function setRepositories($repositories);
31072
31073
31074
31075
31076
31077
31078 public function setAutoload(array $autoload);
31079
31080
31081
31082
31083
31084
31085 public function setDevAutoload(array $devAutoload);
31086
31087
31088
31089
31090
31091
31092 public function setStabilityFlags(array $stabilityFlags);
31093
31094
31095
31096
31097
31098
31099 public function setSuggests(array $suggests);
31100
31101
31102
31103
31104 public function setExtra(array $extra);
31105 }
31106 <?php
31107
31108
31109
31110
31111
31112
31113
31114
31115
31116
31117
31118 namespace Composer\Package\Version;
31119
31120 use Composer\Config;
31121 use Composer\Repository\Vcs\HgDriver;
31122 use Composer\IO\NullIO;
31123 use Composer\Semver\VersionParser as SemverVersionParser;
31124 use Composer\Util\Git as GitUtil;
31125 use Composer\Util\ProcessExecutor;
31126 use Composer\Util\Svn as SvnUtil;
31127
31128
31129
31130
31131
31132
31133
31134 class VersionGuesser
31135 {
31136
31137
31138
31139 private $config;
31140
31141
31142
31143
31144 private $process;
31145
31146
31147
31148
31149 private $versionParser;
31150
31151
31152
31153
31154
31155
31156 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
31157 {
31158 $this->config = $config;
31159 $this->process = $process;
31160 $this->versionParser = $versionParser;
31161 }
31162
31163
31164
31165
31166
31167
31168
31169 public function guessVersion(array $packageConfig, $path)
31170 {
31171 if (function_exists('proc_open')) {
31172 $versionData = $this->guessGitVersion($packageConfig, $path);
31173 if (null !== $versionData && null !== $versionData['version']) {
31174 return $this->postprocess($versionData);
31175 }
31176
31177 $versionData = $this->guessHgVersion($packageConfig, $path);
31178 if (null !== $versionData && null !== $versionData['version']) {
31179 return $this->postprocess($versionData);
31180 }
31181
31182 $versionData = $this->guessFossilVersion($packageConfig, $path);
31183 if (null !== $versionData && null !== $versionData['version']) {
31184 return $this->postprocess($versionData);
31185 }
31186
31187 $versionData = $this->guessSvnVersion($packageConfig, $path);
31188 if (null !== $versionData && null !== $versionData['version']) {
31189 return $this->postprocess($versionData);
31190 }
31191 }
31192 }
31193
31194 private function postprocess(array $versionData)
31195 {
31196 if ('-dev' === substr($versionData['version'], -4) && preg_match('{\.9{7}}', $versionData['version'])) {
31197 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
31198 }
31199
31200 return $versionData;
31201 }
31202
31203 private function guessGitVersion(array $packageConfig, $path)
31204 {
31205 GitUtil::cleanEnv();
31206 $commit = null;
31207 $version = null;
31208 $prettyVersion = null;
31209 $isDetached = false;
31210
31211
31212  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
31213 $branches = array();
31214 $isFeatureBranch = false;
31215
31216
31217  foreach ($this->process->splitLines($output) as $branch) {
31218 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
31219 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
31220 $version = 'dev-' . $match[2];
31221 $prettyVersion = $version;
31222 $isFeatureBranch = true;
31223 $isDetached = true;
31224 } else {
31225 $version = $this->versionParser->normalizeBranch($match[1]);
31226 $prettyVersion = 'dev-' . $match[1];
31227 $isFeatureBranch = 0 === strpos($version, 'dev-');
31228 }
31229
31230 if ($match[2]) {
31231 $commit = $match[2];
31232 }
31233 }
31234
31235 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
31236 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
31237 $branches[] = $match[1];
31238 }
31239 }
31240 }
31241
31242 if ($isFeatureBranch) {
31243
31244  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
31245 $version = $result['version'];
31246 $prettyVersion = $result['pretty_version'];
31247 }
31248 }
31249
31250 if (!$version || $isDetached) {
31251 $result = $this->versionFromGitTags($path);
31252 if ($result) {
31253 $version = $result['version'];
31254 $prettyVersion = $result['pretty_version'];
31255 }
31256 }
31257
31258 if (!$commit) {
31259 $command = 'git log --pretty="%H" -n1 HEAD';
31260 if (0 === $this->process->execute($command, $output, $path)) {
31261 $commit = trim($output) ?: null;
31262 }
31263 }
31264
31265 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
31266 }
31267
31268 private function versionFromGitTags($path)
31269 {
31270
31271  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
31272 try {
31273 $version = $this->versionParser->normalize(trim($output));
31274
31275 return array('version' => $version, 'pretty_version' => trim($output));
31276 } catch (\Exception $e) {
31277 }
31278 }
31279
31280 return null;
31281 }
31282
31283 private function guessHgVersion(array $packageConfig, $path)
31284 {
31285
31286  if (0 === $this->process->execute('hg branch', $output, $path)) {
31287 $branch = trim($output);
31288 $version = $this->versionParser->normalizeBranch($branch);
31289 $isFeatureBranch = 0 === strpos($version, 'dev-');
31290
31291 if ('9999999-dev' === $version) {
31292 return array('version' => $version, 'commit' => null, 'pretty_version' => 'dev-'.$branch);
31293 }
31294
31295 if (!$isFeatureBranch) {
31296 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
31297 }
31298
31299
31300  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
31301 $branches = array_keys($driver->getBranches());
31302
31303
31304  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
31305 $result['commit'] = '';
31306
31307 return $result;
31308 }
31309 }
31310
31311 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
31312 {
31313 $prettyVersion = $version;
31314
31315
31316  
31317  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
31318 || strpos(json_encode($packageConfig), '"self.version"')
31319 ) {
31320 $branch = preg_replace('{^dev-}', '', $version);
31321 $length = PHP_INT_MAX;
31322
31323 $nonFeatureBranches = '';
31324 if (!empty($packageConfig['non-feature-branches'])) {
31325 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
31326 }
31327
31328 foreach ($branches as $candidate) {
31329
31330  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
31331 break;
31332 }
31333
31334
31335  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
31336 continue;
31337 }
31338
31339 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
31340 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
31341 continue;
31342 }
31343
31344 if (strlen($output) < $length) {
31345 $length = strlen($output);
31346 $version = $this->versionParser->normalizeBranch($candidate);
31347 $prettyVersion = 'dev-' . $match[1];
31348 }
31349 }
31350 }
31351
31352 return array('version' => $version, 'pretty_version' => $prettyVersion);
31353 }
31354
31355 private function guessFossilVersion(array $packageConfig, $path)
31356 {
31357 $version = null;
31358 $prettyVersion = null;
31359
31360
31361  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
31362 $branch = trim($output);
31363 $version = $this->versionParser->normalizeBranch($branch);
31364 $prettyVersion = 'dev-' . $branch;
31365 }
31366
31367
31368  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
31369 try {
31370 $version = $this->versionParser->normalize(trim($output));
31371 $prettyVersion = trim($output);
31372 } catch (\Exception $e) {
31373 }
31374 }
31375
31376 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
31377 }
31378
31379 private function guessSvnVersion(array $packageConfig, $path)
31380 {
31381 SvnUtil::cleanEnv();
31382
31383
31384  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
31385 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
31386 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
31387 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
31388
31389 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
31390
31391 if (preg_match($urlPattern, $output, $matches)) {
31392 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
31393
31394  $version = $this->versionParser->normalizeBranch($matches[3]);
31395 $prettyVersion = 'dev-' . $matches[3];
31396
31397 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
31398 }
31399
31400 $prettyVersion = trim($matches[1]);
31401 $version = $this->versionParser->normalize($prettyVersion);
31402
31403 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
31404 }
31405 }
31406 }
31407 }
31408 <?php
31409
31410
31411
31412
31413
31414
31415
31416
31417
31418
31419
31420 namespace Composer\Package\Version;
31421
31422 use Composer\Repository\PlatformRepository;
31423 use Composer\Semver\VersionParser as SemverVersionParser;
31424 use Composer\Semver\Semver;
31425
31426 class VersionParser extends SemverVersionParser
31427 {
31428 private static $constraints = array();
31429
31430
31431
31432
31433 public function parseConstraints($constraints)
31434 {
31435 if (!isset(self::$constraints[$constraints])) {
31436 self::$constraints[$constraints] = parent::parseConstraints($constraints);
31437 }
31438
31439 return self::$constraints[$constraints];
31440 }
31441
31442
31443
31444
31445
31446
31447
31448
31449
31450
31451
31452 public function parseNameVersionPairs(array $pairs)
31453 {
31454 $pairs = array_values($pairs);
31455 $result = array();
31456
31457 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
31458 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
31459 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
31460 $pair .= ' '.$pairs[$i + 1];
31461 $i++;
31462 }
31463
31464 if (strpos($pair, ' ')) {
31465 list($name, $version) = explode(' ', $pair, 2);
31466 $result[] = array('name' => $name, 'version' => $version);
31467 } else {
31468 $result[] = array('name' => $pair);
31469 }
31470 }
31471
31472 return $result;
31473 }
31474
31475
31476
31477
31478 public static function isUpgrade($normalizedFrom, $normalizedTo)
31479 {
31480 if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') {
31481 return true;
31482 }
31483
31484 $sorted = Semver::sort(array($normalizedTo, $normalizedFrom));
31485
31486 return $sorted[0] === $normalizedFrom;
31487 }
31488 }
31489 <?php
31490
31491
31492
31493
31494
31495
31496
31497
31498
31499
31500
31501 namespace Composer\Package\Version;
31502
31503 use Composer\DependencyResolver\Pool;
31504 use Composer\Package\BasePackage;
31505 use Composer\Package\PackageInterface;
31506 use Composer\Package\Loader\ArrayLoader;
31507 use Composer\Package\Dumper\ArrayDumper;
31508 use Composer\Semver\Constraint\Constraint;
31509
31510
31511
31512
31513
31514
31515
31516 class VersionSelector
31517 {
31518 private $pool;
31519
31520 private $parser;
31521
31522 public function __construct(Pool $pool)
31523 {
31524 $this->pool = $pool;
31525 }
31526
31527
31528
31529
31530
31531
31532
31533
31534
31535
31536
31537 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
31538 {
31539 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
31540 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
31541
31542 if ($targetPhpVersion) {
31543 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
31544 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
31545 $reqs = $pkg->getRequires();
31546
31547 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
31548 });
31549 }
31550
31551 if (!$candidates) {
31552 return false;
31553 }
31554
31555
31556  $package = reset($candidates);
31557 $minPriority = BasePackage::$stabilities[$preferredStability];
31558 foreach ($candidates as $candidate) {
31559 $candidatePriority = $candidate->getStabilityPriority();
31560 $currentPriority = $package->getStabilityPriority();
31561
31562
31563  
31564  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
31565 continue;
31566 }
31567
31568
31569  
31570  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
31571 $package = $candidate;
31572 continue;
31573 }
31574
31575
31576  
31577  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
31578 $package = $candidate;
31579 continue;
31580 }
31581
31582
31583  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
31584 $package = $candidate;
31585 }
31586 }
31587
31588 return $package;
31589 }
31590
31591
31592
31593
31594
31595
31596
31597
31598
31599
31600
31601
31602
31603
31604
31605
31606 public function findRecommendedRequireVersion(PackageInterface $package)
31607 {
31608 $version = $package->getVersion();
31609 if (!$package->isDev()) {
31610 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
31611 }
31612
31613 $loader = new ArrayLoader($this->getParser());
31614 $dumper = new ArrayDumper();
31615 $extra = $loader->getBranchAlias($dumper->dump($package));
31616 if ($extra) {
31617 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
31618 if ($count) {
31619 $extra = str_replace('.9999999', '.0', $extra);
31620
31621 return $this->transformVersion($extra, $extra, 'dev');
31622 }
31623 }
31624
31625 return $package->getPrettyVersion();
31626 }
31627
31628 private function transformVersion($version, $prettyVersion, $stability)
31629 {
31630
31631  
31632  $semanticVersionParts = explode('.', $version);
31633
31634
31635  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
31636
31637  if ($semanticVersionParts[0] === '0') {
31638 unset($semanticVersionParts[3]);
31639 } else {
31640 unset($semanticVersionParts[2], $semanticVersionParts[3]);
31641 }
31642 $version = implode('.', $semanticVersionParts);
31643 } else {
31644 return $prettyVersion;
31645 }
31646
31647
31648  if ($stability != 'stable') {
31649 $version .= '@'.$stability;
31650 }
31651
31652
31653  return '^' . $version;
31654 }
31655
31656 private function getParser()
31657 {
31658 if ($this->parser === null) {
31659 $this->parser = new VersionParser();
31660 }
31661
31662 return $this->parser;
31663 }
31664 }
31665 <?php
31666
31667
31668
31669
31670
31671
31672
31673
31674
31675
31676
31677 namespace Composer\Plugin\Capability;
31678
31679
31680
31681
31682
31683
31684
31685 interface Capability
31686 {
31687 }
31688 <?php
31689
31690
31691
31692
31693
31694
31695
31696
31697
31698
31699
31700 namespace Composer\Plugin\Capability;
31701
31702
31703
31704
31705
31706
31707
31708
31709
31710
31711
31712 interface CommandProvider extends Capability
31713 {
31714
31715
31716
31717
31718
31719 public function getCommands();
31720 }
31721 <?php
31722
31723
31724
31725
31726
31727
31728
31729
31730
31731
31732
31733 namespace Composer\Plugin;
31734
31735
31736
31737
31738
31739
31740
31741
31742 interface Capable
31743 {
31744
31745
31746
31747
31748
31749
31750
31751
31752
31753
31754
31755
31756
31757
31758
31759
31760
31761
31762 public function getCapabilities();
31763 }
31764 <?php
31765
31766
31767
31768
31769
31770
31771
31772
31773
31774
31775
31776 namespace Composer\Plugin;
31777
31778 use Composer\EventDispatcher\Event;
31779 use Symfony\Component\Console\Input\InputInterface;
31780 use Symfony\Component\Console\Output\OutputInterface;
31781
31782
31783
31784
31785
31786
31787 class CommandEvent extends Event
31788 {
31789
31790
31791
31792 private $commandName;
31793
31794
31795
31796
31797 private $input;
31798
31799
31800
31801
31802 private $output;
31803
31804
31805
31806
31807
31808
31809
31810
31811
31812
31813
31814 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
31815 {
31816 parent::__construct($name, $args, $flags);
31817 $this->commandName = $commandName;
31818 $this->input = $input;
31819 $this->output = $output;
31820 }
31821
31822
31823
31824
31825
31826
31827 public function getInput()
31828 {
31829 return $this->input;
31830 }
31831
31832
31833
31834
31835
31836
31837 public function getOutput()
31838 {
31839 return $this->output;
31840 }
31841
31842
31843
31844
31845
31846
31847 public function getCommandName()
31848 {
31849 return $this->commandName;
31850 }
31851 }
31852 <?php
31853
31854
31855
31856
31857
31858
31859
31860
31861
31862
31863
31864 namespace Composer\Plugin;
31865
31866
31867
31868
31869
31870
31871 class PluginEvents
31872 {
31873
31874
31875
31876
31877
31878
31879
31880
31881 const INIT = 'init';
31882
31883
31884
31885
31886
31887
31888
31889
31890
31891 const COMMAND = 'command';
31892
31893
31894
31895
31896
31897
31898
31899
31900
31901 const PRE_FILE_DOWNLOAD = 'pre-file-download';
31902
31903
31904
31905
31906
31907
31908
31909
31910
31911 const PRE_COMMAND_RUN = 'pre-command-run';
31912 }
31913 <?php
31914
31915
31916
31917
31918
31919
31920
31921
31922
31923
31924
31925 namespace Composer\Plugin;
31926
31927 use Composer\Composer;
31928 use Composer\IO\IOInterface;
31929
31930
31931
31932
31933
31934
31935 interface PluginInterface
31936 {
31937
31938
31939
31940
31941
31942 const PLUGIN_API_VERSION = '1.1.0';
31943
31944
31945
31946
31947
31948
31949
31950 public function activate(Composer $composer, IOInterface $io);
31951 }
31952 <?php
31953
31954
31955
31956
31957
31958
31959
31960
31961
31962
31963
31964 namespace Composer\Plugin;
31965
31966 use Composer\Composer;
31967 use Composer\EventDispatcher\EventSubscriberInterface;
31968 use Composer\IO\IOInterface;
31969 use Composer\Package\CompletePackage;
31970 use Composer\Package\Package;
31971 use Composer\Package\Version\VersionParser;
31972 use Composer\Repository\RepositoryInterface;
31973 use Composer\Package\PackageInterface;
31974 use Composer\Package\Link;
31975 use Composer\Semver\Constraint\Constraint;
31976 use Composer\DependencyResolver\Pool;
31977 use Composer\Plugin\Capability\Capability;
31978 use Composer\Util\PackageSorter;
31979
31980
31981
31982
31983
31984
31985
31986 class PluginManager
31987 {
31988 protected $composer;
31989 protected $io;
31990 protected $globalComposer;
31991 protected $versionParser;
31992 protected $disablePlugins = false;
31993
31994 protected $plugins = array();
31995 protected $registeredPlugins = array();
31996
31997 private static $classCounter = 0;
31998
31999
32000
32001
32002
32003
32004
32005
32006
32007 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
32008 {
32009 $this->io = $io;
32010 $this->composer = $composer;
32011 $this->globalComposer = $globalComposer;
32012 $this->versionParser = new VersionParser();
32013 $this->disablePlugins = $disablePlugins;
32014 }
32015
32016
32017
32018
32019 public function loadInstalledPlugins()
32020 {
32021 if ($this->disablePlugins) {
32022 return;
32023 }
32024
32025 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
32026 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
32027 if ($repo) {
32028 $this->loadRepository($repo);
32029 }
32030 if ($globalRepo) {
32031 $this->loadRepository($globalRepo);
32032 }
32033 }
32034
32035
32036
32037
32038
32039
32040 public function getPlugins()
32041 {
32042 return $this->plugins;
32043 }
32044
32045
32046
32047
32048
32049
32050 public function getGlobalComposer()
32051 {
32052 return $this->globalComposer;
32053 }
32054
32055
32056
32057
32058
32059
32060
32061
32062
32063
32064
32065
32066 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
32067 {
32068 if ($this->disablePlugins) {
32069 return;
32070 }
32071
32072 if ($package->getType() === 'composer-plugin') {
32073 $requiresComposer = null;
32074 foreach ($package->getRequires() as $link) { 
32075 if ('composer-plugin-api' === $link->getTarget()) {
32076 $requiresComposer = $link->getConstraint();
32077 break;
32078 }
32079 }
32080
32081 if (!$requiresComposer) {
32082 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
32083 }
32084
32085 $currentPluginApiVersion = $this->getPluginApiVersion();
32086 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
32087
32088 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
32089 $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>');
32090 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
32091 $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>');
32092
32093 return;
32094 }
32095 }
32096
32097 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
32098
32099 if (in_array($package->getName(), $this->registeredPlugins)) {
32100 return;
32101 }
32102
32103 $extra = $package->getExtra();
32104 if (empty($extra['class'])) {
32105 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
32106 }
32107 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
32108
32109 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
32110 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
32111
32112 $pool = new Pool('dev');
32113 $pool->addRepository($localRepo);
32114 if ($globalRepo) {
32115 $pool->addRepository($globalRepo);
32116 }
32117
32118 $autoloadPackages = array($package->getName() => $package);
32119 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
32120
32121 $generator = $this->composer->getAutoloadGenerator();
32122 $autoloads = array();
32123 foreach ($autoloadPackages as $autoloadPackage) {
32124 $downloadPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage));
32125 $autoloads[] = array($autoloadPackage, $downloadPath);
32126 }
32127
32128 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
32129 $classLoader = $generator->createLoader($map);
32130 $classLoader->register();
32131
32132 foreach ($classes as $class) {
32133 if (class_exists($class, false)) {
32134 $class = trim($class, '\\');
32135 $path = $classLoader->findFile($class);
32136 $code = file_get_contents($path);
32137 $separatorPos = strrpos($class, '\\');
32138 $className = $class;
32139 if ($separatorPos) {
32140 $className = substr($class, $separatorPos + 1);
32141 }
32142 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
32143 $code = str_replace('__FILE__', var_export($path, true), $code);
32144 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
32145 $code = str_replace('__CLASS__', var_export($class, true), $code);
32146 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
32147 eval($code);
32148 $class .= '_composer_tmp'.self::$classCounter;
32149 self::$classCounter++;
32150 }
32151
32152 if ($oldInstallerPlugin) {
32153 $installer = new $class($this->io, $this->composer);
32154 $this->composer->getInstallationManager()->addInstaller($installer);
32155 } elseif (class_exists($class)) {
32156 $plugin = new $class();
32157 $this->addPlugin($plugin);
32158 $this->registeredPlugins[] = $package->getName();
32159 } elseif ($failOnMissingClasses) {
32160 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
32161 }
32162 }
32163 }
32164
32165
32166
32167
32168
32169
32170 protected function getPluginApiVersion()
32171 {
32172 return PluginInterface::PLUGIN_API_VERSION;
32173 }
32174
32175
32176
32177
32178
32179
32180
32181
32182
32183
32184 public function addPlugin(PluginInterface $plugin)
32185 {
32186 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
32187 $this->plugins[] = $plugin;
32188 $plugin->activate($this->composer, $this->io);
32189
32190 if ($plugin instanceof EventSubscriberInterface) {
32191 $this->composer->getEventDispatcher()->addSubscriber($plugin);
32192 }
32193 }
32194
32195
32196
32197
32198
32199
32200
32201
32202
32203
32204
32205
32206 private function loadRepository(RepositoryInterface $repo)
32207 {
32208 $packages = $repo->getPackages();
32209 $sortedPackages = array_reverse(PackageSorter::sortPackages($packages));
32210 foreach ($sortedPackages as $package) {
32211 if (!($package instanceof CompletePackage)) {
32212 continue;
32213 }
32214 if ('composer-plugin' === $package->getType()) {
32215 $this->registerPackage($package);
32216
32217  } elseif ('composer-installer' === $package->getType()) {
32218 $this->registerPackage($package);
32219 }
32220 }
32221 }
32222
32223
32224
32225
32226
32227
32228
32229
32230
32231
32232 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
32233 {
32234 $requires = array_merge(
32235 $package->getRequires(),
32236 $package->getDevRequires()
32237 );
32238
32239 foreach ($requires as $requireLink) {
32240 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
32241 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
32242 $collected[$requiredPackage->getName()] = $requiredPackage;
32243 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
32244 }
32245 }
32246
32247 return $collected;
32248 }
32249
32250
32251
32252
32253
32254
32255
32256
32257
32258
32259
32260 private function lookupInstalledPackage(Pool $pool, Link $link)
32261 {
32262 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
32263
32264 return !empty($packages) ? $packages[0] : null;
32265 }
32266
32267
32268
32269
32270
32271
32272
32273
32274
32275 private function getInstallPath(PackageInterface $package, $global = false)
32276 {
32277 if (!$global) {
32278 return $this->composer->getInstallationManager()->getInstallPath($package);
32279 }
32280
32281 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
32282 }
32283
32284
32285
32286
32287
32288
32289
32290 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
32291 {
32292 if (!($plugin instanceof Capable)) {
32293 return null;
32294 }
32295
32296 $capabilities = (array) $plugin->getCapabilities();
32297
32298 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
32299 return trim($capabilities[$capability]);
32300 }
32301
32302 if (
32303 array_key_exists($capability, $capabilities)
32304 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
32305 ) {
32306 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
32307 }
32308 }
32309
32310
32311
32312
32313
32314
32315
32316
32317
32318 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
32319 {
32320 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
32321 if (!class_exists($capabilityClass)) {
32322 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
32323 }
32324
32325 $ctorArgs['plugin'] = $plugin;
32326 $capabilityObj = new $capabilityClass($ctorArgs);
32327
32328
32329  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
32330 throw new \RuntimeException(
32331 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
32332 );
32333 }
32334
32335 return $capabilityObj;
32336 }
32337 }
32338
32339
32340
32341
32342
32343
32344
32345
32346 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
32347 {
32348 $capabilities = array();
32349 foreach ($this->getPlugins() as $plugin) {
32350 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
32351 $capabilities[] = $capability;
32352 }
32353 }
32354
32355 return $capabilities;
32356 }
32357 }
32358 <?php
32359
32360
32361
32362
32363
32364
32365
32366
32367
32368
32369
32370 namespace Composer\Plugin;
32371
32372 use Composer\EventDispatcher\Event;
32373 use Symfony\Component\Console\Input\InputInterface;
32374
32375
32376
32377
32378
32379
32380 class PreCommandRunEvent extends Event
32381 {
32382
32383
32384
32385 private $input;
32386
32387
32388
32389
32390 private $command;
32391
32392
32393
32394
32395
32396
32397
32398
32399 public function __construct($name, InputInterface $input, $command)
32400 {
32401 parent::__construct($name);
32402 $this->input = $input;
32403 $this->command = $command;
32404 }
32405
32406
32407
32408
32409
32410
32411 public function getInput()
32412 {
32413 return $this->input;
32414 }
32415
32416
32417
32418
32419
32420
32421 public function getCommand()
32422 {
32423 return $this->command;
32424 }
32425 }
32426 <?php
32427
32428
32429
32430
32431
32432
32433
32434
32435
32436
32437
32438 namespace Composer\Plugin;
32439
32440 use Composer\EventDispatcher\Event;
32441 use Composer\Util\RemoteFilesystem;
32442
32443
32444
32445
32446
32447
32448 class PreFileDownloadEvent extends Event
32449 {
32450
32451
32452
32453 private $rfs;
32454
32455
32456
32457
32458 private $processedUrl;
32459
32460
32461
32462
32463
32464
32465
32466
32467 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
32468 {
32469 parent::__construct($name);
32470 $this->rfs = $rfs;
32471 $this->processedUrl = $processedUrl;
32472 }
32473
32474
32475
32476
32477
32478
32479 public function getRemoteFilesystem()
32480 {
32481 return $this->rfs;
32482 }
32483
32484
32485
32486
32487
32488
32489 public function setRemoteFilesystem(RemoteFilesystem $rfs)
32490 {
32491 $this->rfs = $rfs;
32492 }
32493
32494
32495
32496
32497
32498
32499 public function getProcessedUrl()
32500 {
32501 return $this->processedUrl;
32502 }
32503 }
32504 <?php
32505
32506
32507
32508
32509
32510
32511
32512
32513
32514
32515
32516 namespace Composer\Question;
32517
32518 use Symfony\Component\Console\Exception\InvalidArgumentException;
32519 use Symfony\Component\Console\Question\Question;
32520
32521
32522
32523
32524
32525
32526
32527
32528 class StrictConfirmationQuestion extends Question
32529 {
32530 private $trueAnswerRegex;
32531 private $falseAnswerRegex;
32532
32533
32534
32535
32536
32537
32538
32539
32540
32541 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
32542 {
32543 parent::__construct($question, (bool) $default);
32544
32545 $this->trueAnswerRegex = $trueAnswerRegex;
32546 $this->falseAnswerRegex = $falseAnswerRegex;
32547 $this->setNormalizer($this->getDefaultNormalizer());
32548 $this->setValidator($this->getDefaultValidator());
32549 }
32550
32551
32552
32553
32554
32555
32556 private function getDefaultNormalizer()
32557 {
32558 $default = $this->getDefault();
32559 $trueRegex = $this->trueAnswerRegex;
32560 $falseRegex = $this->falseAnswerRegex;
32561
32562 return function ($answer) use ($default, $trueRegex, $falseRegex) {
32563 if (is_bool($answer)) {
32564 return $answer;
32565 }
32566 if (empty($answer) && !empty($default)) {
32567 return $default;
32568 }
32569
32570 if (preg_match($trueRegex, $answer)) {
32571 return true;
32572 }
32573
32574 if (preg_match($falseRegex, $answer)) {
32575 return false;
32576 }
32577
32578 return null;
32579 };
32580 }
32581
32582
32583
32584
32585
32586
32587 private function getDefaultValidator()
32588 {
32589 return function ($answer) {
32590 if (!is_bool($answer)) {
32591 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
32592 }
32593
32594 return $answer;
32595 };
32596 }
32597 }
32598 <?php
32599
32600
32601
32602
32603
32604
32605
32606
32607
32608
32609
32610 namespace Composer\Repository;
32611
32612 use Composer\Package\AliasPackage;
32613 use Composer\Package\PackageInterface;
32614 use Composer\Package\CompletePackageInterface;
32615 use Composer\Package\Version\VersionParser;
32616 use Composer\Semver\Constraint\ConstraintInterface;
32617 use Composer\Semver\Constraint\Constraint;
32618
32619
32620
32621
32622
32623
32624 class ArrayRepository extends BaseRepository
32625 {
32626
32627 protected $packages;
32628
32629 public function __construct(array $packages = array())
32630 {
32631 foreach ($packages as $package) {
32632 $this->addPackage($package);
32633 }
32634 }
32635
32636
32637
32638
32639 public function findPackage($name, $constraint)
32640 {
32641 $name = strtolower($name);
32642
32643 if (!$constraint instanceof ConstraintInterface) {
32644 $versionParser = new VersionParser();
32645 $constraint = $versionParser->parseConstraints($constraint);
32646 }
32647
32648 foreach ($this->getPackages() as $package) {
32649 if ($name === $package->getName()) {
32650 $pkgConstraint = new Constraint('==', $package->getVersion());
32651 if ($constraint->matches($pkgConstraint)) {
32652 return $package;
32653 }
32654 }
32655 }
32656
32657 return null;
32658 }
32659
32660
32661
32662
32663 public function findPackages($name, $constraint = null)
32664 {
32665
32666  $name = strtolower($name);
32667 $packages = array();
32668
32669 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
32670 $versionParser = new VersionParser();
32671 $constraint = $versionParser->parseConstraints($constraint);
32672 }
32673
32674 foreach ($this->getPackages() as $package) {
32675 if ($name === $package->getName()) {
32676 $pkgConstraint = new Constraint('==', $package->getVersion());
32677 if (null === $constraint || $constraint->matches($pkgConstraint)) {
32678 $packages[] = $package;
32679 }
32680 }
32681 }
32682
32683 return $packages;
32684 }
32685
32686
32687
32688
32689 public function search($query, $mode = 0, $type = null)
32690 {
32691 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
32692
32693 $matches = array();
32694 foreach ($this->getPackages() as $package) {
32695 $name = $package->getName();
32696 if (isset($matches[$name])) {
32697 continue;
32698 }
32699 if (preg_match($regex, $name)
32700 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
32701 ) {
32702 if (null !== $type && $package->getType() !== $type) {
32703 continue;
32704 }
32705
32706 $matches[$name] = array(
32707 'name' => $package->getPrettyName(),
32708 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
32709 );
32710 }
32711 }
32712
32713 return array_values($matches);
32714 }
32715
32716
32717
32718
32719 public function hasPackage(PackageInterface $package)
32720 {
32721 $packageId = $package->getUniqueName();
32722
32723 foreach ($this->getPackages() as $repoPackage) {
32724 if ($packageId === $repoPackage->getUniqueName()) {
32725 return true;
32726 }
32727 }
32728
32729 return false;
32730 }
32731
32732
32733
32734
32735
32736
32737 public function addPackage(PackageInterface $package)
32738 {
32739 if (null === $this->packages) {
32740 $this->initialize();
32741 }
32742 $package->setRepository($this);
32743 $this->packages[] = $package;
32744
32745 if ($package instanceof AliasPackage) {
32746 $aliasedPackage = $package->getAliasOf();
32747 if (null === $aliasedPackage->getRepository()) {
32748 $this->addPackage($aliasedPackage);
32749 }
32750 }
32751 }
32752
32753 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
32754 {
32755 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
32756 }
32757
32758
32759
32760
32761
32762
32763 public function removePackage(PackageInterface $package)
32764 {
32765 $packageId = $package->getUniqueName();
32766
32767 foreach ($this->getPackages() as $key => $repoPackage) {
32768 if ($packageId === $repoPackage->getUniqueName()) {
32769 array_splice($this->packages, $key, 1);
32770
32771 return;
32772 }
32773 }
32774 }
32775
32776
32777
32778
32779 public function getPackages()
32780 {
32781 if (null === $this->packages) {
32782 $this->initialize();
32783 }
32784
32785 return $this->packages;
32786 }
32787
32788
32789
32790
32791
32792
32793 public function count()
32794 {
32795 return count($this->packages);
32796 }
32797
32798
32799
32800
32801 protected function initialize()
32802 {
32803 $this->packages = array();
32804 }
32805 }
32806 <?php
32807
32808
32809
32810
32811
32812
32813
32814
32815
32816
32817
32818 namespace Composer\Repository;
32819
32820 use Composer\IO\IOInterface;
32821 use Composer\Json\JsonFile;
32822 use Composer\Package\Loader\ArrayLoader;
32823 use Composer\Package\Loader\LoaderInterface;
32824 use Composer\Util\Zip;
32825
32826
32827
32828
32829 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
32830 {
32831
32832 protected $loader;
32833
32834 protected $lookup;
32835 protected $repoConfig;
32836 private $io;
32837
32838 public function __construct(array $repoConfig, IOInterface $io)
32839 {
32840 parent::__construct();
32841 if (!extension_loaded('zip')) {
32842 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
32843 }
32844
32845 $this->loader = new ArrayLoader();
32846 $this->lookup = $repoConfig['url'];
32847 $this->io = $io;
32848 $this->repoConfig = $repoConfig;
32849 }
32850
32851 public function getRepoConfig()
32852 {
32853 return $this->repoConfig;
32854 }
32855
32856 protected function initialize()
32857 {
32858 parent::initialize();
32859
32860 $this->scanDirectory($this->lookup);
32861 }
32862
32863 private function scanDirectory($path)
32864 {
32865 $io = $this->io;
32866
32867 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
32868 $iterator = new \RecursiveIteratorIterator($directory);
32869 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
32870 foreach ($regex as $file) {
32871
32872 if (!$file->isFile()) {
32873 continue;
32874 }
32875
32876 $package = $this->getComposerInformation($file);
32877 if (!$package) {
32878 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
32879 continue;
32880 }
32881
32882 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
32883 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
32884
32885 $this->addPackage($package);
32886 }
32887 }
32888
32889 private function getComposerInformation(\SplFileInfo $file)
32890 {
32891 $json = Zip::getComposerJson($file->getPathname());
32892
32893 if (null === $json) {
32894 return false;
32895 }
32896
32897 $package = JsonFile::parseJson($json, $file->getPathname().'#composer.json');
32898 $package['dist'] = array(
32899 'type' => 'zip',
32900 'url' => strtr($file->getPathname(), '\\', '/'),
32901 'shasum' => sha1_file($file->getRealPath()),
32902 );
32903
32904 try {
32905 $package = $this->loader->load($package);
32906 } catch (\UnexpectedValueException $e) {
32907 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
32908 }
32909
32910 return $package;
32911 }
32912 }
32913 <?php
32914
32915
32916
32917
32918
32919
32920
32921
32922
32923
32924
32925 namespace Composer\Repository;
32926
32927 use Composer\Package\RootPackageInterface;
32928 use Composer\Semver\Constraint\ConstraintInterface;
32929 use Composer\Semver\Constraint\Constraint;
32930 use Composer\Package\Link;
32931
32932
32933
32934
32935
32936
32937 abstract class BaseRepository implements RepositoryInterface
32938 {
32939
32940
32941
32942
32943
32944
32945
32946
32947
32948
32949
32950
32951
32952 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
32953 {
32954 $needles = array_map('strtolower', (array) $needle);
32955 $results = array();
32956
32957
32958  if (null === $packagesFound) {
32959 $packagesFound = $needles;
32960 }
32961
32962
32963  $rootPackage = null;
32964 foreach ($this->getPackages() as $package) {
32965 if ($package instanceof RootPackageInterface) {
32966 $rootPackage = $package;
32967 break;
32968 }
32969 }
32970
32971
32972  foreach ($this->getPackages() as $package) {
32973 $links = $package->getRequires();
32974
32975
32976  
32977  $packagesInTree = $packagesFound;
32978
32979
32980  if (!$invert) {
32981 $links += $package->getReplaces();
32982
32983
32984  
32985  
32986  foreach ($package->getReplaces() as $link) {
32987 foreach ($needles as $needle) {
32988 if ($link->getSource() === $needle) {
32989 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
32990
32991  if (in_array($link->getTarget(), $packagesInTree)) {
32992 $results[] = array($package, $link, false);
32993 continue;
32994 }
32995 $packagesInTree[] = $link->getTarget();
32996 $dependents = $recurse ? $this->getDependents($link->getTarget(), null, false, true, $packagesInTree) : array();
32997 $results[] = array($package, $link, $dependents);
32998 $needles[] = $link->getTarget();
32999 }
33000 }
33001 }
33002 }
33003 }
33004
33005
33006  if ($package instanceof RootPackageInterface) {
33007 $links += $package->getDevRequires();
33008 }
33009
33010
33011  foreach ($links as $link) {
33012 foreach ($needles as $needle) {
33013 if ($link->getTarget() === $needle) {
33014 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
33015
33016  if (in_array($link->getSource(), $packagesInTree)) {
33017 $results[] = array($package, $link, false);
33018 continue;
33019 }
33020 $packagesInTree[] = $link->getSource();
33021 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
33022 $results[] = array($package, $link, $dependents);
33023 }
33024 }
33025 }
33026 }
33027
33028
33029  if ($invert && in_array($package->getName(), $needles)) {
33030 foreach ($package->getConflicts() as $link) {
33031 foreach ($this->findPackages($link->getTarget()) as $pkg) {
33032 $version = new Constraint('=', $pkg->getVersion());
33033 if ($link->getConstraint()->matches($version) === $invert) {
33034 $results[] = array($package, $link, false);
33035 }
33036 }
33037 }
33038 }
33039
33040
33041  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
33042 foreach ($package->getRequires() as $link) {
33043 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
33044 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
33045 continue;
33046 }
33047
33048 $platformPkg = $this->findPackage($link->getTarget(), '*');
33049 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
33050 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
33051
33052 continue;
33053 }
33054
33055 foreach ($this->getPackages() as $pkg) {
33056 if (!in_array($link->getTarget(), $pkg->getNames())) {
33057 continue;
33058 }
33059
33060 $version = new Constraint('=', $pkg->getVersion());
33061 if (!$link->getConstraint()->matches($version)) {
33062
33063  
33064  if ($rootPackage) {
33065 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
33066 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
33067 $results[] = array($package, $link, false);
33068 $results[] = array($rootPackage, $rootReq, false);
33069 continue 3;
33070 }
33071 }
33072 $results[] = array($package, $link, false);
33073 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
33074 } else {
33075
33076  $results[] = array($package, $link, false);
33077 }
33078 }
33079
33080 continue 2;
33081 }
33082 }
33083 }
33084 }
33085
33086 ksort($results);
33087
33088 return $results;
33089 }
33090 }
33091 <?php
33092
33093
33094
33095
33096
33097
33098
33099
33100
33101
33102
33103 namespace Composer\Repository;
33104
33105 use Composer\Package\Loader\ArrayLoader;
33106 use Composer\Package\PackageInterface;
33107 use Composer\Package\AliasPackage;
33108 use Composer\Package\Version\VersionParser;
33109 use Composer\DependencyResolver\Pool;
33110 use Composer\Json\JsonFile;
33111 use Composer\Cache;
33112 use Composer\Config;
33113 use Composer\Composer;
33114 use Composer\Factory;
33115 use Composer\IO\IOInterface;
33116 use Composer\Util\RemoteFilesystem;
33117 use Composer\Plugin\PluginEvents;
33118 use Composer\Plugin\PreFileDownloadEvent;
33119 use Composer\EventDispatcher\EventDispatcher;
33120 use Composer\Downloader\TransportException;
33121 use Composer\Semver\Constraint\ConstraintInterface;
33122 use Composer\Semver\Constraint\Constraint;
33123
33124
33125
33126
33127 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33128 {
33129 protected $config;
33130 protected $repoConfig;
33131 protected $options;
33132 protected $url;
33133 protected $baseUrl;
33134 protected $io;
33135 protected $rfs;
33136 protected $cache;
33137 protected $notifyUrl;
33138 protected $searchUrl;
33139 protected $hasProviders = false;
33140 protected $providersUrl;
33141 protected $lazyProvidersUrl;
33142 protected $providerListing;
33143 protected $providers = array();
33144 protected $providersByUid = array();
33145 protected $loader;
33146 protected $rootAliases;
33147 protected $allowSslDowngrade = false;
33148 protected $eventDispatcher;
33149 protected $sourceMirrors;
33150 protected $distMirrors;
33151 private $degradedMode = false;
33152 private $rootData;
33153 private $hasPartialPackages;
33154 private $partialPackagesByName;
33155
33156 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
33157 {
33158 parent::__construct();
33159 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
33160
33161  $repoConfig['url'] = 'http://'.$repoConfig['url'];
33162 }
33163 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
33164
33165 if ('https?' === substr($repoConfig['url'], 0, 6)) {
33166 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
33167 }
33168
33169 $urlBits = parse_url($repoConfig['url']);
33170 if ($urlBits === false || empty($urlBits['scheme'])) {
33171 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
33172 }
33173
33174 if (!isset($repoConfig['options'])) {
33175 $repoConfig['options'] = array();
33176 }
33177 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
33178 $this->allowSslDowngrade = true;
33179 }
33180
33181 $this->config = $config;
33182 $this->options = $repoConfig['options'];
33183 $this->url = $repoConfig['url'];
33184
33185
33186  if (preg_match('{^(?P<proto>https?)://packagist\.org/?$}i', $this->url, $match)) {
33187 $this->url = $match['proto'].'://repo.packagist.org';
33188 }
33189
33190 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
33191 $this->io = $io;
33192 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
33193 $this->loader = new ArrayLoader();
33194 if ($rfs && $this->options) {
33195 $rfs = clone $rfs;
33196 $rfs->setOptions($this->options);
33197 }
33198 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
33199 $this->eventDispatcher = $eventDispatcher;
33200 $this->repoConfig = $repoConfig;
33201 }
33202
33203 public function getRepoConfig()
33204 {
33205 return $this->repoConfig;
33206 }
33207
33208 public function setRootAliases(array $rootAliases)
33209 {
33210 $this->rootAliases = $rootAliases;
33211 }
33212
33213
33214
33215
33216 public function findPackage($name, $constraint)
33217 {
33218 if (!$this->hasProviders()) {
33219 return parent::findPackage($name, $constraint);
33220 }
33221
33222 $name = strtolower($name);
33223 if (!$constraint instanceof ConstraintInterface) {
33224 $versionParser = new VersionParser();
33225 $constraint = $versionParser->parseConstraints($constraint);
33226 }
33227
33228 foreach ($this->getProviderNames() as $providerName) {
33229 if ($name === $providerName) {
33230 $packages = $this->whatProvides(new Pool('dev'), $providerName);
33231 foreach ($packages as $package) {
33232 if ($name === $package->getName()) {
33233 $pkgConstraint = new Constraint('==', $package->getVersion());
33234 if ($constraint->matches($pkgConstraint)) {
33235 return $package;
33236 }
33237 }
33238 }
33239 break;
33240 }
33241 }
33242 }
33243
33244
33245
33246
33247 public function findPackages($name, $constraint = null)
33248 {
33249 if (!$this->hasProviders()) {
33250 return parent::findPackages($name, $constraint);
33251 }
33252
33253  $name = strtolower($name);
33254
33255 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
33256 $versionParser = new VersionParser();
33257 $constraint = $versionParser->parseConstraints($constraint);
33258 }
33259
33260 $packages = array();
33261
33262 foreach ($this->getProviderNames() as $providerName) {
33263 if ($name === $providerName) {
33264 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
33265 foreach ($candidates as $package) {
33266 if ($name === $package->getName()) {
33267 $pkgConstraint = new Constraint('==', $package->getVersion());
33268 if (null === $constraint || $constraint->matches($pkgConstraint)) {
33269 $packages[] = $package;
33270 }
33271 }
33272 }
33273 break;
33274 }
33275 }
33276
33277 return $packages;
33278 }
33279
33280 public function getPackages()
33281 {
33282 if ($this->hasProviders()) {
33283 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
33284 }
33285
33286 return parent::getPackages();
33287 }
33288
33289
33290
33291
33292 public function search($query, $mode = 0, $type = null)
33293 {
33294 $this->loadRootServerFile();
33295
33296 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
33297 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
33298
33299 $origin = RemoteFilesystem::getOrigin($url);
33300 $json = $this->rfs->getContents($origin, $url, false);
33301 $search = JsonFile::parseJson($json, $url);
33302
33303 if (empty($search['results'])) {
33304 return array();
33305 }
33306
33307 $results = array();
33308 foreach ($search['results'] as $result) {
33309
33310  if (empty($result['virtual'])) {
33311 $results[] = $result;
33312 }
33313 }
33314
33315 return $results;
33316 }
33317
33318 if ($this->hasProviders()) {
33319 $results = array();
33320 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
33321
33322 foreach ($this->getProviderNames() as $name) {
33323 if (preg_match($regex, $name)) {
33324 $results[] = array('name' => $name);
33325 }
33326 }
33327
33328 return $results;
33329 }
33330
33331 return parent::search($query, $mode);
33332 }
33333
33334 public function getProviderNames()
33335 {
33336 $this->loadRootServerFile();
33337
33338 if (null === $this->providerListing) {
33339 $this->loadProviderListings($this->loadRootServerFile());
33340 }
33341
33342 if ($this->lazyProvidersUrl) {
33343
33344  return array();
33345 }
33346
33347 if ($this->providersUrl) {
33348 return array_keys($this->providerListing);
33349 }
33350
33351 return array();
33352 }
33353
33354 protected function configurePackageTransportOptions(PackageInterface $package)
33355 {
33356 foreach ($package->getDistUrls() as $url) {
33357 if (strpos($url, $this->baseUrl) === 0) {
33358 $package->setTransportOptions($this->options);
33359
33360 return;
33361 }
33362 }
33363 }
33364
33365 public function hasProviders()
33366 {
33367 $this->loadRootServerFile();
33368
33369 return $this->hasProviders;
33370 }
33371
33372 public function resetPackageIds()
33373 {
33374 foreach ($this->providersByUid as $package) {
33375 if ($package instanceof AliasPackage) {
33376 $package->getAliasOf()->setId(-1);
33377 }
33378 $package->setId(-1);
33379 }
33380 }
33381
33382
33383
33384
33385
33386
33387
33388 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
33389 {
33390 if (isset($this->providers[$name]) && !$bypassFilters) {
33391 return $this->providers[$name];
33392 }
33393
33394 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
33395 $this->initializePartialPackages();
33396 }
33397
33398 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
33399
33400  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
33401 return array();
33402 }
33403
33404 if (null === $this->providerListing) {
33405 $this->loadProviderListings($this->loadRootServerFile());
33406 }
33407
33408 $useLastModifiedCheck = false;
33409 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
33410 $hash = null;
33411 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
33412 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
33413 $useLastModifiedCheck = true;
33414 } elseif ($this->providersUrl) {
33415
33416  if (!isset($this->providerListing[$name])) {
33417 return array();
33418 }
33419
33420 $hash = $this->providerListing[$name]['sha256'];
33421 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
33422 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
33423 } else {
33424 return array();
33425 }
33426
33427 $packages = null;
33428 if ($cacheKey) {
33429 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
33430 $packages = json_decode($this->cache->read($cacheKey), true);
33431 } elseif ($useLastModifiedCheck) {
33432 if ($contents = $this->cache->read($cacheKey)) {
33433 $contents = json_decode($contents, true);
33434 if (isset($contents['last-modified'])) {
33435 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
33436 if (true === $response) {
33437 $packages = $contents;
33438 } elseif ($response) {
33439 $packages = $response;
33440 }
33441 }
33442 }
33443 }
33444 }
33445
33446 if (!$packages) {
33447 try {
33448 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
33449 } catch (TransportException $e) {
33450
33451  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
33452 $packages = array('packages' => array());
33453 } else {
33454 throw $e;
33455 }
33456 }
33457 }
33458
33459 $loadingPartialPackage = false;
33460 } else {
33461 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
33462 $loadingPartialPackage = true;
33463 }
33464
33465 $this->providers[$name] = array();
33466 foreach ($packages['packages'] as $versions) {
33467 foreach ($versions as $version) {
33468 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
33469 continue;
33470 }
33471
33472
33473  if (isset($this->providersByUid[$version['uid']])) {
33474
33475  if (!isset($this->providers[$name][$version['uid']])) {
33476
33477  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
33478 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
33479 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
33480 } else {
33481 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
33482 }
33483
33484  if (isset($this->providersByUid[$version['uid'].'-root'])) {
33485 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
33486 }
33487 }
33488 } else {
33489 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
33490 continue;
33491 }
33492
33493
33494  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
33495 $package->setRepository($this);
33496
33497 if ($package instanceof AliasPackage) {
33498 $aliased = $package->getAliasOf();
33499 $aliased->setRepository($this);
33500
33501 $this->providers[$name][$version['uid']] = $aliased;
33502 $this->providers[$name][$version['uid'].'-alias'] = $package;
33503
33504
33505  $this->providersByUid[$version['uid']] = $package;
33506 } else {
33507 $this->providers[$name][$version['uid']] = $package;
33508 $this->providersByUid[$version['uid']] = $package;
33509 }
33510
33511
33512  unset($rootAliasData);
33513
33514 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
33515 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
33516 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
33517 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
33518 }
33519
33520 if (isset($rootAliasData)) {
33521 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
33522 $alias->setRepository($this);
33523
33524 $this->providers[$name][$version['uid'].'-root'] = $alias;
33525 $this->providersByUid[$version['uid'].'-root'] = $alias;
33526 }
33527 }
33528 }
33529 }
33530
33531 $result = $this->providers[$name];
33532
33533
33534  
33535  if ($bypassFilters) {
33536 foreach ($this->providers[$name] as $uid => $provider) {
33537 unset($this->providersByUid[$uid]);
33538 }
33539 unset($this->providers[$name]);
33540 }
33541
33542 return $result;
33543 }
33544
33545
33546
33547
33548 protected function initialize()
33549 {
33550 parent::initialize();
33551
33552 $repoData = $this->loadDataFromServer();
33553
33554 foreach ($repoData as $package) {
33555 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
33556 }
33557 }
33558
33559
33560
33561
33562
33563
33564 public function addPackage(PackageInterface $package)
33565 {
33566 parent::addPackage($package);
33567 $this->configurePackageTransportOptions($package);
33568 }
33569
33570 protected function loadRootServerFile()
33571 {
33572 if (null !== $this->rootData) {
33573 return $this->rootData;
33574 }
33575
33576 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
33577 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
33578 }
33579
33580 $jsonUrlParts = parse_url($this->url);
33581
33582 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
33583 $jsonUrl = $this->url;
33584 } else {
33585 $jsonUrl = $this->url . '/packages.json';
33586 }
33587
33588 $data = $this->fetchFile($jsonUrl, 'packages.json');
33589
33590 if (!empty($data['notify-batch'])) {
33591 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
33592 } elseif (!empty($data['notify'])) {
33593 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
33594 }
33595
33596 if (!empty($data['search'])) {
33597 $this->searchUrl = $this->canonicalizeUrl($data['search']);
33598 }
33599
33600 if (!empty($data['mirrors'])) {
33601 foreach ($data['mirrors'] as $mirror) {
33602 if (!empty($mirror['git-url'])) {
33603 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
33604 }
33605 if (!empty($mirror['hg-url'])) {
33606 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
33607 }
33608 if (!empty($mirror['dist-url'])) {
33609 $this->distMirrors[] = array(
33610 'url' => $this->canonicalizeUrl($mirror['dist-url']),
33611 'preferred' => !empty($mirror['preferred']),
33612 );
33613 }
33614 }
33615 }
33616
33617 if (!empty($data['providers-lazy-url'])) {
33618 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
33619 $this->hasProviders = true;
33620
33621 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
33622 }
33623
33624 if ($this->allowSslDowngrade) {
33625 $this->url = str_replace('https://', 'http://', $this->url);
33626 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
33627 }
33628
33629 if (!empty($data['providers-url'])) {
33630 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
33631 $this->hasProviders = true;
33632 }
33633
33634 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
33635 $this->hasProviders = true;
33636 }
33637
33638
33639  if (preg_match('{^https?://repo\.packagist\.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
33640 $this->url = 'https://repo.packagist.org';
33641 $this->baseUrl = 'https://repo.packagist.org';
33642 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://repo.packagist.org/p/%package%.json');
33643 $this->providersUrl = null;
33644 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
33645 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
33646 $this->providersUrl = null;
33647 }
33648
33649 return $this->rootData = $data;
33650 }
33651
33652 protected function canonicalizeUrl($url)
33653 {
33654 if ('/' === $url[0]) {
33655 if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) {
33656 return $matches[0] . $url;
33657 }
33658
33659 return $this->url;
33660 }
33661
33662 return $url;
33663 }
33664
33665 protected function loadDataFromServer()
33666 {
33667 $data = $this->loadRootServerFile();
33668
33669 return $this->loadIncludes($data);
33670 }
33671
33672 protected function loadProviderListings($data)
33673 {
33674 if (isset($data['providers'])) {
33675 if (!is_array($this->providerListing)) {
33676 $this->providerListing = array();
33677 }
33678 $this->providerListing = array_merge($this->providerListing, $data['providers']);
33679 }
33680
33681 if ($this->providersUrl && isset($data['provider-includes'])) {
33682 $includes = $data['provider-includes'];
33683 foreach ($includes as $include => $metadata) {
33684 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
33685 $cacheKey = str_replace(array('%hash%','$'), '', $include);
33686 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
33687 $includedData = json_decode($this->cache->read($cacheKey), true);
33688 } else {
33689 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
33690 }
33691
33692 $this->loadProviderListings($includedData);
33693 }
33694 }
33695 }
33696
33697 protected function loadIncludes($data)
33698 {
33699 $packages = array();
33700
33701
33702  if (!isset($data['packages']) && !isset($data['includes'])) {
33703 foreach ($data as $pkg) {
33704 foreach ($pkg['versions'] as $metadata) {
33705 $packages[] = $metadata;
33706 }
33707 }
33708
33709 return $packages;
33710 }
33711
33712 if (isset($data['packages'])) {
33713 foreach ($data['packages'] as $package => $versions) {
33714 foreach ($versions as $version => $metadata) {
33715 $packages[] = $metadata;
33716 }
33717 }
33718 }
33719
33720 if (isset($data['includes'])) {
33721 foreach ($data['includes'] as $include => $metadata) {
33722 if ($this->cache->sha1($include) === $metadata['sha1']) {
33723 $includedData = json_decode($this->cache->read($include), true);
33724 } else {
33725 $includedData = $this->fetchFile($include);
33726 }
33727 $packages = array_merge($packages, $this->loadIncludes($includedData));
33728 }
33729 }
33730
33731 return $packages;
33732 }
33733
33734 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
33735 {
33736 try {
33737 if (!isset($data['notification-url'])) {
33738 $data['notification-url'] = $this->notifyUrl;
33739 }
33740
33741 $package = $this->loader->load($data, $class);
33742 if (isset($this->sourceMirrors[$package->getSourceType()])) {
33743 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
33744 }
33745 $package->setDistMirrors($this->distMirrors);
33746 $this->configurePackageTransportOptions($package);
33747
33748 return $package;
33749 } catch (\Exception $e) {
33750 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);
33751 }
33752 }
33753
33754 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
33755 {
33756 if (null === $cacheKey) {
33757 $cacheKey = $filename;
33758 $filename = $this->baseUrl.'/'.$filename;
33759 }
33760
33761
33762  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
33763 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
33764 }
33765
33766 $retries = 3;
33767 while ($retries--) {
33768 try {
33769 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
33770 if ($this->eventDispatcher) {
33771 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
33772 }
33773
33774 $origin = RemoteFilesystem::getOrigin($filename);
33775 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
33776
33777 $json = $rfs->getContents($origin, $filename, false);
33778 if ($sha256 && $sha256 !== hash('sha256', $json)) {
33779
33780  if ($this->allowSslDowngrade) {
33781 $this->url = str_replace('http://', 'https://', $this->url);
33782 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
33783 $filename = str_replace('http://', 'https://', $filename);
33784 }
33785
33786 if ($retries) {
33787 usleep(100000);
33788
33789 continue;
33790 }
33791
33792
33793  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.');
33794 }
33795
33796 $data = JsonFile::parseJson($json, $filename);
33797 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
33798
33799 if ($cacheKey) {
33800 if ($storeLastModifiedTime) {
33801 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
33802 if ($lastModifiedDate) {
33803 $data['last-modified'] = $lastModifiedDate;
33804 $json = json_encode($data);
33805 }
33806 }
33807 $this->cache->write($cacheKey, $json);
33808 }
33809
33810 break;
33811 } catch (\Exception $e) {
33812 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
33813 throw $e;
33814 }
33815
33816 if ($retries) {
33817 usleep(100000);
33818 continue;
33819 }
33820
33821 if ($e instanceof RepositorySecurityException) {
33822 throw $e;
33823 }
33824
33825 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
33826 if (!$this->degradedMode) {
33827 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
33828 $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>');
33829 }
33830 $this->degradedMode = true;
33831 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
33832
33833 break;
33834 }
33835
33836 throw $e;
33837 }
33838 }
33839
33840 return $data;
33841 }
33842
33843 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
33844 {
33845 $retries = 3;
33846 while ($retries--) {
33847 try {
33848 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
33849 if ($this->eventDispatcher) {
33850 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
33851 }
33852
33853 $origin = RemoteFilesystem::getOrigin($filename);
33854 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
33855 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
33856 $json = $rfs->getContents($origin, $filename, false, $options);
33857 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
33858 return true;
33859 }
33860
33861 $data = JsonFile::parseJson($json, $filename);
33862 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
33863
33864 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
33865 if ($lastModifiedDate) {
33866 $data['last-modified'] = $lastModifiedDate;
33867 $json = json_encode($data);
33868 }
33869 $this->cache->write($cacheKey, $json);
33870
33871 return $data;
33872 } catch (\Exception $e) {
33873 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
33874 throw $e;
33875 }
33876
33877 if ($retries) {
33878 usleep(100000);
33879 continue;
33880 }
33881
33882 if (!$this->degradedMode) {
33883 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
33884 $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>');
33885 }
33886 $this->degradedMode = true;
33887
33888 return true;
33889 }
33890 }
33891 }
33892
33893
33894
33895
33896
33897
33898 private function initializePartialPackages()
33899 {
33900 $rootData = $this->loadRootServerFile();
33901
33902 $this->partialPackagesByName = array();
33903 foreach ($rootData['packages'] as $package => $versions) {
33904 $package = strtolower($package);
33905 foreach ($versions as $version) {
33906 $this->partialPackagesByName[$package][] = $version;
33907 if (!empty($version['provide']) && is_array($version['provide'])) {
33908 foreach ($version['provide'] as $provided => $providedVersion) {
33909 $this->partialPackagesByName[strtolower($provided)][] = $version;
33910 }
33911 }
33912 if (!empty($version['replace']) && is_array($version['replace'])) {
33913 foreach ($version['replace'] as $provided => $providedVersion) {
33914 $this->partialPackagesByName[strtolower($provided)][] = $version;
33915 }
33916 }
33917 }
33918 }
33919
33920
33921  $this->rootData = true;
33922 }
33923 }
33924 <?php
33925
33926
33927
33928
33929
33930
33931
33932
33933
33934
33935
33936 namespace Composer\Repository;
33937
33938 use Composer\Package\PackageInterface;
33939
33940
33941
33942
33943
33944
33945 class CompositeRepository extends BaseRepository
33946 {
33947
33948
33949
33950
33951 private $repositories;
33952
33953
33954
33955
33956
33957 public function __construct(array $repositories)
33958 {
33959 $this->repositories = array();
33960 foreach ($repositories as $repo) {
33961 $this->addRepository($repo);
33962 }
33963 }
33964
33965
33966
33967
33968
33969
33970 public function getRepositories()
33971 {
33972 return $this->repositories;
33973 }
33974
33975
33976
33977
33978 public function hasPackage(PackageInterface $package)
33979 {
33980 foreach ($this->repositories as $repository) {
33981
33982 if ($repository->hasPackage($package)) {
33983 return true;
33984 }
33985 }
33986
33987 return false;
33988 }
33989
33990
33991
33992
33993 public function findPackage($name, $constraint)
33994 {
33995 foreach ($this->repositories as $repository) {
33996
33997 $package = $repository->findPackage($name, $constraint);
33998 if (null !== $package) {
33999 return $package;
34000 }
34001 }
34002
34003 return null;
34004 }
34005
34006
34007
34008
34009 public function findPackages($name, $constraint = null)
34010 {
34011 $packages = array();
34012 foreach ($this->repositories as $repository) {
34013
34014 $packages[] = $repository->findPackages($name, $constraint);
34015 }
34016
34017 return $packages ? call_user_func_array('array_merge', $packages) : array();
34018 }
34019
34020
34021
34022
34023 public function search($query, $mode = 0, $type = null)
34024 {
34025 $matches = array();
34026 foreach ($this->repositories as $repository) {
34027
34028 $matches[] = $repository->search($query, $mode, $type);
34029 }
34030
34031 return $matches ? call_user_func_array('array_merge', $matches) : array();
34032 }
34033
34034
34035
34036
34037 public function getPackages()
34038 {
34039 $packages = array();
34040 foreach ($this->repositories as $repository) {
34041
34042 $packages[] = $repository->getPackages();
34043 }
34044
34045 return $packages ? call_user_func_array('array_merge', $packages) : array();
34046 }
34047
34048
34049
34050
34051 public function removePackage(PackageInterface $package)
34052 {
34053 foreach ($this->repositories as $repository) {
34054
34055 $repository->removePackage($package);
34056 }
34057 }
34058
34059
34060
34061
34062 public function count()
34063 {
34064 $total = 0;
34065 foreach ($this->repositories as $repository) {
34066
34067 $total += $repository->count();
34068 }
34069
34070 return $total;
34071 }
34072
34073
34074
34075
34076
34077 public function addRepository(RepositoryInterface $repository)
34078 {
34079 if ($repository instanceof self) {
34080 foreach ($repository->getRepositories() as $repo) {
34081 $this->addRepository($repo);
34082 }
34083 } else {
34084 $this->repositories[] = $repository;
34085 }
34086 }
34087 }
34088 <?php
34089
34090
34091
34092
34093
34094
34095
34096
34097
34098
34099
34100 namespace Composer\Repository;
34101
34102
34103
34104
34105
34106
34107 interface ConfigurableRepositoryInterface
34108 {
34109 public function getRepoConfig();
34110 }
34111 <?php
34112
34113
34114
34115
34116
34117
34118
34119
34120
34121
34122
34123 namespace Composer\Repository;
34124
34125 use Composer\Json\JsonFile;
34126 use Composer\Package\Loader\ArrayLoader;
34127 use Composer\Package\Dumper\ArrayDumper;
34128
34129
34130
34131
34132
34133
34134
34135 class FilesystemRepository extends WritableArrayRepository
34136 {
34137 private $file;
34138
34139
34140
34141
34142
34143
34144 public function __construct(JsonFile $repositoryFile)
34145 {
34146 parent::__construct();
34147 $this->file = $repositoryFile;
34148 }
34149
34150
34151
34152
34153 protected function initialize()
34154 {
34155 parent::initialize();
34156
34157 if (!$this->file->exists()) {
34158 return;
34159 }
34160
34161 try {
34162 $packages = $this->file->read();
34163
34164
34165  if (isset($packages['packages'])) {
34166 $packages = $packages['packages'];
34167 }
34168
34169 if (!is_array($packages)) {
34170 throw new \UnexpectedValueException('Could not parse package list from the repository');
34171 }
34172 } catch (\Exception $e) {
34173 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
34174 }
34175
34176 $loader = new ArrayLoader(null, true);
34177 foreach ($packages as $packageData) {
34178 $package = $loader->load($packageData);
34179 $this->addPackage($package);
34180 }
34181 }
34182
34183 public function reload()
34184 {
34185 $this->packages = null;
34186 $this->initialize();
34187 }
34188
34189
34190
34191
34192 public function write()
34193 {
34194 $data = array();
34195 $dumper = new ArrayDumper();
34196
34197 foreach ($this->getCanonicalPackages() as $package) {
34198 $data[] = $dumper->dump($package);
34199 }
34200
34201 usort($data, function ($a, $b) {
34202 return strcmp($a['name'], $b['name']);
34203 });
34204
34205 $this->file->write($data);
34206 }
34207 }
34208 <?php
34209
34210
34211
34212
34213
34214
34215
34216
34217
34218
34219
34220 namespace Composer\Repository;
34221
34222
34223
34224
34225
34226
34227
34228
34229 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
34230 {
34231 }
34232 <?php
34233
34234
34235
34236
34237
34238
34239
34240
34241
34242
34243
34244 namespace Composer\Repository;
34245
34246
34247
34248
34249
34250
34251 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
34252 {
34253 }
34254 <?php
34255
34256
34257
34258
34259
34260
34261
34262
34263
34264
34265
34266 namespace Composer\Repository;
34267
34268
34269
34270
34271
34272
34273
34274
34275 interface InstalledRepositoryInterface extends WritableRepositoryInterface
34276 {
34277 }
34278 <?php
34279
34280
34281
34282
34283
34284
34285
34286
34287
34288
34289
34290 namespace Composer\Repository;
34291
34292
34293
34294
34295
34296
34297 class InvalidRepositoryException extends \Exception
34298 {
34299 }
34300 <?php
34301
34302
34303
34304
34305
34306
34307
34308
34309
34310
34311
34312 namespace Composer\Repository;
34313
34314 use Composer\Package\Loader\ArrayLoader;
34315 use Composer\Package\Loader\ValidatingArrayLoader;
34316
34317
34318
34319
34320
34321
34322 class PackageRepository extends ArrayRepository
34323 {
34324 private $config;
34325
34326
34327
34328
34329
34330
34331 public function __construct(array $config)
34332 {
34333 parent::__construct();
34334 $this->config = $config['package'];
34335
34336
34337  if (!is_numeric(key($this->config))) {
34338 $this->config = array($this->config);
34339 }
34340 }
34341
34342
34343
34344
34345 protected function initialize()
34346 {
34347 parent::initialize();
34348
34349 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
34350 foreach ($this->config as $package) {
34351 try {
34352 $package = $loader->load($package);
34353 } catch (\Exception $e) {
34354 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
34355 }
34356
34357 $this->addPackage($package);
34358 }
34359 }
34360 }
34361 <?php
34362
34363
34364
34365
34366
34367
34368
34369
34370
34371
34372
34373 namespace Composer\Repository;
34374
34375 use Composer\Config;
34376 use Composer\IO\IOInterface;
34377 use Composer\Json\JsonFile;
34378 use Composer\Package\Loader\ArrayLoader;
34379 use Composer\Package\Version\VersionGuesser;
34380 use Composer\Package\Version\VersionParser;
34381 use Composer\Util\Platform;
34382 use Composer\Util\ProcessExecutor;
34383
34384
34385
34386
34387
34388
34389
34390
34391
34392
34393
34394
34395
34396
34397
34398
34399
34400
34401
34402
34403
34404
34405
34406
34407
34408
34409
34410
34411
34412
34413
34414
34415
34416
34417
34418
34419 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
34420 {
34421
34422
34423
34424 private $loader;
34425
34426
34427
34428
34429 private $versionGuesser;
34430
34431
34432
34433
34434 private $url;
34435
34436
34437
34438
34439 private $repoConfig;
34440
34441
34442
34443
34444 private $process;
34445
34446
34447
34448
34449 private $options;
34450
34451
34452
34453
34454
34455
34456
34457
34458 public function __construct(array $repoConfig, IOInterface $io, Config $config)
34459 {
34460 if (!isset($repoConfig['url'])) {
34461 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
34462 }
34463
34464 $this->loader = new ArrayLoader(null, true);
34465 $this->url = Platform::expandPath($repoConfig['url']);
34466 $this->process = new ProcessExecutor($io);
34467 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
34468 $this->repoConfig = $repoConfig;
34469 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
34470
34471 parent::__construct();
34472 }
34473
34474 public function getRepoConfig()
34475 {
34476 return $this->repoConfig;
34477 }
34478
34479
34480
34481
34482
34483
34484 protected function initialize()
34485 {
34486 parent::initialize();
34487
34488 foreach ($this->getUrlMatches() as $url) {
34489 $path = realpath($url) . DIRECTORY_SEPARATOR;
34490 $composerFilePath = $path.'composer.json';
34491
34492 if (!file_exists($composerFilePath)) {
34493 continue;
34494 }
34495
34496 $json = file_get_contents($composerFilePath);
34497 $package = JsonFile::parseJson($json, $composerFilePath);
34498 $package['dist'] = array(
34499 'type' => 'path',
34500 'url' => $url,
34501 'reference' => sha1($json . serialize($this->options)),
34502 );
34503 $package['transport-options'] = $this->options;
34504
34505
34506  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
34507 if (
34508 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
34509 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
34510 && $ref1 === $ref2
34511 ) {
34512 $package['version'] = $rootVersion;
34513 }
34514 }
34515
34516 if (!isset($package['version'])) {
34517 $versionData = $this->versionGuesser->guessVersion($package, $path);
34518 if (is_array($versionData) && $versionData['pretty_version']) {
34519 $package['version'] = $versionData['pretty_version'];
34520 } else {
34521 $package['version'] = 'dev-master';
34522 }
34523 }
34524
34525 $output = '';
34526 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
34527 $package['dist']['reference'] = trim($output);
34528 }
34529 $package = $this->loader->load($package);
34530 $this->addPackage($package);
34531 }
34532 }
34533
34534
34535
34536
34537
34538
34539 private function getUrlMatches()
34540 {
34541 $flags = GLOB_MARK | GLOB_ONLYDIR;
34542
34543 if (defined('GLOB_BRACE')) {
34544 $flags |= GLOB_BRACE;
34545 } elseif (strpos($this->url, '{') !== false || strpos($this->url, '}') !== false) {
34546 throw new \RuntimeException('The operating system does not support GLOB_BRACE which is required for the url '. $this->url);
34547 }
34548
34549
34550  return array_map(function ($val) {
34551 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
34552 }, glob($this->url, $flags));
34553 }
34554 }
34555 <?php
34556
34557
34558
34559
34560
34561
34562
34563
34564
34565
34566
34567 namespace Composer\Repository\Pear;
34568
34569 use Composer\Util\RemoteFilesystem;
34570
34571
34572
34573
34574
34575
34576
34577
34578 abstract class BaseChannelReader
34579 {
34580
34581
34582
34583 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
34584 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
34585 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
34586 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
34587 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
34588 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
34589
34590
34591 private $rfs;
34592
34593 protected function __construct(RemoteFilesystem $rfs)
34594 {
34595 $this->rfs = $rfs;
34596 }
34597
34598
34599
34600
34601
34602
34603
34604
34605
34606 protected function requestContent($origin, $path)
34607 {
34608 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
34609 $content = $this->rfs->getContents($origin, $url, false);
34610 if (!$content) {
34611 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
34612 }
34613
34614 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
34615 }
34616
34617
34618
34619
34620
34621
34622
34623
34624
34625 protected function requestXml($origin, $path)
34626 {
34627
34628  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
34629
34630 if (false === $xml) {
34631 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
34632 }
34633
34634 return $xml;
34635 }
34636 }
34637 <?php
34638
34639
34640
34641
34642
34643
34644
34645
34646
34647
34648
34649 namespace Composer\Repository\Pear;
34650
34651
34652
34653
34654
34655
34656 class ChannelInfo
34657 {
34658 private $name;
34659 private $alias;
34660 private $packages;
34661
34662
34663
34664
34665
34666
34667 public function __construct($name, $alias, array $packages)
34668 {
34669 $this->name = $name;
34670 $this->alias = $alias;
34671 $this->packages = $packages;
34672 }
34673
34674
34675
34676
34677
34678
34679 public function getName()
34680 {
34681 return $this->name;
34682 }
34683
34684
34685
34686
34687
34688
34689 public function getAlias()
34690 {
34691 return $this->alias;
34692 }
34693
34694
34695
34696
34697
34698
34699 public function getPackages()
34700 {
34701 return $this->packages;
34702 }
34703 }
34704 <?php
34705
34706
34707
34708
34709
34710
34711
34712
34713
34714
34715
34716 namespace Composer\Repository\Pear;
34717
34718 use Composer\Util\RemoteFilesystem;
34719
34720
34721
34722
34723
34724
34725
34726
34727 class ChannelReader extends BaseChannelReader
34728 {
34729
34730 private $readerMap;
34731
34732 public function __construct(RemoteFilesystem $rfs)
34733 {
34734 parent::__construct($rfs);
34735
34736 $rest10reader = new ChannelRest10Reader($rfs);
34737 $rest11reader = new ChannelRest11Reader($rfs);
34738
34739 $this->readerMap = array(
34740 'REST1.3' => $rest11reader,
34741 'REST1.2' => $rest11reader,
34742 'REST1.1' => $rest11reader,
34743 'REST1.0' => $rest10reader,
34744 );
34745 }
34746
34747
34748
34749
34750
34751
34752
34753
34754 public function read($url)
34755 {
34756 $xml = $this->requestXml($url, "/channel.xml");
34757
34758 $channelName = (string) $xml->name;
34759 $channelAlias = (string) $xml->suggestedalias;
34760
34761 $supportedVersions = array_keys($this->readerMap);
34762 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
34763 if (!$selectedRestVersion) {
34764 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
34765 }
34766
34767 $reader = $this->readerMap[$selectedRestVersion['version']];
34768 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
34769
34770 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
34771 }
34772
34773
34774
34775
34776
34777
34778
34779
34780 private function selectRestVersion($channelXml, $supportedVersions)
34781 {
34782 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
34783
34784 foreach ($supportedVersions as $version) {
34785 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
34786 $testResult = $channelXml->xpath($xpathTest);
34787
34788 foreach ($testResult as $result) {
34789
34790  $result = (string) $result;
34791 if (preg_match('{^https://}i', $result)) {
34792 return array('version' => $version, 'baseUrl' => $result);
34793 }
34794 }
34795
34796
34797  if (count($testResult) > 0) {
34798 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
34799 }
34800 }
34801
34802 return null;
34803 }
34804 }
34805 <?php
34806
34807
34808
34809
34810
34811
34812
34813
34814
34815
34816
34817 namespace Composer\Repository\Pear;
34818
34819 use Composer\Downloader\TransportException;
34820
34821
34822
34823
34824
34825
34826
34827
34828
34829
34830
34831
34832 class ChannelRest10Reader extends BaseChannelReader
34833 {
34834 private $dependencyReader;
34835
34836 public function __construct($rfs)
34837 {
34838 parent::__construct($rfs);
34839
34840 $this->dependencyReader = new PackageDependencyParser();
34841 }
34842
34843
34844
34845
34846
34847
34848
34849
34850 public function read($baseUrl)
34851 {
34852 return $this->readPackages($baseUrl);
34853 }
34854
34855
34856
34857
34858
34859
34860
34861
34862 private function readPackages($baseUrl)
34863 {
34864 $result = array();
34865
34866 $xmlPath = '/p/packages.xml';
34867 $xml = $this->requestXml($baseUrl, $xmlPath);
34868 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
34869 foreach ($xml->xpath('ns:p') as $node) {
34870 $packageName = (string) $node;
34871 $packageInfo = $this->readPackage($baseUrl, $packageName);
34872 $result[] = $packageInfo;
34873 }
34874
34875 return $result;
34876 }
34877
34878
34879
34880
34881
34882
34883
34884
34885
34886 private function readPackage($baseUrl, $packageName)
34887 {
34888 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
34889 $xml = $this->requestXml($baseUrl, $xmlPath);
34890 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
34891
34892 $channelName = (string) $xml->c;
34893 $packageName = (string) $xml->n;
34894 $license = (string) $xml->l;
34895 $shortDescription = (string) $xml->s;
34896 $description = (string) $xml->d;
34897
34898 return new PackageInfo(
34899 $channelName,
34900 $packageName,
34901 $license,
34902 $shortDescription,
34903 $description,
34904 $this->readPackageReleases($baseUrl, $packageName)
34905 );
34906 }
34907
34908
34909
34910
34911
34912
34913
34914
34915
34916
34917 private function readPackageReleases($baseUrl, $packageName)
34918 {
34919 $result = array();
34920
34921 try {
34922 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
34923 $xml = $this->requestXml($baseUrl, $xmlPath);
34924 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
34925 foreach ($xml->xpath('ns:r') as $node) {
34926 $releaseVersion = (string) $node->v;
34927 $releaseStability = (string) $node->s;
34928
34929 try {
34930 $result[$releaseVersion] = new ReleaseInfo(
34931 $releaseStability,
34932 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
34933 );
34934 } catch (TransportException $exception) {
34935 if ($exception->getCode() != 404) {
34936 throw $exception;
34937 }
34938 }
34939 }
34940 } catch (TransportException $exception) {
34941 if ($exception->getCode() != 404) {
34942 throw $exception;
34943 }
34944 }
34945
34946 return $result;
34947 }
34948
34949
34950
34951
34952
34953
34954
34955
34956
34957
34958 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
34959 {
34960 $dependencyReader = new PackageDependencyParser();
34961
34962 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
34963 $content = $this->requestContent($baseUrl, $depthPath);
34964 $dependencyArray = unserialize($content);
34965
34966 return $dependencyReader->buildDependencyInfo($dependencyArray);
34967 }
34968 }
34969 <?php
34970
34971
34972
34973
34974
34975
34976
34977
34978
34979
34980
34981 namespace Composer\Repository\Pear;
34982
34983
34984
34985
34986
34987
34988
34989
34990
34991
34992 class ChannelRest11Reader extends BaseChannelReader
34993 {
34994 private $dependencyReader;
34995
34996 public function __construct($rfs)
34997 {
34998 parent::__construct($rfs);
34999
35000 $this->dependencyReader = new PackageDependencyParser();
35001 }
35002
35003
35004
35005
35006
35007
35008
35009
35010 public function read($baseUrl)
35011 {
35012 return $this->readChannelPackages($baseUrl);
35013 }
35014
35015
35016
35017
35018
35019
35020
35021
35022 private function readChannelPackages($baseUrl)
35023 {
35024 $result = array();
35025
35026 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
35027 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
35028 foreach ($xml->xpath('ns:c') as $node) {
35029 $categoryName = (string) $node;
35030 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
35031 $result = array_merge($result, $categoryPackages);
35032 }
35033
35034 return $result;
35035 }
35036
35037
35038
35039
35040
35041
35042
35043
35044
35045 private function readCategoryPackages($baseUrl, $categoryName)
35046 {
35047 $result = array();
35048
35049 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
35050 $xml = $this->requestXml($baseUrl, $categoryPath);
35051 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
35052 foreach ($xml->xpath('ns:pi') as $node) {
35053 $packageInfo = $this->parsePackage($node);
35054 $result[] = $packageInfo;
35055 }
35056
35057 return $result;
35058 }
35059
35060
35061
35062
35063
35064
35065
35066 private function parsePackage($packageInfo)
35067 {
35068 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
35069 $channelName = (string) $packageInfo->p->c;
35070 $packageName = (string) $packageInfo->p->n;
35071 $license = (string) $packageInfo->p->l;
35072 $shortDescription = (string) $packageInfo->p->s;
35073 $description = (string) $packageInfo->p->d;
35074
35075 $dependencies = array();
35076 foreach ($packageInfo->xpath('ns:deps') as $node) {
35077 $dependencyVersion = (string) $node->v;
35078 $dependencyArray = unserialize((string) $node->d);
35079
35080 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
35081
35082 $dependencies[$dependencyVersion] = $dependencyInfo;
35083 }
35084
35085 $releases = array();
35086 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
35087 if ($releasesInfo) {
35088 foreach ($releasesInfo as $node) {
35089 $releaseVersion = (string) $node->v;
35090 $releaseStability = (string) $node->s;
35091 $releases[$releaseVersion] = new ReleaseInfo(
35092 $releaseStability,
35093 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
35094 );
35095 }
35096 }
35097
35098 return new PackageInfo(
35099 $channelName,
35100 $packageName,
35101 $license,
35102 $shortDescription,
35103 $description,
35104 $releases
35105 );
35106 }
35107 }
35108 <?php
35109
35110
35111
35112
35113
35114
35115
35116
35117
35118
35119
35120 namespace Composer\Repository\Pear;
35121
35122
35123
35124
35125
35126
35127 class DependencyConstraint
35128 {
35129 private $type;
35130 private $constraint;
35131 private $channelName;
35132 private $packageName;
35133
35134
35135
35136
35137
35138
35139
35140 public function __construct($type, $constraint, $channelName, $packageName)
35141 {
35142 $this->type = $type;
35143 $this->constraint = $constraint;
35144 $this->channelName = $channelName;
35145 $this->packageName = $packageName;
35146 }
35147
35148 public function getChannelName()
35149 {
35150 return $this->channelName;
35151 }
35152
35153 public function getConstraint()
35154 {
35155 return $this->constraint;
35156 }
35157
35158 public function getPackageName()
35159 {
35160 return $this->packageName;
35161 }
35162
35163 public function getType()
35164 {
35165 return $this->type;
35166 }
35167 }
35168 <?php
35169
35170
35171
35172
35173
35174
35175
35176
35177
35178
35179
35180 namespace Composer\Repository\Pear;
35181
35182
35183
35184
35185
35186
35187 class DependencyInfo
35188 {
35189 private $requires;
35190 private $optionals;
35191
35192
35193
35194
35195
35196 public function __construct($requires, $optionals)
35197 {
35198 $this->requires = $requires;
35199 $this->optionals = $optionals;
35200 }
35201
35202
35203
35204
35205 public function getRequires()
35206 {
35207 return $this->requires;
35208 }
35209
35210
35211
35212
35213 public function getOptionals()
35214 {
35215 return $this->optionals;
35216 }
35217 }
35218 <?php
35219
35220
35221
35222
35223
35224
35225
35226
35227
35228
35229
35230 namespace Composer\Repository\Pear;
35231
35232
35233
35234
35235
35236
35237 class PackageDependencyParser
35238 {
35239
35240
35241
35242
35243
35244
35245 public function buildDependencyInfo($depArray)
35246 {
35247 if (!is_array($depArray)) {
35248 return new DependencyInfo(array(), array());
35249 }
35250 if (!$this->isHash($depArray)) {
35251 return new DependencyInfo($this->buildDependency10Info($depArray), array());
35252 }
35253
35254 return $this->buildDependency20Info($depArray);
35255 }
35256
35257
35258
35259
35260
35261
35262
35263
35264
35265
35266
35267
35268
35269 private function buildDependency10Info($depArray)
35270 {
35271 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
35272
35273 $result = array();
35274
35275 foreach ($depArray as $depItem) {
35276 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
35277
35278  continue;
35279 }
35280
35281 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
35282 ? 'optional'
35283 : 'required';
35284 $depType = 'not' == $depItem['rel']
35285 ? 'conflicts'
35286 : $depType;
35287
35288 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
35289
35290
35291  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
35292 ? '*'
35293 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
35294
35295 switch ($depItem['type']) {
35296 case 'php':
35297 $depChannelName = 'php';
35298 $depPackageName = '';
35299 break;
35300 case 'pkg':
35301 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
35302 $depPackageName = $depItem['name'];
35303 break;
35304 case 'ext':
35305 $depChannelName = 'ext';
35306 $depPackageName = $depItem['name'];
35307 break;
35308 case 'os':
35309 case 'sapi':
35310 $depChannelName = '';
35311 $depPackageName = '';
35312 break;
35313 default:
35314 $depChannelName = '';
35315 $depPackageName = '';
35316 break;
35317 }
35318
35319 if ('' != $depChannelName) {
35320 $result[] = new DependencyConstraint(
35321 $depType,
35322 $depVersionConstraint,
35323 $depChannelName,
35324 $depPackageName
35325 );
35326 }
35327 }
35328
35329 return $result;
35330 }
35331
35332
35333
35334
35335
35336
35337
35338 private function buildDependency20Info($depArray)
35339 {
35340 $result = array();
35341 $optionals = array();
35342 $defaultOptionals = array();
35343 foreach ($depArray as $depType => $depTypeGroup) {
35344 if (!is_array($depTypeGroup)) {
35345 continue;
35346 }
35347 if ('required' == $depType || 'optional' == $depType) {
35348 foreach ($depTypeGroup as $depItemType => $depItem) {
35349 switch ($depItemType) {
35350 case 'php':
35351 $result[] = new DependencyConstraint(
35352 $depType,
35353 $this->parse20VersionConstraint($depItem),
35354 'php',
35355 ''
35356 );
35357 break;
35358 case 'package':
35359 $deps = $this->buildDepPackageConstraints($depItem, $depType);
35360 $result = array_merge($result, $deps);
35361 break;
35362 case 'extension':
35363 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
35364 $result = array_merge($result, $deps);
35365 break;
35366 case 'subpackage':
35367 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
35368 $defaultOptionals += $deps;
35369 break;
35370 case 'os':
35371 case 'pearinstaller':
35372 break;
35373 default:
35374 break;
35375 }
35376 }
35377 } elseif ('group' == $depType) {
35378 if ($this->isHash($depTypeGroup)) {
35379 $depTypeGroup = array($depTypeGroup);
35380 }
35381
35382 foreach ($depTypeGroup as $depItem) {
35383 $groupName = $depItem['attribs']['name'];
35384 if (!isset($optionals[$groupName])) {
35385 $optionals[$groupName] = array();
35386 }
35387
35388 if (isset($depItem['subpackage'])) {
35389 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
35390 } else {
35391 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
35392 }
35393 }
35394 }
35395 }
35396
35397 if (count($defaultOptionals) > 0) {
35398 $optionals['*'] = $defaultOptionals;
35399 }
35400
35401 return new DependencyInfo($result, $optionals);
35402 }
35403
35404
35405
35406
35407
35408
35409
35410
35411 private function buildDepExtensionConstraints($depItem, $depType)
35412 {
35413 if ($this->isHash($depItem)) {
35414 $depItem = array($depItem);
35415 }
35416
35417 $result = array();
35418 foreach ($depItem as $subDepItem) {
35419 $depChannelName = 'ext';
35420 $depPackageName = $subDepItem['name'];
35421 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
35422
35423 $result[] = new DependencyConstraint(
35424 $depType,
35425 $depVersionConstraint,
35426 $depChannelName,
35427 $depPackageName
35428 );
35429 }
35430
35431 return $result;
35432 }
35433
35434
35435
35436
35437
35438
35439
35440
35441 private function buildDepPackageConstraints($depItem, $depType)
35442 {
35443 if ($this->isHash($depItem)) {
35444 $depItem = array($depItem);
35445 }
35446
35447 $result = array();
35448 foreach ($depItem as $subDepItem) {
35449 if (!array_key_exists('channel', $subDepItem)) {
35450 $subDepItem['channel'] = $subDepItem['uri'];
35451 }
35452 $depChannelName = $subDepItem['channel'];
35453 $depPackageName = $subDepItem['name'];
35454 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
35455 if (isset($subDepItem['conflicts'])) {
35456 $depType = 'conflicts';
35457 }
35458
35459 $result[] = new DependencyConstraint(
35460 $depType,
35461 $depVersionConstraint,
35462 $depChannelName,
35463 $depPackageName
35464 );
35465 }
35466
35467 return $result;
35468 }
35469
35470
35471
35472
35473
35474
35475
35476 private function parse20VersionConstraint(array $data)
35477 {
35478 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
35479
35480 $versions = array();
35481 $values = array_intersect_key($data, $dep20toOperatorMap);
35482 if (0 == count($values)) {
35483 return '*';
35484 }
35485 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
35486 $versions[] = '>' . $this->parseVersion($values['min']);
35487 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
35488 $versions[] = '<' . $this->parseVersion($values['max']);
35489 } else {
35490 foreach ($values as $op => $version) {
35491 if ('exclude' == $op && is_array($version)) {
35492 foreach ($version as $versionPart) {
35493 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
35494 }
35495 } else {
35496 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
35497 }
35498 }
35499 }
35500
35501 return implode(',', $versions);
35502 }
35503
35504
35505
35506
35507
35508
35509
35510 private function parseVersion($version)
35511 {
35512 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
35513 $version = $matches[1]
35514 .(!empty($matches[2]) ? $matches[2] : '.0')
35515 .(!empty($matches[3]) ? $matches[3] : '.0')
35516 .(!empty($matches[4]) ? $matches[4] : '.0');
35517
35518 return $version;
35519 }
35520
35521 return null;
35522 }
35523
35524
35525
35526
35527
35528
35529
35530 private function isHash(array $array)
35531 {
35532 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
35533 }
35534 }
35535 <?php
35536
35537
35538
35539
35540
35541
35542
35543
35544
35545
35546
35547 namespace Composer\Repository\Pear;
35548
35549
35550
35551
35552
35553
35554 class PackageInfo
35555 {
35556 private $channelName;
35557 private $packageName;
35558 private $license;
35559 private $shortDescription;
35560 private $description;
35561 private $releases;
35562
35563
35564
35565
35566
35567
35568
35569
35570
35571 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
35572 {
35573 $this->channelName = $channelName;
35574 $this->packageName = $packageName;
35575 $this->license = $license;
35576 $this->shortDescription = $shortDescription;
35577 $this->description = $description;
35578 $this->releases = $releases;
35579 }
35580
35581
35582
35583
35584 public function getChannelName()
35585 {
35586 return $this->channelName;
35587 }
35588
35589
35590
35591
35592 public function getPackageName()
35593 {
35594 return $this->packageName;
35595 }
35596
35597
35598
35599
35600 public function getDescription()
35601 {
35602 return $this->description;
35603 }
35604
35605
35606
35607
35608 public function getShortDescription()
35609 {
35610 return $this->shortDescription;
35611 }
35612
35613
35614
35615
35616 public function getLicense()
35617 {
35618 return $this->license;
35619 }
35620
35621
35622
35623
35624 public function getReleases()
35625 {
35626 return $this->releases;
35627 }
35628 }
35629 <?php
35630
35631
35632
35633
35634
35635
35636
35637
35638
35639
35640
35641 namespace Composer\Repository\Pear;
35642
35643
35644
35645
35646
35647
35648 class ReleaseInfo
35649 {
35650 private $stability;
35651 private $dependencyInfo;
35652
35653
35654
35655
35656
35657 public function __construct($stability, $dependencyInfo)
35658 {
35659 $this->stability = $stability;
35660 $this->dependencyInfo = $dependencyInfo;
35661 }
35662
35663
35664
35665
35666 public function getDependencyInfo()
35667 {
35668 return $this->dependencyInfo;
35669 }
35670
35671
35672
35673
35674 public function getStability()
35675 {
35676 return $this->stability;
35677 }
35678 }
35679 <?php
35680
35681
35682
35683
35684
35685
35686
35687
35688
35689
35690
35691 namespace Composer\Repository;
35692
35693 use Composer\IO\IOInterface;
35694 use Composer\Semver\VersionParser as SemverVersionParser;
35695 use Composer\Package\Version\VersionParser;
35696 use Composer\Repository\Pear\ChannelReader;
35697 use Composer\Package\CompletePackage;
35698 use Composer\Repository\Pear\ChannelInfo;
35699 use Composer\EventDispatcher\EventDispatcher;
35700 use Composer\Package\Link;
35701 use Composer\Semver\Constraint\Constraint;
35702 use Composer\Util\RemoteFilesystem;
35703 use Composer\Config;
35704 use Composer\Factory;
35705
35706
35707
35708
35709
35710
35711
35712
35713
35714
35715 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
35716 {
35717 private $url;
35718 private $io;
35719 private $rfs;
35720 private $versionParser;
35721 private $repoConfig;
35722
35723
35724
35725
35726 private $vendorAlias;
35727
35728 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
35729 {
35730 parent::__construct();
35731 if (!preg_match('{^https?://}', $repoConfig['url'])) {
35732 $repoConfig['url'] = 'http://'.$repoConfig['url'];
35733 }
35734
35735 $urlBits = parse_url($repoConfig['url']);
35736 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
35737 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
35738 }
35739
35740 $this->url = rtrim($repoConfig['url'], '/');
35741 $this->io = $io;
35742 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
35743 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
35744 $this->versionParser = new VersionParser();
35745 $this->repoConfig = $repoConfig;
35746 }
35747
35748 public function getRepoConfig()
35749 {
35750 return $this->repoConfig;
35751 }
35752
35753 protected function initialize()
35754 {
35755 parent::initialize();
35756
35757 $this->io->writeError('Initializing PEAR repository '.$this->url);
35758
35759 $reader = new ChannelReader($this->rfs);
35760 try {
35761 $channelInfo = $reader->read($this->url);
35762 } catch (\Exception $e) {
35763 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
35764
35765 return;
35766 }
35767 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
35768 foreach ($packages as $package) {
35769 $this->addPackage($package);
35770 }
35771 }
35772
35773
35774
35775
35776
35777
35778
35779
35780 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
35781 {
35782 $result = array();
35783 foreach ($channelInfo->getPackages() as $packageDefinition) {
35784 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
35785 try {
35786 $normalizedVersion = $versionParser->normalize($version);
35787 } catch (\UnexpectedValueException $e) {
35788 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
35789 continue;
35790 }
35791
35792 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
35793
35794
35795  
35796  $urlBits = parse_url($this->url);
35797 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
35798 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
35799
35800 $requires = array();
35801 $suggests = array();
35802 $conflicts = array();
35803 $replaces = array();
35804
35805
35806  
35807  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
35808 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
35809 $aliasConstraint = new Constraint('==', $normalizedVersion);
35810 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
35811 }
35812
35813
35814  if (!empty($this->vendorAlias)
35815 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
35816 ) {
35817 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
35818 $aliasConstraint = new Constraint('==', $normalizedVersion);
35819 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
35820 }
35821
35822 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
35823 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
35824 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
35825 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
35826 switch ($dependencyConstraint->getType()) {
35827 case 'required':
35828 $requires[] = $link;
35829 break;
35830 case 'conflicts':
35831 $conflicts[] = $link;
35832 break;
35833 case 'replaces':
35834 $replaces[] = $link;
35835 break;
35836 }
35837 }
35838
35839 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
35840 foreach ($dependencyConstraints as $dependencyConstraint) {
35841 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
35842 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
35843 }
35844 }
35845
35846 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
35847 $package->setType('pear-library');
35848 $package->setDescription($packageDefinition->getDescription());
35849 $package->setLicense(array($packageDefinition->getLicense()));
35850 $package->setDistType('file');
35851 $package->setDistUrl($distUrl);
35852 $package->setAutoload(array('classmap' => array('')));
35853 $package->setIncludePaths(array('/'));
35854 $package->setRequires($requires);
35855 $package->setConflicts($conflicts);
35856 $package->setSuggests($suggests);
35857 $package->setReplaces($replaces);
35858 $result[] = $package;
35859 }
35860 }
35861
35862 return $result;
35863 }
35864
35865 private function buildComposerPackageName($channelName, $packageName)
35866 {
35867 if ('php' === $channelName) {
35868 return "php";
35869 }
35870 if ('ext' === $channelName) {
35871 return "ext-{$packageName}";
35872 }
35873
35874 return "pear-{$channelName}/{$packageName}";
35875 }
35876 }
35877 <?php
35878
35879
35880
35881
35882
35883
35884
35885
35886
35887
35888
35889 namespace Composer\Repository;
35890
35891 use Composer\Package\CompletePackage;
35892 use Composer\Package\PackageInterface;
35893 use Composer\Package\Version\VersionParser;
35894 use Composer\Plugin\PluginInterface;
35895 use Composer\Util\ProcessExecutor;
35896 use Composer\Util\Silencer;
35897 use Composer\Util\Platform;
35898 use Composer\XdebugHandler\XdebugHandler;
35899 use Symfony\Component\Process\ExecutableFinder;
35900
35901
35902
35903
35904 class PlatformRepository extends ArrayRepository
35905 {
35906 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-plugin-api)$}iD';
35907
35908 private $versionParser;
35909
35910
35911
35912
35913
35914
35915
35916
35917 private $overrides = array();
35918
35919 private $process;
35920
35921 public function __construct(array $packages = array(), array $overrides = array(), ProcessExecutor $process = null)
35922 {
35923 $this->process = $process === null ? (new ProcessExecutor()) : $process;
35924 foreach ($overrides as $name => $version) {
35925 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
35926 }
35927 parent::__construct($packages);
35928 }
35929
35930 protected function initialize()
35931 {
35932 parent::initialize();
35933
35934 $this->versionParser = new VersionParser();
35935
35936
35937  
35938  foreach ($this->overrides as $override) {
35939
35940  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
35941 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
35942 }
35943
35944 $this->addOverriddenPackage($override);
35945 }
35946
35947 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
35948 $version = $this->versionParser->normalize($prettyVersion);
35949 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
35950 $composerPluginApi->setDescription('The Composer Plugin API');
35951 $this->addPackage($composerPluginApi);
35952
35953 try {
35954 $prettyVersion = PHP_VERSION;
35955 $version = $this->versionParser->normalize($prettyVersion);
35956 } catch (\UnexpectedValueException $e) {
35957 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
35958 $version = $this->versionParser->normalize($prettyVersion);
35959 }
35960
35961 $php = new CompletePackage('php', $version, $prettyVersion);
35962 $php->setDescription('The PHP interpreter');
35963 $this->addPackage($php);
35964
35965 if (PHP_DEBUG) {
35966 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
35967 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
35968 $this->addPackage($phpdebug);
35969 }
35970
35971 if (defined('PHP_ZTS') && PHP_ZTS) {
35972 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
35973 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
35974 $this->addPackage($phpzts);
35975 }
35976
35977 if (PHP_INT_SIZE === 8) {
35978 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
35979 $php64->setDescription('The PHP interpreter, 64bit');
35980 $this->addPackage($php64);
35981 }
35982
35983
35984  
35985  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
35986 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
35987 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
35988 $this->addPackage($phpIpv6);
35989 }
35990
35991 $loadedExtensions = get_loaded_extensions();
35992
35993
35994  foreach ($loadedExtensions as $name) {
35995 if (in_array($name, array('standard', 'Core'))) {
35996 continue;
35997 }
35998
35999 $reflExt = new \ReflectionExtension($name);
36000 $prettyVersion = $reflExt->getVersion();
36001 $this->addExtension($name, $prettyVersion);
36002 }
36003
36004
36005  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = XdebugHandler::getSkippedVersion())) {
36006 $this->addExtension('xdebug', $prettyVersion);
36007 }
36008
36009
36010  
36011  
36012  foreach ($loadedExtensions as $name) {
36013 $prettyVersion = null;
36014 $description = 'The '.$name.' PHP library';
36015 switch ($name) {
36016 case 'curl':
36017 $curlVersion = curl_version();
36018 $prettyVersion = $curlVersion['version'];
36019 break;
36020
36021 case 'iconv':
36022 $prettyVersion = ICONV_VERSION;
36023 break;
36024
36025 case 'intl':
36026 $name = 'ICU';
36027 if (defined('INTL_ICU_VERSION')) {
36028 $prettyVersion = INTL_ICU_VERSION;
36029 } else {
36030 $reflector = new \ReflectionExtension('intl');
36031
36032 ob_start();
36033 $reflector->info();
36034 $output = ob_get_clean();
36035
36036 preg_match('/^ICU version => (.*)$/m', $output, $matches);
36037 $prettyVersion = $matches[1];
36038 }
36039
36040 break;
36041
36042 case 'imagick':
36043 $imagick = new \Imagick();
36044 $imageMagickVersion = $imagick->getVersion();
36045
36046  
36047  preg_match('/^ImageMagick ([\d.]+)(?:-(\d+))?/', $imageMagickVersion['versionString'], $matches);
36048 if (isset($matches[2])) {
36049 $prettyVersion = "{$matches[1]}.{$matches[2]}";
36050 } else {
36051 $prettyVersion = $matches[1];
36052 }
36053 break;
36054
36055 case 'libxml':
36056 $prettyVersion = LIBXML_DOTTED_VERSION;
36057 break;
36058
36059 case 'openssl':
36060 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
36061 if (empty($match[2])) {
36062 return $match[1];
36063 }
36064
36065
36066  
36067
36068 if (!preg_match('{^z*[a-z]$}', $match[2])) {
36069
36070  return 0;
36071 }
36072
36073 $len = strlen($match[2]);
36074 $patchVersion = ($len - 1) * 26; 
36075  $patchVersion += ord($match[2][$len - 1]) - 96;
36076
36077 return $match[1].'.'.$patchVersion;
36078 }, OPENSSL_VERSION_TEXT);
36079
36080 $description = OPENSSL_VERSION_TEXT;
36081 break;
36082
36083 case 'pcre':
36084 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
36085 break;
36086
36087 case 'uuid':
36088 $prettyVersion = phpversion('uuid');
36089 break;
36090
36091 case 'xsl':
36092 $prettyVersion = LIBXSLT_DOTTED_VERSION;
36093 break;
36094
36095 default:
36096
36097  continue 2;
36098 }
36099
36100 try {
36101 $version = $this->versionParser->normalize($prettyVersion);
36102 } catch (\UnexpectedValueException $e) {
36103 continue;
36104 }
36105
36106 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
36107 $lib->setDescription($description);
36108 $this->addPackage($lib);
36109 }
36110
36111 $hhvmVersion = defined('HHVM_VERSION') ? HHVM_VERSION : null;
36112 if ($hhvmVersion === null && !Platform::isWindows()) {
36113 $finder = new ExecutableFinder();
36114 $hhvm = $finder->find('hhvm');
36115 if ($hhvm !== null) {
36116 $exitCode = $this->process->execute(
36117 ProcessExecutor::escape($hhvm).
36118 ' --php -d hhvm.jit=0 -r "echo HHVM_VERSION;" 2>/dev/null',
36119 $hhvmVersion
36120 );
36121 if ($exitCode !== 0) {
36122 $hhvmVersion = null;
36123 }
36124 }
36125 }
36126 if ($hhvmVersion) {
36127 try {
36128 $prettyVersion = $hhvmVersion;
36129 $version = $this->versionParser->normalize($prettyVersion);
36130 } catch (\UnexpectedValueException $e) {
36131 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $hhvmVersion);
36132 $version = $this->versionParser->normalize($prettyVersion);
36133 }
36134
36135 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
36136 $hhvm->setDescription('The HHVM Runtime (64bit)');
36137 $this->addPackage($hhvm);
36138 }
36139 }
36140
36141
36142
36143
36144 public function addPackage(PackageInterface $package)
36145 {
36146
36147  if (isset($this->overrides[$package->getName()])) {
36148 $overrider = $this->findPackage($package->getName(), '*');
36149 if ($package->getVersion() === $overrider->getVersion()) {
36150 $actualText = 'same as actual';
36151 } else {
36152 $actualText = 'actual: '.$package->getPrettyVersion();
36153 }
36154 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
36155
36156 return;
36157 }
36158
36159
36160  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
36161 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
36162 if ($package->getVersion() === $overrider->getVersion()) {
36163 $actualText = 'same as actual';
36164 } else {
36165 $actualText = 'actual: '.$package->getPrettyVersion();
36166 }
36167 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
36168
36169 return;
36170 }
36171
36172 parent::addPackage($package);
36173 }
36174
36175 private function addOverriddenPackage(array $override, $name = null)
36176 {
36177 $version = $this->versionParser->normalize($override['version']);
36178 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
36179 $package->setDescription('Package overridden via config.platform');
36180 $package->setExtra(array('config.platform' => true));
36181 parent::addPackage($package);
36182
36183 return $package;
36184 }
36185
36186
36187
36188
36189
36190
36191
36192 private function addExtension($name, $prettyVersion)
36193 {
36194 $extraDescription = null;
36195
36196 try {
36197 $version = $this->versionParser->normalize($prettyVersion);
36198 } catch (\UnexpectedValueException $e) {
36199 $extraDescription = ' (actual version: '.$prettyVersion.')';
36200 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
36201 $prettyVersion = $match[1];
36202 } else {
36203 $prettyVersion = '0';
36204 }
36205 $version = $this->versionParser->normalize($prettyVersion);
36206 }
36207
36208 $packageName = $this->buildPackageName($name);
36209 $ext = new CompletePackage($packageName, $version, $prettyVersion);
36210 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
36211 $this->addPackage($ext);
36212 }
36213
36214 private function buildPackageName($name)
36215 {
36216 return 'ext-' . str_replace(' ', '-', $name);
36217 }
36218 }
36219 <?php
36220
36221
36222
36223
36224
36225
36226
36227
36228
36229
36230
36231 namespace Composer\Repository;
36232
36233 use Composer\Factory;
36234 use Composer\IO\IOInterface;
36235 use Composer\Config;
36236 use Composer\EventDispatcher\EventDispatcher;
36237 use Composer\Util\RemoteFilesystem;
36238 use Composer\Json\JsonFile;
36239
36240
36241
36242
36243 class RepositoryFactory
36244 {
36245
36246
36247
36248
36249
36250
36251
36252 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
36253 {
36254 if (0 === strpos($repository, 'http')) {
36255 $repoConfig = array('type' => 'composer', 'url' => $repository);
36256 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
36257 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
36258 $data = $json->read();
36259 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
36260 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
36261 } elseif ($allowFilesystem) {
36262 $repoConfig = array('type' => 'filesystem', 'json' => $json);
36263 } else {
36264 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
36265 }
36266 } elseif ('{' === substr($repository, 0, 1)) {
36267
36268  $repoConfig = JsonFile::parseJson($repository);
36269 } else {
36270 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
36271 }
36272
36273 return $repoConfig;
36274 }
36275
36276
36277
36278
36279
36280
36281
36282
36283 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
36284 {
36285 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
36286
36287 return static::createRepo($io, $config, $repoConfig);
36288 }
36289
36290
36291
36292
36293
36294
36295
36296 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
36297 {
36298 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
36299 $repos = static::createRepos($rm, array($repoConfig));
36300
36301 return reset($repos);
36302 }
36303
36304
36305
36306
36307
36308
36309
36310 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
36311 {
36312 if (!$config) {
36313 $config = Factory::createConfig($io);
36314 }
36315 if ($io) {
36316 $io->loadConfiguration($config);
36317 }
36318 if (!$rm) {
36319 if (!$io) {
36320 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
36321 }
36322 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
36323 }
36324
36325 return static::createRepos($rm, $config->getRepositories());
36326 }
36327
36328
36329
36330
36331
36332
36333
36334
36335 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
36336 {
36337 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
36338 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
36339 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
36340 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
36341 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
36342 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
36343 $rm->setRepositoryClass('git-bitbucket', 'Composer\Repository\VcsRepository');
36344 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
36345 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
36346 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
36347 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
36348 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
36349 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
36350 $rm->setRepositoryClass('hg-bitbucket', 'Composer\Repository\VcsRepository');
36351 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
36352 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
36353
36354 return $rm;
36355 }
36356
36357
36358
36359
36360 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
36361 {
36362 $repos = array();
36363
36364 foreach ($repoConfigs as $index => $repo) {
36365 if (is_string($repo)) {
36366 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
36367 }
36368 if (!is_array($repo)) {
36369 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
36370 }
36371 if (!isset($repo['type'])) {
36372 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
36373 }
36374 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
36375 while (isset($repos[$name])) {
36376 $name .= '2';
36377 }
36378 if ($repo['type'] === 'filesystem') {
36379 $repos[$name] = new FilesystemRepository($repo['json']);
36380 } else {
36381 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
36382 }
36383 }
36384
36385 return $repos;
36386 }
36387 }
36388 <?php
36389
36390
36391
36392
36393
36394
36395
36396
36397
36398
36399
36400 namespace Composer\Repository;
36401
36402 use Composer\Package\PackageInterface;
36403
36404
36405
36406
36407
36408
36409
36410
36411 interface RepositoryInterface extends \Countable
36412 {
36413 const SEARCH_FULLTEXT = 0;
36414 const SEARCH_NAME = 1;
36415
36416
36417
36418
36419
36420
36421
36422
36423 public function hasPackage(PackageInterface $package);
36424
36425
36426
36427
36428
36429
36430
36431
36432
36433 public function findPackage($name, $constraint);
36434
36435
36436
36437
36438
36439
36440
36441
36442
36443 public function findPackages($name, $constraint = null);
36444
36445
36446
36447
36448
36449
36450 public function getPackages();
36451
36452
36453
36454
36455
36456
36457
36458
36459
36460 public function search($query, $mode = 0);
36461 }
36462 <?php
36463
36464
36465
36466
36467
36468
36469
36470
36471
36472
36473
36474 namespace Composer\Repository;
36475
36476 use Composer\IO\IOInterface;
36477 use Composer\Config;
36478 use Composer\EventDispatcher\EventDispatcher;
36479 use Composer\Package\PackageInterface;
36480 use Composer\Util\RemoteFilesystem;
36481
36482
36483
36484
36485
36486
36487
36488
36489 class RepositoryManager
36490 {
36491 private $localRepository;
36492 private $repositories = array();
36493 private $repositoryClasses = array();
36494 private $io;
36495 private $config;
36496 private $eventDispatcher;
36497 private $rfs;
36498
36499 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
36500 {
36501 $this->io = $io;
36502 $this->config = $config;
36503 $this->eventDispatcher = $eventDispatcher;
36504 $this->rfs = $rfs;
36505 }
36506
36507
36508
36509
36510
36511
36512
36513
36514
36515 public function findPackage($name, $constraint)
36516 {
36517 foreach ($this->repositories as $repository) {
36518
36519 if ($package = $repository->findPackage($name, $constraint)) {
36520 return $package;
36521 }
36522 }
36523
36524 return null;
36525 }
36526
36527
36528
36529
36530
36531
36532
36533
36534
36535 public function findPackages($name, $constraint)
36536 {
36537 $packages = array();
36538
36539 foreach ($this->getRepositories() as $repository) {
36540 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
36541 }
36542
36543 return $packages;
36544 }
36545
36546
36547
36548
36549
36550
36551 public function addRepository(RepositoryInterface $repository)
36552 {
36553 $this->repositories[] = $repository;
36554 }
36555
36556
36557
36558
36559
36560
36561
36562
36563 public function prependRepository(RepositoryInterface $repository)
36564 {
36565 array_unshift($this->repositories, $repository);
36566 }
36567
36568
36569
36570
36571
36572
36573
36574
36575
36576
36577 public function createRepository($type, $config, $name = null)
36578 {
36579 if (!isset($this->repositoryClasses[$type])) {
36580 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
36581 }
36582
36583 if (isset($config['packagist']) && false === $config['packagist']) {
36584 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
36585 }
36586
36587 $class = $this->repositoryClasses[$type];
36588
36589 $reflMethod = new \ReflectionMethod($class, '__construct');
36590 $params = $reflMethod->getParameters();
36591 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
36592 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
36593 }
36594
36595 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
36596 }
36597
36598
36599
36600
36601
36602
36603
36604 public function setRepositoryClass($type, $class)
36605 {
36606 $this->repositoryClasses[$type] = $class;
36607 }
36608
36609
36610
36611
36612
36613
36614 public function getRepositories()
36615 {
36616 return $this->repositories;
36617 }
36618
36619
36620
36621
36622
36623
36624 public function setLocalRepository(WritableRepositoryInterface $repository)
36625 {
36626 $this->localRepository = $repository;
36627 }
36628
36629
36630
36631
36632
36633
36634 public function getLocalRepository()
36635 {
36636 return $this->localRepository;
36637 }
36638 }
36639 <?php
36640
36641
36642
36643
36644
36645
36646
36647
36648
36649
36650
36651 namespace Composer\Repository;
36652
36653
36654
36655
36656
36657
36658 class RepositorySecurityException extends \Exception
36659 {
36660 }
36661 <?php
36662
36663
36664
36665
36666
36667
36668
36669
36670
36671
36672
36673 namespace Composer\Repository\Vcs;
36674
36675 use Composer\Cache;
36676 use Composer\Downloader\TransportException;
36677 use Composer\Json\JsonFile;
36678 use Composer\Util\Bitbucket;
36679
36680 abstract class BitbucketDriver extends VcsDriver
36681 {
36682
36683 protected $cache;
36684 protected $owner;
36685 protected $repository;
36686 protected $hasIssues;
36687 protected $rootIdentifier;
36688 protected $tags;
36689 protected $branches;
36690 protected $infoCache = array();
36691 protected $branchesUrl = '';
36692 protected $tagsUrl = '';
36693 protected $homeUrl = '';
36694 protected $website = '';
36695 protected $cloneHttpsUrl = '';
36696
36697
36698
36699
36700 protected $fallbackDriver;
36701
36702 protected $vcsType;
36703
36704
36705
36706
36707 public function initialize()
36708 {
36709 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#i', $this->url, $match);
36710 $this->owner = $match[1];
36711 $this->repository = $match[2];
36712 $this->originUrl = 'bitbucket.org';
36713 $this->cache = new Cache(
36714 $this->io,
36715 implode('/', array(
36716 $this->config->get('cache-repo-dir'),
36717 $this->originUrl,
36718 $this->owner,
36719 $this->repository,
36720 ))
36721 );
36722 }
36723
36724
36725
36726
36727 public function getUrl()
36728 {
36729 if ($this->fallbackDriver) {
36730 return $this->fallbackDriver->getUrl();
36731 }
36732
36733 return $this->cloneHttpsUrl;
36734 }
36735
36736
36737
36738
36739
36740
36741
36742 protected function getRepoData()
36743 {
36744 $resource = sprintf(
36745 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
36746 $this->owner,
36747 $this->repository,
36748 http_build_query(
36749 array('fields' => '-project,-owner'),
36750 null,
36751 '&'
36752 )
36753 );
36754
36755 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
36756 if ($this->fallbackDriver) {
36757 return false;
36758 }
36759 $this->parseCloneUrls($repoData['links']['clone']);
36760
36761 $this->hasIssues = !empty($repoData['has_issues']);
36762 $this->branchesUrl = $repoData['links']['branches']['href'];
36763 $this->tagsUrl = $repoData['links']['tags']['href'];
36764 $this->homeUrl = $repoData['links']['html']['href'];
36765 $this->website = $repoData['website'];
36766 $this->vcsType = $repoData['scm'];
36767
36768 return true;
36769 }
36770
36771
36772
36773
36774 public function getComposerInformation($identifier)
36775 {
36776 if ($this->fallbackDriver) {
36777 return $this->fallbackDriver->getComposerInformation($identifier);
36778 }
36779
36780 if (!isset($this->infoCache[$identifier])) {
36781 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
36782 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
36783 }
36784
36785 $composer = $this->getBaseComposerInformation($identifier);
36786
36787 if ($composer) {
36788
36789  if (!isset($composer['support']['source'])) {
36790 $label = array_search(
36791 $identifier,
36792 $this->getTags()
36793 ) ?: array_search(
36794 $identifier,
36795 $this->getBranches()
36796 ) ?: $identifier;
36797
36798 if (array_key_exists($label, $tags = $this->getTags())) {
36799 $hash = $tags[$label];
36800 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
36801 $hash = $branches[$label];
36802 }
36803
36804 if (! isset($hash)) {
36805 $composer['support']['source'] = sprintf(
36806 'https://%s/%s/%s/src',
36807 $this->originUrl,
36808 $this->owner,
36809 $this->repository
36810 );
36811 } else {
36812 $composer['support']['source'] = sprintf(
36813 'https://%s/%s/%s/src/%s/?at=%s',
36814 $this->originUrl,
36815 $this->owner,
36816 $this->repository,
36817 $hash,
36818 $label
36819 );
36820 }
36821 }
36822 if (!isset($composer['support']['issues']) && $this->hasIssues) {
36823 $composer['support']['issues'] = sprintf(
36824 'https://%s/%s/%s/issues',
36825 $this->originUrl,
36826 $this->owner,
36827 $this->repository
36828 );
36829 }
36830 if (!isset($composer['homepage'])) {
36831 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
36832 }
36833 }
36834
36835 $this->infoCache[$identifier] = $composer;
36836
36837 if ($this->shouldCache($identifier)) {
36838 $this->cache->write($identifier, json_encode($composer));
36839 }
36840 }
36841
36842 return $this->infoCache[$identifier];
36843 }
36844
36845
36846
36847
36848 public function getFileContent($file, $identifier)
36849 {
36850 if ($this->fallbackDriver) {
36851 return $this->fallbackDriver->getFileContent($file, $identifier);
36852 }
36853
36854 if (strpos($identifier, '/') !== false) {
36855 $branches = $this->getBranches();
36856 if (isset($branches[$identifier])) {
36857 $identifier = $branches[$identifier];
36858 }
36859 }
36860
36861 $resource = sprintf(
36862 'https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s',
36863 $this->owner,
36864 $this->repository,
36865 $identifier,
36866 $file
36867 );
36868
36869 return $this->getContentsWithOAuthCredentials($resource);
36870 }
36871
36872
36873
36874
36875 public function getChangeDate($identifier)
36876 {
36877 if ($this->fallbackDriver) {
36878 return $this->fallbackDriver->getChangeDate($identifier);
36879 }
36880
36881 if (strpos($identifier, '/') !== false) {
36882 $branches = $this->getBranches();
36883 if (isset($branches[$identifier])) {
36884 $identifier = $branches[$identifier];
36885 }
36886 }
36887
36888 $resource = sprintf(
36889 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
36890 $this->owner,
36891 $this->repository,
36892 $identifier
36893 );
36894 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
36895
36896 return new \DateTime($commit['date']);
36897 }
36898
36899
36900
36901
36902 public function getSource($identifier)
36903 {
36904 if ($this->fallbackDriver) {
36905 return $this->fallbackDriver->getSource($identifier);
36906 }
36907
36908 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
36909 }
36910
36911
36912
36913
36914 public function getDist($identifier)
36915 {
36916 if ($this->fallbackDriver) {
36917 return $this->fallbackDriver->getDist($identifier);
36918 }
36919
36920 $url = sprintf(
36921 'https://bitbucket.org/%s/%s/get/%s.zip',
36922 $this->owner,
36923 $this->repository,
36924 $identifier
36925 );
36926
36927 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36928 }
36929
36930
36931
36932
36933 public function getTags()
36934 {
36935 if ($this->fallbackDriver) {
36936 return $this->fallbackDriver->getTags();
36937 }
36938
36939 if (null === $this->tags) {
36940 $this->tags = array();
36941 $resource = sprintf(
36942 '%s?%s',
36943 $this->tagsUrl,
36944 http_build_query(
36945 array(
36946 'pagelen' => 100,
36947 'fields' => 'values.name,values.target.hash,next',
36948 'sort' => '-target.date',
36949 ),
36950 null,
36951 '&'
36952 )
36953 );
36954 $hasNext = true;
36955 while ($hasNext) {
36956 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
36957 foreach ($tagsData['values'] as $data) {
36958 $this->tags[$data['name']] = $data['target']['hash'];
36959 }
36960 if (empty($tagsData['next'])) {
36961 $hasNext = false;
36962 } else {
36963 $resource = $tagsData['next'];
36964 }
36965 }
36966 if ($this->vcsType === 'hg') {
36967 unset($this->tags['tip']);
36968 }
36969 }
36970
36971 return $this->tags;
36972 }
36973
36974
36975
36976
36977 public function getBranches()
36978 {
36979 if ($this->fallbackDriver) {
36980 return $this->fallbackDriver->getBranches();
36981 }
36982
36983 if (null === $this->branches) {
36984 $this->branches = array();
36985 $resource = sprintf(
36986 '%s?%s',
36987 $this->branchesUrl,
36988 http_build_query(
36989 array(
36990 'pagelen' => 100,
36991 'fields' => 'values.name,values.target.hash,values.heads,next',
36992 'sort' => '-target.date',
36993 ),
36994 null,
36995 '&'
36996 )
36997 );
36998 $hasNext = true;
36999 while ($hasNext) {
37000 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
37001 foreach ($branchData['values'] as $data) {
37002
37003  if ($this->vcsType === 'hg' && empty($data['heads'])) {
37004 continue;
37005 }
37006
37007 $this->branches[$data['name']] = $data['target']['hash'];
37008 }
37009 if (empty($branchData['next'])) {
37010 $hasNext = false;
37011 } else {
37012 $resource = $branchData['next'];
37013 }
37014 }
37015 }
37016
37017 return $this->branches;
37018 }
37019
37020
37021
37022
37023
37024
37025
37026
37027
37028 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
37029 {
37030 try {
37031 return parent::getContents($url);
37032 } catch (TransportException $e) {
37033 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
37034
37035 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
37036 if (!$this->io->hasAuthentication($this->originUrl)
37037 && $bitbucketUtil->authorizeOAuth($this->originUrl)
37038 ) {
37039 return parent::getContents($url);
37040 }
37041
37042 if (!$this->io->isInteractive() && $fetchingRepoData) {
37043 return $this->attemptCloneFallback();
37044 }
37045 }
37046
37047 throw $e;
37048 }
37049 }
37050
37051
37052
37053
37054
37055
37056 abstract protected function generateSshUrl();
37057
37058 protected function attemptCloneFallback()
37059 {
37060 try {
37061 $this->setupFallbackDriver($this->generateSshUrl());
37062 } catch (\RuntimeException $e) {
37063 $this->fallbackDriver = null;
37064
37065 $this->io->writeError(
37066 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
37067 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
37068 );
37069 throw $e;
37070 }
37071 }
37072
37073
37074
37075
37076
37077 abstract protected function setupFallbackDriver($url);
37078
37079
37080
37081
37082
37083 protected function parseCloneUrls(array $cloneLinks)
37084 {
37085 foreach ($cloneLinks as $cloneLink) {
37086 if ($cloneLink['name'] === 'https') {
37087
37088  
37089  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
37090 }
37091 }
37092 }
37093
37094
37095
37096
37097 protected function getMainBranchData()
37098 {
37099 $resource = sprintf(
37100 'https://api.bitbucket.org/2.0/repositories/%s/%s?fields=mainbranch',
37101 $this->owner,
37102 $this->repository
37103 );
37104
37105 $data = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
37106 if (isset($data['mainbranch'])) {
37107 return $data['mainbranch'];
37108 }
37109
37110 return null;
37111 }
37112 }
37113 <?php
37114
37115
37116
37117
37118
37119
37120
37121
37122
37123
37124
37125 namespace Composer\Repository\Vcs;
37126
37127 use Composer\Cache;
37128 use Composer\Config;
37129 use Composer\Util\ProcessExecutor;
37130 use Composer\Util\Filesystem;
37131 use Composer\IO\IOInterface;
37132
37133
37134
37135
37136 class FossilDriver extends VcsDriver
37137 {
37138 protected $tags;
37139 protected $branches;
37140 protected $rootIdentifier;
37141 protected $repoFile;
37142 protected $checkoutDir;
37143 protected $infoCache = array();
37144
37145
37146
37147
37148 public function initialize()
37149 {
37150
37151  $this->checkFossil();
37152
37153
37154  $this->config->prohibitUrlByConfig($this->url, $this->io);
37155
37156
37157  
37158  if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
37159 $this->checkoutDir = $this->url;
37160 } else {
37161 if (!Cache::isUsable($this->config->get('cache-repo-dir')) || !Cache::isUsable($this->config->get('cache-vcs-dir'))) {
37162 throw new \RuntimeException('FossilDriver requires a usable cache directory, and it looks like you set it to be disabled');
37163 }
37164
37165 $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url);
37166 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
37167 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
37168
37169 $this->updateLocalRepo();
37170 }
37171
37172 $this->getTags();
37173 $this->getBranches();
37174 }
37175
37176
37177
37178
37179 protected function checkFossil()
37180 {
37181 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
37182 throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
37183 }
37184 }
37185
37186
37187
37188
37189 protected function updateLocalRepo()
37190 {
37191 $fs = new Filesystem();
37192 $fs->ensureDirectoryExists($this->checkoutDir);
37193
37194 if (!is_writable(dirname($this->checkoutDir))) {
37195 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
37196 }
37197
37198
37199  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
37200 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
37201 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
37202 }
37203 } else {
37204
37205  $fs->removeDirectory($this->checkoutDir);
37206 $fs->remove($this->repoFile);
37207
37208 $fs->ensureDirectoryExists($this->checkoutDir);
37209
37210 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
37211 $output = $this->process->getErrorOutput();
37212
37213 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
37214 }
37215
37216 if (0 !== $this->process->execute(sprintf('fossil open %s --nested', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
37217 $output = $this->process->getErrorOutput();
37218
37219 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
37220 }
37221 }
37222 }
37223
37224
37225
37226
37227 public function getRootIdentifier()
37228 {
37229 if (null === $this->rootIdentifier) {
37230 $this->rootIdentifier = 'trunk';
37231 }
37232
37233 return $this->rootIdentifier;
37234 }
37235
37236
37237
37238
37239 public function getUrl()
37240 {
37241 return $this->url;
37242 }
37243
37244
37245
37246
37247 public function getSource($identifier)
37248 {
37249 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
37250 }
37251
37252
37253
37254
37255 public function getDist($identifier)
37256 {
37257 return null;
37258 }
37259
37260
37261
37262
37263 public function getFileContent($file, $identifier)
37264 {
37265 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37266 $this->process->execute($command, $content, $this->checkoutDir);
37267
37268 if (!trim($content)) {
37269 return null;
37270 }
37271
37272 return $content;
37273 }
37274
37275
37276
37277
37278 public function getChangeDate($identifier)
37279 {
37280 $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir);
37281 list($ckout, $date, $message) = explode(' ', trim($output), 3);
37282
37283 return new \DateTime($date, new \DateTimeZone('UTC'));
37284 }
37285
37286
37287
37288
37289 public function getTags()
37290 {
37291 if (null === $this->tags) {
37292 $tags = array();
37293
37294 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
37295 foreach ($this->process->splitLines($output) as $tag) {
37296 $tags[$tag] = $tag;
37297 }
37298
37299 $this->tags = $tags;
37300 }
37301
37302 return $this->tags;
37303 }
37304
37305
37306
37307
37308 public function getBranches()
37309 {
37310 if (null === $this->branches) {
37311 $branches = array();
37312 $bookmarks = array();
37313
37314 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
37315 foreach ($this->process->splitLines($output) as $branch) {
37316 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
37317 $branches[$branch] = $branch;
37318 }
37319
37320 $this->branches = $branches;
37321 }
37322
37323 return $this->branches;
37324 }
37325
37326
37327
37328
37329 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37330 {
37331 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
37332 return true;
37333 }
37334
37335 if (preg_match('!/fossil/|\.fossil!', $url)) {
37336 return true;
37337 }
37338
37339
37340  if (Filesystem::isLocalPath($url)) {
37341 $url = Filesystem::getPlatformPath($url);
37342 if (!is_dir($url)) {
37343 return false;
37344 }
37345
37346 $process = new ProcessExecutor($io);
37347
37348  if ($process->execute('fossil info', $output, $url) === 0) {
37349 return true;
37350 }
37351 }
37352
37353 return false;
37354 }
37355 }
37356 <?php
37357
37358
37359
37360
37361
37362
37363
37364
37365
37366
37367
37368 namespace Composer\Repository\Vcs;
37369
37370 use Composer\Config;
37371 use Composer\IO\IOInterface;
37372
37373
37374
37375
37376 class GitBitbucketDriver extends BitbucketDriver
37377 {
37378
37379
37380
37381 public function getRootIdentifier()
37382 {
37383 if ($this->fallbackDriver) {
37384 return $this->fallbackDriver->getRootIdentifier();
37385 }
37386
37387 if (null === $this->rootIdentifier) {
37388 if (! $this->getRepoData()) {
37389 return $this->fallbackDriver->getRootIdentifier();
37390 }
37391
37392 if ($this->vcsType !== 'git') {
37393 throw new \RuntimeException(
37394 $this->url.' does not appear to be a git repository, use '.
37395 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
37396 );
37397 }
37398
37399 $mainBranchData = $this->getMainBranchData();
37400 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
37401 }
37402
37403 return $this->rootIdentifier;
37404 }
37405
37406
37407
37408
37409 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37410 {
37411 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#i', $url)) {
37412 return false;
37413 }
37414
37415 if (!extension_loaded('openssl')) {
37416 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37417
37418 return false;
37419 }
37420
37421 return true;
37422 }
37423
37424
37425
37426
37427 protected function setupFallbackDriver($url)
37428 {
37429 $this->fallbackDriver = new GitDriver(
37430 array('url' => $url),
37431 $this->io,
37432 $this->config,
37433 $this->process,
37434 $this->remoteFilesystem
37435 );
37436 $this->fallbackDriver->initialize();
37437 }
37438
37439
37440
37441
37442 protected function generateSshUrl()
37443 {
37444 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
37445 }
37446 }
37447 <?php
37448
37449
37450
37451
37452
37453
37454
37455
37456
37457
37458
37459 namespace Composer\Repository\Vcs;
37460
37461 use Composer\Util\ProcessExecutor;
37462 use Composer\Util\Filesystem;
37463 use Composer\Util\Git as GitUtil;
37464 use Composer\IO\IOInterface;
37465 use Composer\Cache;
37466 use Composer\Config;
37467
37468
37469
37470
37471 class GitDriver extends VcsDriver
37472 {
37473 protected $cache;
37474 protected $tags;
37475 protected $branches;
37476 protected $rootIdentifier;
37477 protected $repoDir;
37478 protected $infoCache = array();
37479
37480
37481
37482
37483 public function initialize()
37484 {
37485 if (Filesystem::isLocalPath($this->url)) {
37486 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
37487 $this->repoDir = $this->url;
37488 $cacheUrl = realpath($this->url);
37489 } else {
37490 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
37491 throw new \RuntimeException('GitDriver requires a usable cache directory, and it looks like you set it to be disabled');
37492 }
37493
37494 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
37495
37496 GitUtil::cleanEnv();
37497
37498 $fs = new Filesystem();
37499 $fs->ensureDirectoryExists(dirname($this->repoDir));
37500
37501 if (!is_writable(dirname($this->repoDir))) {
37502 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
37503 }
37504
37505 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
37506 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.');
37507 }
37508
37509 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
37510 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
37511 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
37512 }
37513
37514 $cacheUrl = $this->url;
37515 }
37516
37517 $this->getTags();
37518 $this->getBranches();
37519
37520 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
37521 }
37522
37523
37524
37525
37526 public function getRootIdentifier()
37527 {
37528 if (null === $this->rootIdentifier) {
37529 $this->rootIdentifier = 'master';
37530
37531
37532  $this->process->execute('git branch --no-color', $output, $this->repoDir);
37533 $branches = $this->process->splitLines($output);
37534 if (!in_array('* master', $branches)) {
37535 foreach ($branches as $branch) {
37536 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
37537 $this->rootIdentifier = $match[1];
37538 break;
37539 }
37540 }
37541 }
37542 }
37543
37544 return $this->rootIdentifier;
37545 }
37546
37547
37548
37549
37550 public function getUrl()
37551 {
37552 return $this->url;
37553 }
37554
37555
37556
37557
37558 public function getSource($identifier)
37559 {
37560 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
37561 }
37562
37563
37564
37565
37566 public function getDist($identifier)
37567 {
37568 return null;
37569 }
37570
37571
37572
37573
37574 public function getFileContent($file, $identifier)
37575 {
37576 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37577 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
37578
37579 if (!trim($content)) {
37580 return null;
37581 }
37582
37583 return $content;
37584 }
37585
37586
37587
37588
37589 public function getChangeDate($identifier)
37590 {
37591 $this->process->execute(sprintf(
37592 'git log -1 --format=%%at %s',
37593 ProcessExecutor::escape($identifier)
37594 ), $output, $this->repoDir);
37595
37596 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
37597 }
37598
37599
37600
37601
37602 public function getTags()
37603 {
37604 if (null === $this->tags) {
37605 $this->tags = array();
37606
37607 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
37608 foreach ($output = $this->process->splitLines($output) as $tag) {
37609 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
37610 $this->tags[$match[2]] = $match[1];
37611 }
37612 }
37613 }
37614
37615 return $this->tags;
37616 }
37617
37618
37619
37620
37621 public function getBranches()
37622 {
37623 if (null === $this->branches) {
37624 $branches = array();
37625
37626 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
37627 foreach ($this->process->splitLines($output) as $branch) {
37628 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
37629 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
37630 $branches[$match[1]] = $match[2];
37631 }
37632 }
37633 }
37634
37635 $this->branches = $branches;
37636 }
37637
37638 return $this->branches;
37639 }
37640
37641
37642
37643
37644 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37645 {
37646 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
37647 return true;
37648 }
37649
37650
37651  if (Filesystem::isLocalPath($url)) {
37652 $url = Filesystem::getPlatformPath($url);
37653 if (!is_dir($url)) {
37654 return false;
37655 }
37656
37657 $process = new ProcessExecutor($io);
37658
37659  if ($process->execute('git tag', $output, $url) === 0) {
37660 return true;
37661 }
37662 }
37663
37664 if (!$deep) {
37665 return false;
37666 }
37667
37668 $process = new ProcessExecutor($io);
37669
37670 return $process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0;
37671 }
37672 }
37673 <?php
37674
37675
37676
37677
37678
37679
37680
37681
37682
37683
37684
37685 namespace Composer\Repository\Vcs;
37686
37687 use Composer\Config;
37688 use Composer\Downloader\TransportException;
37689 use Composer\Json\JsonFile;
37690 use Composer\Cache;
37691 use Composer\IO\IOInterface;
37692 use Composer\Util\GitHub;
37693
37694
37695
37696
37697 class GitHubDriver extends VcsDriver
37698 {
37699 protected $cache;
37700 protected $owner;
37701 protected $repository;
37702 protected $tags;
37703 protected $branches;
37704 protected $rootIdentifier;
37705 protected $repoData;
37706 protected $hasIssues;
37707 protected $infoCache = array();
37708 protected $isPrivate = false;
37709
37710
37711
37712
37713
37714
37715 protected $gitDriver;
37716
37717
37718
37719
37720 public function initialize()
37721 {
37722 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
37723 $this->owner = $match[3];
37724 $this->repository = $match[4];
37725 $this->originUrl = strtolower(!empty($match[1]) ? $match[1] : $match[2]);
37726 if ($this->originUrl === 'www.github.com') {
37727 $this->originUrl = 'github.com';
37728 }
37729 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
37730
37731 if ( $this->config->get('use-github-api') === false || (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api'] ) ){
37732 $this->setupGitDriver($this->url);
37733
37734 return;
37735 }
37736
37737 $this->fetchRootIdentifier();
37738 }
37739
37740 public function getRepositoryUrl()
37741 {
37742 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
37743 }
37744
37745
37746
37747
37748 public function getRootIdentifier()
37749 {
37750 if ($this->gitDriver) {
37751 return $this->gitDriver->getRootIdentifier();
37752 }
37753
37754 return $this->rootIdentifier;
37755 }
37756
37757
37758
37759
37760 public function getUrl()
37761 {
37762 if ($this->gitDriver) {
37763 return $this->gitDriver->getUrl();
37764 }
37765
37766 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
37767 }
37768
37769
37770
37771
37772 protected function getApiUrl()
37773 {
37774 if ('github.com' === $this->originUrl) {
37775 $apiUrl = 'api.github.com';
37776 } else {
37777 $apiUrl = $this->originUrl . '/api/v3';
37778 }
37779
37780 return 'https://' . $apiUrl;
37781 }
37782
37783
37784
37785
37786 public function getSource($identifier)
37787 {
37788 if ($this->gitDriver) {
37789 return $this->gitDriver->getSource($identifier);
37790 }
37791 if ($this->isPrivate) {
37792
37793  
37794  $url = $this->generateSshUrl();
37795 } else {
37796 $url = $this->getUrl();
37797 }
37798
37799 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
37800 }
37801
37802
37803
37804
37805 public function getDist($identifier)
37806 {
37807 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
37808
37809 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
37810 }
37811
37812
37813
37814
37815 public function getComposerInformation($identifier)
37816 {
37817 if ($this->gitDriver) {
37818 return $this->gitDriver->getComposerInformation($identifier);
37819 }
37820
37821 if (!isset($this->infoCache[$identifier])) {
37822 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
37823 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37824 }
37825
37826 $composer = $this->getBaseComposerInformation($identifier);
37827
37828 if ($composer) {
37829
37830  if (!isset($composer['support']['source'])) {
37831 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
37832 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
37833 }
37834 if (!isset($composer['support']['issues']) && $this->hasIssues) {
37835 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
37836 }
37837 }
37838
37839 if ($this->shouldCache($identifier)) {
37840 $this->cache->write($identifier, json_encode($composer));
37841 }
37842
37843 $this->infoCache[$identifier] = $composer;
37844 }
37845
37846 return $this->infoCache[$identifier];
37847 }
37848
37849
37850
37851
37852 public function getFileContent($file, $identifier)
37853 {
37854 if ($this->gitDriver) {
37855 return $this->gitDriver->getFileContent($file, $identifier);
37856 }
37857
37858 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
37859 $resource = JsonFile::parseJson($this->getContents($resource));
37860 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
37861 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
37862 }
37863
37864 return $content;
37865 }
37866
37867
37868
37869
37870 public function getChangeDate($identifier)
37871 {
37872 if ($this->gitDriver) {
37873 return $this->gitDriver->getChangeDate($identifier);
37874 }
37875
37876 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
37877 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
37878
37879 return new \DateTime($commit['commit']['committer']['date']);
37880 }
37881
37882
37883
37884
37885 public function getTags()
37886 {
37887 if ($this->gitDriver) {
37888 return $this->gitDriver->getTags();
37889 }
37890 if (null === $this->tags) {
37891 $this->tags = array();
37892 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
37893
37894 do {
37895 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
37896 foreach ($tagsData as $tag) {
37897 $this->tags[$tag['name']] = $tag['commit']['sha'];
37898 }
37899
37900 $resource = $this->getNextPage();
37901 } while ($resource);
37902 }
37903
37904 return $this->tags;
37905 }
37906
37907
37908
37909
37910 public function getBranches()
37911 {
37912 if ($this->gitDriver) {
37913 return $this->gitDriver->getBranches();
37914 }
37915 if (null === $this->branches) {
37916 $this->branches = array();
37917 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
37918
37919 $branchBlacklist = array('gh-pages');
37920
37921 do {
37922 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
37923 foreach ($branchData as $branch) {
37924 $name = substr($branch['ref'], 11);
37925 if (!in_array($name, $branchBlacklist)) {
37926 $this->branches[$name] = $branch['object']['sha'];
37927 }
37928 }
37929
37930 $resource = $this->getNextPage();
37931 } while ($resource);
37932 }
37933
37934 return $this->branches;
37935 }
37936
37937
37938
37939
37940 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37941 {
37942 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
37943 return false;
37944 }
37945
37946 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
37947 if (!in_array(strtolower(preg_replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) {
37948 return false;
37949 }
37950
37951 if (!extension_loaded('openssl')) {
37952 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
37953
37954 return false;
37955 }
37956
37957 return true;
37958 }
37959
37960
37961
37962
37963
37964
37965 public function getRepoData()
37966 {
37967 $this->fetchRootIdentifier();
37968
37969 return $this->repoData;
37970 }
37971
37972
37973
37974
37975
37976
37977 protected function generateSshUrl()
37978 {
37979 if (false !== strpos($this->originUrl, ':')) {
37980 return 'ssh://git@' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
37981 }
37982
37983 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
37984 }
37985
37986
37987
37988
37989 protected function getContents($url, $fetchingRepoData = false)
37990 {
37991 try {
37992 return parent::getContents($url);
37993 } catch (TransportException $e) {
37994 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
37995
37996 switch ($e->getCode()) {
37997 case 401:
37998 case 404:
37999
38000  if (!$fetchingRepoData) {
38001 throw $e;
38002 }
38003
38004 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
38005 return parent::getContents($url);
38006 }
38007
38008 if (!$this->io->isInteractive()) {
38009 return $this->attemptCloneFallback();
38010 }
38011
38012 $scopesIssued = array();
38013 $scopesNeeded = array();
38014 if ($headers = $e->getHeaders()) {
38015 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
38016 $scopesIssued = explode(' ', $scopes);
38017 }
38018 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
38019 $scopesNeeded = explode(' ', $scopes);
38020 }
38021 }
38022 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
38023
38024  
38025  if (!$headers || !count($scopesNeeded) || count($scopesFailed)) {
38026 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
38027 }
38028
38029 return parent::getContents($url);
38030
38031 case 403:
38032 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
38033 return parent::getContents($url);
38034 }
38035
38036 if (!$this->io->isInteractive() && $fetchingRepoData) {
38037 return $this->attemptCloneFallback();
38038 }
38039
38040 $rateLimited = $gitHubUtil->isRateLimited($e->getHeaders());
38041
38042 if (!$this->io->hasAuthentication($this->originUrl)) {
38043 if (!$this->io->isInteractive()) {
38044 $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>');
38045 throw $e;
38046 }
38047
38048 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
38049
38050 return parent::getContents($url);
38051 }
38052
38053 if ($rateLimited) {
38054 $rateLimit = $gitHubUtil->getRateLimit($e->getHeaders());
38055 $this->io->writeError(sprintf(
38056 '<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>',
38057 $rateLimit['limit'],
38058 $rateLimit['reset']
38059 ));
38060 }
38061
38062 throw $e;
38063
38064 default:
38065 throw $e;
38066 }
38067 }
38068 }
38069
38070
38071
38072
38073
38074
38075 protected function fetchRootIdentifier()
38076 {
38077 if ($this->repoData) {
38078 return;
38079 }
38080
38081 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
38082
38083 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
38084 if (null === $this->repoData && null !== $this->gitDriver) {
38085 return;
38086 }
38087
38088 $this->owner = $this->repoData['owner']['login'];
38089 $this->repository = $this->repoData['name'];
38090
38091 $this->isPrivate = !empty($this->repoData['private']);
38092 if (isset($this->repoData['default_branch'])) {
38093 $this->rootIdentifier = $this->repoData['default_branch'];
38094 } elseif (isset($this->repoData['master_branch'])) {
38095 $this->rootIdentifier = $this->repoData['master_branch'];
38096 } else {
38097 $this->rootIdentifier = 'master';
38098 }
38099 $this->hasIssues = !empty($this->repoData['has_issues']);
38100 }
38101
38102 protected function attemptCloneFallback()
38103 {
38104 $this->isPrivate = true;
38105
38106 try {
38107
38108  
38109  
38110  
38111  $this->setupGitDriver($this->generateSshUrl());
38112
38113 return;
38114 } catch (\RuntimeException $e) {
38115 $this->gitDriver = null;
38116
38117 $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>');
38118 throw $e;
38119 }
38120 }
38121
38122 protected function setupGitDriver($url)
38123 {
38124 $this->gitDriver = new GitDriver(
38125 array('url' => $url),
38126 $this->io,
38127 $this->config,
38128 $this->process,
38129 $this->remoteFilesystem
38130 );
38131 $this->gitDriver->initialize();
38132 }
38133
38134 protected function getNextPage()
38135 {
38136 $headers = $this->remoteFilesystem->getLastHeaders();
38137 foreach ($headers as $header) {
38138 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
38139 $links = explode(',', $match[1]);
38140 foreach ($links as $link) {
38141 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
38142 return $match[1];
38143 }
38144 }
38145 }
38146 }
38147 }
38148 }
38149 <?php
38150
38151
38152
38153
38154
38155
38156
38157
38158
38159
38160
38161 namespace Composer\Repository\Vcs;
38162
38163 use Composer\Config;
38164 use Composer\Cache;
38165 use Composer\IO\IOInterface;
38166 use Composer\Json\JsonFile;
38167 use Composer\Downloader\TransportException;
38168 use Composer\Util\RemoteFilesystem;
38169 use Composer\Util\GitLab;
38170
38171
38172
38173
38174
38175
38176
38177 class GitLabDriver extends VcsDriver
38178 {
38179 private $scheme;
38180 private $namespace;
38181 private $repository;
38182
38183
38184
38185
38186 private $project;
38187
38188
38189
38190
38191 private $commits = array();
38192
38193
38194
38195
38196 private $tags;
38197
38198
38199
38200
38201 private $branches;
38202
38203
38204
38205
38206
38207
38208 protected $gitDriver;
38209
38210
38211
38212
38213
38214
38215 private $isPrivate = true;
38216
38217
38218
38219
38220 private $hasNonstandardOrigin = false;
38221
38222 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
38223
38224
38225
38226
38227
38228
38229
38230
38231 public function initialize()
38232 {
38233 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
38234 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
38235 }
38236
38237 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
38238 $configuredDomains = $this->config->get('gitlab-domains');
38239 $urlParts = explode('/', $match['parts']);
38240
38241 $this->scheme = !empty($match['scheme'])
38242 ? $match['scheme']
38243 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
38244 ;
38245 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts, $match['port']);
38246
38247 if (false !== strpos($this->originUrl, ':') || false !== strpos($this->originUrl, '/')) {
38248 $this->hasNonstandardOrigin = true;
38249 }
38250
38251 $this->namespace = implode('/', $urlParts);
38252 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
38253
38254 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
38255
38256 $this->fetchProject();
38257 }
38258
38259
38260
38261
38262
38263
38264
38265 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
38266 {
38267 $this->remoteFilesystem = $remoteFilesystem;
38268 }
38269
38270
38271
38272
38273 public function getFileContent($file, $identifier)
38274 {
38275 if ($this->gitDriver) {
38276 return $this->gitDriver->getFileContent($file, $identifier);
38277 }
38278
38279
38280  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
38281 $branches = $this->getBranches();
38282 if (isset($branches[$identifier])) {
38283 $identifier = $branches[$identifier];
38284 }
38285 }
38286
38287 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
38288
38289 try {
38290 $content = $this->getContents($resource);
38291 } catch (TransportException $e) {
38292 if ($e->getCode() !== 404) {
38293 throw $e;
38294 }
38295
38296 return null;
38297 }
38298
38299 return $content;
38300 }
38301
38302
38303
38304
38305 public function getChangeDate($identifier)
38306 {
38307 if ($this->gitDriver) {
38308 return $this->gitDriver->getChangeDate($identifier);
38309 }
38310
38311 if (isset($this->commits[$identifier])) {
38312 return new \DateTime($this->commits[$identifier]['committed_date']);
38313 }
38314
38315 return new \DateTime();
38316 }
38317
38318
38319
38320
38321 public function getRepositoryUrl()
38322 {
38323 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
38324 }
38325
38326
38327
38328
38329 public function getUrl()
38330 {
38331 if ($this->gitDriver) {
38332 return $this->gitDriver->getUrl();
38333 }
38334
38335 return $this->project['web_url'];
38336 }
38337
38338
38339
38340
38341 public function getDist($identifier)
38342 {
38343 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
38344
38345 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
38346 }
38347
38348
38349
38350
38351 public function getSource($identifier)
38352 {
38353 if ($this->gitDriver) {
38354 return $this->gitDriver->getSource($identifier);
38355 }
38356
38357 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
38358 }
38359
38360
38361
38362
38363 public function getRootIdentifier()
38364 {
38365 if ($this->gitDriver) {
38366 return $this->gitDriver->getRootIdentifier();
38367 }
38368
38369 return $this->project['default_branch'];
38370 }
38371
38372
38373
38374
38375 public function getBranches()
38376 {
38377 if ($this->gitDriver) {
38378 return $this->gitDriver->getBranches();
38379 }
38380
38381 if (!$this->branches) {
38382 $this->branches = $this->getReferences('branches');
38383 }
38384
38385 return $this->branches;
38386 }
38387
38388
38389
38390
38391 public function getTags()
38392 {
38393 if ($this->gitDriver) {
38394 return $this->gitDriver->getTags();
38395 }
38396
38397 if (!$this->tags) {
38398 $this->tags = $this->getReferences('tags');
38399 }
38400
38401 return $this->tags;
38402 }
38403
38404
38405
38406
38407 public function getApiUrl()
38408 {
38409 return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
38410 }
38411
38412
38413
38414
38415
38416
38417
38418 private function urlEncodeAll($string)
38419 {
38420 $encoded = '';
38421 for ($i = 0; isset($string[$i]); $i++) {
38422 $character = $string[$i];
38423 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
38424 $character = '%' . sprintf('%02X', ord($character));
38425 }
38426 $encoded .= $character;
38427 }
38428
38429 return $encoded;
38430 }
38431
38432
38433
38434
38435
38436
38437 protected function getReferences($type)
38438 {
38439 $perPage = 100;
38440 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
38441
38442 $references = array();
38443 do {
38444 $data = JsonFile::parseJson($this->getContents($resource), $resource);
38445
38446 foreach ($data as $datum) {
38447 $references[$datum['name']] = $datum['commit']['id'];
38448
38449
38450  
38451  $this->commits[$datum['commit']['id']] = $datum['commit'];
38452 }
38453
38454 if (count($data) >= $perPage) {
38455 $resource = $this->getNextPage();
38456 } else {
38457 $resource = false;
38458 }
38459 } while ($resource);
38460
38461 return $references;
38462 }
38463
38464 protected function fetchProject()
38465 {
38466
38467  $resource = $this->getApiUrl();
38468 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
38469 if (isset($this->project['visibility'])) {
38470 $this->isPrivate = $this->project['visibility'] !== 'public';
38471 } else {
38472
38473  $this->isPrivate = false;
38474 }
38475 }
38476
38477 protected function attemptCloneFallback()
38478 {
38479 try {
38480 if ($this->isPrivate === false) {
38481 $url = $this->generatePublicUrl();
38482 } else {
38483 $url = $this->generateSshUrl();
38484 }
38485
38486
38487  
38488  
38489  $this->setupGitDriver($url);
38490
38491 return;
38492 } catch (\RuntimeException $e) {
38493 $this->gitDriver = null;
38494
38495 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
38496 throw $e;
38497 }
38498 }
38499
38500
38501
38502
38503
38504
38505 protected function generateSshUrl()
38506 {
38507 if ($this->hasNonstandardOrigin) {
38508 return 'ssh://git@'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository.'.git';
38509 }
38510
38511 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
38512 }
38513
38514 protected function generatePublicUrl()
38515 {
38516 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
38517 }
38518
38519 protected function setupGitDriver($url)
38520 {
38521 $this->gitDriver = new GitDriver(
38522 array('url' => $url),
38523 $this->io,
38524 $this->config,
38525 $this->process,
38526 $this->remoteFilesystem
38527 );
38528 $this->gitDriver->initialize();
38529 }
38530
38531
38532
38533
38534 protected function getContents($url, $fetchingRepoData = false)
38535 {
38536 try {
38537 $res = parent::getContents($url);
38538
38539 if ($fetchingRepoData) {
38540 $json = JsonFile::parseJson($res, $url);
38541
38542
38543  if (!isset($json['default_branch'])) {
38544 if (!empty($json['id'])) {
38545 $this->isPrivate = false;
38546 }
38547
38548 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
38549 }
38550 }
38551
38552 return $res;
38553 } catch (TransportException $e) {
38554 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
38555
38556 switch ($e->getCode()) {
38557 case 401:
38558 case 404:
38559
38560  if (!$fetchingRepoData) {
38561 throw $e;
38562 }
38563
38564 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
38565 return parent::getContents($url);
38566 }
38567
38568 if (!$this->io->isInteractive()) {
38569 return $this->attemptCloneFallback();
38570 }
38571 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
38572 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
38573
38574 return parent::getContents($url);
38575
38576 case 403:
38577 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
38578 return parent::getContents($url);
38579 }
38580
38581 if (!$this->io->isInteractive() && $fetchingRepoData) {
38582 return $this->attemptCloneFallback();
38583 }
38584
38585 throw $e;
38586
38587 default:
38588 throw $e;
38589 }
38590 }
38591 }
38592
38593
38594
38595
38596
38597
38598
38599 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38600 {
38601 if (!preg_match(self::URL_REGEX, $url, $match)) {
38602 return false;
38603 }
38604
38605 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
38606 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
38607 $urlParts = explode('/', $match['parts']);
38608
38609 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts, $match['port'])) {
38610 return false;
38611 }
38612
38613 if ('https' === $scheme && !extension_loaded('openssl')) {
38614 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
38615
38616 return false;
38617 }
38618
38619 return true;
38620 }
38621
38622 private function getNextPage()
38623 {
38624 $headers = $this->remoteFilesystem->getLastHeaders();
38625 foreach ($headers as $header) {
38626 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
38627 $links = explode(',', $match[1]);
38628 foreach ($links as $link) {
38629 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
38630 return $match[1];
38631 }
38632 }
38633 }
38634 }
38635 }
38636
38637
38638
38639
38640
38641
38642
38643 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts, $portNumber)
38644 {
38645 $guessedDomain = strtolower($guessedDomain);
38646
38647 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array($guessedDomain.':'.$portNumber, $configuredDomains))) {
38648 if ($portNumber) {
38649 return $guessedDomain.':'.$portNumber;
38650 }
38651 return $guessedDomain;
38652 }
38653
38654 if ($portNumber) {
38655 $guessedDomain .= ':'.$portNumber;
38656 }
38657
38658 while (null !== ($part = array_shift($urlParts))) {
38659 $guessedDomain .= '/' . $part;
38660
38661 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array(preg_replace('{:\d+}', '', $guessedDomain), $configuredDomains))) {
38662 return $guessedDomain;
38663 }
38664 }
38665
38666 return false;
38667 }
38668 }
38669 <?php
38670
38671
38672
38673
38674
38675
38676
38677
38678
38679
38680
38681 namespace Composer\Repository\Vcs;
38682
38683 use Composer\Config;
38684 use Composer\IO\IOInterface;
38685
38686
38687
38688
38689 class HgBitbucketDriver extends BitbucketDriver
38690 {
38691
38692
38693
38694 public function getRootIdentifier()
38695 {
38696 if ($this->fallbackDriver) {
38697 return $this->fallbackDriver->getRootIdentifier();
38698 }
38699
38700 if (null === $this->rootIdentifier) {
38701 if (! $this->getRepoData()) {
38702 return $this->fallbackDriver->getRootIdentifier();
38703 }
38704
38705 if ($this->vcsType !== 'hg') {
38706 throw new \RuntimeException(
38707 $this->url.' does not appear to be a mercurial repository, use '.
38708 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
38709 );
38710 }
38711
38712 $mainBranchData = $this->getMainBranchData();
38713 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
38714 }
38715
38716 return $this->rootIdentifier;
38717 }
38718
38719
38720
38721
38722 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38723 {
38724 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#i', $url)) {
38725 return false;
38726 }
38727
38728 if (!extension_loaded('openssl')) {
38729 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
38730
38731 return false;
38732 }
38733
38734 return true;
38735 }
38736
38737
38738
38739
38740 protected function setupFallbackDriver($url)
38741 {
38742 $this->fallbackDriver = new HgDriver(
38743 array('url' => $url),
38744 $this->io,
38745 $this->config,
38746 $this->process,
38747 $this->remoteFilesystem
38748 );
38749 $this->fallbackDriver->initialize();
38750 }
38751
38752
38753
38754
38755 protected function generateSshUrl()
38756 {
38757 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
38758 }
38759 }
38760 <?php
38761
38762
38763
38764
38765
38766
38767
38768
38769
38770
38771
38772 namespace Composer\Repository\Vcs;
38773
38774 use Composer\Config;
38775 use Composer\Cache;
38776 use Composer\Util\Hg as HgUtils;
38777 use Composer\Util\ProcessExecutor;
38778 use Composer\Util\Filesystem;
38779 use Composer\IO\IOInterface;
38780
38781
38782
38783
38784 class HgDriver extends VcsDriver
38785 {
38786 protected $tags;
38787 protected $branches;
38788 protected $rootIdentifier;
38789 protected $repoDir;
38790 protected $infoCache = array();
38791
38792
38793
38794
38795 public function initialize()
38796 {
38797 if (Filesystem::isLocalPath($this->url)) {
38798 $this->repoDir = $this->url;
38799 } else {
38800 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
38801 throw new \RuntimeException('HgDriver requires a usable cache directory, and it looks like you set it to be disabled');
38802 }
38803
38804 $cacheDir = $this->config->get('cache-vcs-dir');
38805 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
38806
38807 $fs = new Filesystem();
38808 $fs->ensureDirectoryExists($cacheDir);
38809
38810 if (!is_writable(dirname($this->repoDir))) {
38811 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
38812 }
38813
38814
38815  $this->config->prohibitUrlByConfig($this->url, $this->io);
38816
38817 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
38818
38819
38820  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
38821 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
38822 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
38823 }
38824 } else {
38825
38826  $fs->removeDirectory($this->repoDir);
38827
38828 $repoDir = $this->repoDir;
38829 $command = function ($url) use ($repoDir) {
38830 return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
38831 };
38832
38833 $hgUtils->runCommand($command, $this->url, null);
38834 }
38835 }
38836
38837 $this->getTags();
38838 $this->getBranches();
38839 }
38840
38841
38842
38843
38844 public function getRootIdentifier()
38845 {
38846 if (null === $this->rootIdentifier) {
38847 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
38848 $output = $this->process->splitLines($output);
38849 $this->rootIdentifier = $output[0];
38850 }
38851
38852 return $this->rootIdentifier;
38853 }
38854
38855
38856
38857
38858 public function getUrl()
38859 {
38860 return $this->url;
38861 }
38862
38863
38864
38865
38866 public function getSource($identifier)
38867 {
38868 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
38869 }
38870
38871
38872
38873
38874 public function getDist($identifier)
38875 {
38876 return null;
38877 }
38878
38879
38880
38881
38882 public function getFileContent($file, $identifier)
38883 {
38884 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
38885 $this->process->execute($resource, $content, $this->repoDir);
38886
38887 if (!trim($content)) {
38888 return;
38889 }
38890
38891 return $content;
38892 }
38893
38894
38895
38896
38897 public function getChangeDate($identifier)
38898 {
38899 $this->process->execute(
38900 sprintf(
38901 'hg log --template "{date|rfc3339date}" -r %s',
38902 ProcessExecutor::escape($identifier)
38903 ),
38904 $output,
38905 $this->repoDir
38906 );
38907
38908 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
38909 }
38910
38911
38912
38913
38914 public function getTags()
38915 {
38916 if (null === $this->tags) {
38917 $tags = array();
38918
38919 $this->process->execute('hg tags', $output, $this->repoDir);
38920 foreach ($this->process->splitLines($output) as $tag) {
38921 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
38922 $tags[$match[1]] = $match[2];
38923 }
38924 }
38925 unset($tags['tip']);
38926
38927 $this->tags = $tags;
38928 }
38929
38930 return $this->tags;
38931 }
38932
38933
38934
38935
38936 public function getBranches()
38937 {
38938 if (null === $this->branches) {
38939 $branches = array();
38940 $bookmarks = array();
38941
38942 $this->process->execute('hg branches', $output, $this->repoDir);
38943 foreach ($this->process->splitLines($output) as $branch) {
38944 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
38945 $branches[$match[1]] = $match[2];
38946 }
38947 }
38948
38949 $this->process->execute('hg bookmarks', $output, $this->repoDir);
38950 foreach ($this->process->splitLines($output) as $branch) {
38951 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
38952 $bookmarks[$match[1]] = $match[2];
38953 }
38954 }
38955
38956
38957  $this->branches = array_merge($bookmarks, $branches);
38958 }
38959
38960 return $this->branches;
38961 }
38962
38963
38964
38965
38966 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38967 {
38968 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
38969 return true;
38970 }
38971
38972
38973  if (Filesystem::isLocalPath($url)) {
38974 $url = Filesystem::getPlatformPath($url);
38975 if (!is_dir($url)) {
38976 return false;
38977 }
38978
38979 $process = new ProcessExecutor($io);
38980
38981  if ($process->execute('hg summary', $output, $url) === 0) {
38982 return true;
38983 }
38984 }
38985
38986 if (!$deep) {
38987 return false;
38988 }
38989
38990 $processExecutor = new ProcessExecutor($io);
38991 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
38992
38993 return $exit === 0;
38994 }
38995 }
38996 <?php
38997
38998
38999
39000
39001
39002
39003
39004
39005
39006
39007
39008 namespace Composer\Repository\Vcs;
39009
39010 use Composer\Config;
39011 use Composer\Cache;
39012 use Composer\IO\IOInterface;
39013 use Composer\Util\ProcessExecutor;
39014 use Composer\Util\Perforce;
39015
39016
39017
39018
39019 class PerforceDriver extends VcsDriver
39020 {
39021 protected $depot;
39022 protected $branch;
39023
39024 protected $perforce;
39025
39026
39027
39028
39029 public function initialize()
39030 {
39031 $this->depot = $this->repoConfig['depot'];
39032 $this->branch = '';
39033 if (!empty($this->repoConfig['branch'])) {
39034 $this->branch = $this->repoConfig['branch'];
39035 }
39036
39037 $this->initPerforce($this->repoConfig);
39038 $this->perforce->p4Login();
39039 $this->perforce->checkStream();
39040
39041 $this->perforce->writeP4ClientSpec();
39042 $this->perforce->connectClient();
39043
39044 return true;
39045 }
39046
39047 private function initPerforce($repoConfig)
39048 {
39049 if (!empty($this->perforce)) {
39050 return;
39051 }
39052
39053 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
39054 throw new \RuntimeException('PerforceDriver requires a usable cache directory, and it looks like you set it to be disabled');
39055 }
39056
39057 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
39058 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
39059 }
39060
39061
39062
39063
39064 public function getFileContent($file, $identifier)
39065 {
39066 return $this->perforce->getFileContent($file, $identifier);
39067 }
39068
39069
39070
39071
39072 public function getChangeDate($identifier)
39073 {
39074 return null;
39075 }
39076
39077
39078
39079
39080 public function getRootIdentifier()
39081 {
39082 return $this->branch;
39083 }
39084
39085
39086
39087
39088 public function getBranches()
39089 {
39090 return $this->perforce->getBranches();
39091 }
39092
39093
39094
39095
39096 public function getTags()
39097 {
39098 return $this->perforce->getTags();
39099 }
39100
39101
39102
39103
39104 public function getDist($identifier)
39105 {
39106 return null;
39107 }
39108
39109
39110
39111
39112 public function getSource($identifier)
39113 {
39114 $source = array(
39115 'type' => 'perforce',
39116 'url' => $this->repoConfig['url'],
39117 'reference' => $identifier,
39118 'p4user' => $this->perforce->getUser(),
39119 );
39120
39121 return $source;
39122 }
39123
39124
39125
39126
39127 public function getUrl()
39128 {
39129 return $this->url;
39130 }
39131
39132
39133
39134
39135 public function hasComposerFile($identifier)
39136 {
39137 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
39138 $composerInfoIdentifier = $identifier;
39139
39140 return !empty($composerInfo);
39141 }
39142
39143
39144
39145
39146 public function getContents($url)
39147 {
39148 return false;
39149 }
39150
39151
39152
39153
39154 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39155 {
39156 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
39157 return Perforce::checkServerExists($url, new ProcessExecutor($io));
39158 }
39159
39160 return false;
39161 }
39162
39163
39164
39165
39166 public function cleanup()
39167 {
39168 $this->perforce->cleanupClientSpec();
39169 $this->perforce = null;
39170 }
39171
39172 public function getDepot()
39173 {
39174 return $this->depot;
39175 }
39176
39177 public function getBranch()
39178 {
39179 return $this->branch;
39180 }
39181 }
39182 <?php
39183
39184
39185
39186
39187
39188
39189
39190
39191
39192
39193
39194 namespace Composer\Repository\Vcs;
39195
39196 use Composer\Cache;
39197 use Composer\Config;
39198 use Composer\Json\JsonFile;
39199 use Composer\Util\ProcessExecutor;
39200 use Composer\Util\Filesystem;
39201 use Composer\Util\Svn as SvnUtil;
39202 use Composer\IO\IOInterface;
39203 use Composer\Downloader\TransportException;
39204
39205
39206
39207
39208
39209 class SvnDriver extends VcsDriver
39210 {
39211
39212
39213
39214 protected $cache;
39215 protected $baseUrl;
39216 protected $tags;
39217 protected $branches;
39218 protected $rootIdentifier;
39219 protected $infoCache = array();
39220
39221 protected $trunkPath = 'trunk';
39222 protected $branchesPath = 'branches';
39223 protected $tagsPath = 'tags';
39224 protected $packagePath = '';
39225 protected $cacheCredentials = true;
39226
39227
39228
39229
39230 private $util;
39231
39232
39233
39234
39235 public function initialize()
39236 {
39237 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
39238
39239 SvnUtil::cleanEnv();
39240
39241 if (isset($this->repoConfig['trunk-path'])) {
39242 $this->trunkPath = $this->repoConfig['trunk-path'];
39243 }
39244 if (isset($this->repoConfig['branches-path'])) {
39245 $this->branchesPath = $this->repoConfig['branches-path'];
39246 }
39247 if (isset($this->repoConfig['tags-path'])) {
39248 $this->tagsPath = $this->repoConfig['tags-path'];
39249 }
39250 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
39251 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
39252 }
39253 if (isset($this->repoConfig['package-path'])) {
39254 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
39255 }
39256
39257 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
39258 $this->baseUrl = substr($this->url, 0, $pos);
39259 }
39260
39261 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
39262
39263 $this->getBranches();
39264 $this->getTags();
39265 }
39266
39267
39268
39269
39270 public function getRootIdentifier()
39271 {
39272 return $this->rootIdentifier ?: $this->trunkPath;
39273 }
39274
39275
39276
39277
39278 public function getUrl()
39279 {
39280 return $this->url;
39281 }
39282
39283
39284
39285
39286 public function getSource($identifier)
39287 {
39288 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
39289 }
39290
39291
39292
39293
39294 public function getDist($identifier)
39295 {
39296 return null;
39297 }
39298
39299
39300
39301
39302 protected function shouldCache($identifier)
39303 {
39304 return $this->cache && preg_match('{@\d+$}', $identifier);
39305 }
39306
39307
39308
39309
39310 public function getComposerInformation($identifier)
39311 {
39312 if (!isset($this->infoCache[$identifier])) {
39313 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier.'.json')) {
39314 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
39315 }
39316
39317 try {
39318 $composer = $this->getBaseComposerInformation($identifier);
39319 } catch (TransportException $e) {
39320 $message = $e->getMessage();
39321 if (stripos($message, 'path not found') === false && stripos($message, 'svn: warning: W160013') === false) {
39322 throw $e;
39323 }
39324
39325  $composer = '';
39326 }
39327
39328 if ($this->shouldCache($identifier)) {
39329 $this->cache->write($identifier.'.json', json_encode($composer));
39330 }
39331
39332 $this->infoCache[$identifier] = $composer;
39333 }
39334
39335 return $this->infoCache[$identifier];
39336 }
39337
39338
39339
39340
39341
39342 public function getFileContent($file, $identifier)
39343 {
39344 $identifier = '/' . trim($identifier, '/') . '/';
39345
39346 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
39347 if (!empty($match[2])) {
39348 $path = $match[1];
39349 $rev = $match[2];
39350 } else {
39351 $path = $identifier;
39352 $rev = '';
39353 }
39354
39355 try {
39356 $resource = $path.$file;
39357 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
39358 if (!trim($output)) {
39359 return null;
39360 }
39361 } catch (\RuntimeException $e) {
39362 throw new TransportException($e->getMessage());
39363 }
39364
39365 return $output;
39366 }
39367
39368
39369
39370
39371 public function getChangeDate($identifier)
39372 {
39373 $identifier = '/' . trim($identifier, '/') . '/';
39374
39375 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
39376 if (!empty($match[2])) {
39377 $path = $match[1];
39378 $rev = $match[2];
39379 } else {
39380 $path = $identifier;
39381 $rev = '';
39382 }
39383
39384 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
39385 foreach ($this->process->splitLines($output) as $line) {
39386 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
39387 return new \DateTime($match[1], new \DateTimeZone('UTC'));
39388 }
39389 }
39390
39391 return null;
39392 }
39393
39394
39395
39396
39397 public function getTags()
39398 {
39399 if (null === $this->tags) {
39400 $this->tags = array();
39401
39402 if ($this->tagsPath !== false) {
39403 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
39404 if ($output) {
39405 foreach ($this->process->splitLines($output) as $line) {
39406 $line = trim($line);
39407 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
39408 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
39409 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
39410 '/' . $this->tagsPath . '/' . $match[2],
39411 $match[1]
39412 );
39413 }
39414 }
39415 }
39416 }
39417 }
39418 }
39419
39420 return $this->tags;
39421 }
39422
39423
39424
39425
39426 public function getBranches()
39427 {
39428 if (null === $this->branches) {
39429 $this->branches = array();
39430
39431 if (false === $this->trunkPath) {
39432 $trunkParent = $this->baseUrl . '/';
39433 } else {
39434 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
39435 }
39436
39437 $output = $this->execute('svn ls --verbose', $trunkParent);
39438 if ($output) {
39439 foreach ($this->process->splitLines($output) as $line) {
39440 $line = trim($line);
39441 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
39442 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
39443 $this->branches['trunk'] = $this->buildIdentifier(
39444 '/' . $this->trunkPath,
39445 $match[1]
39446 );
39447 $this->rootIdentifier = $this->branches['trunk'];
39448 break;
39449 }
39450 }
39451 }
39452 }
39453 unset($output);
39454
39455 if ($this->branchesPath !== false) {
39456 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
39457 if ($output) {
39458 foreach ($this->process->splitLines(trim($output)) as $line) {
39459 $line = trim($line);
39460 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
39461 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
39462 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
39463 '/' . $this->branchesPath . '/' . $match[2],
39464 $match[1]
39465 );
39466 }
39467 }
39468 }
39469 }
39470 }
39471 }
39472
39473 return $this->branches;
39474 }
39475
39476
39477
39478
39479 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39480 {
39481 $url = self::normalizeUrl($url);
39482 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
39483 return true;
39484 }
39485
39486
39487  if (!$deep && !Filesystem::isLocalPath($url)) {
39488 return false;
39489 }
39490
39491 $processExecutor = new ProcessExecutor($io);
39492
39493 $exit = $processExecutor->execute(
39494 "svn info --non-interactive ".ProcessExecutor::escape($url),
39495 $ignoredOutput
39496 );
39497
39498 if ($exit === 0) {
39499
39500  return true;
39501 }
39502
39503
39504  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
39505
39506  
39507  return true;
39508 }
39509
39510
39511  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
39512
39513  
39514  return true;
39515 }
39516
39517 return false;
39518 }
39519
39520
39521
39522
39523
39524
39525
39526
39527 protected static function normalizeUrl($url)
39528 {
39529 $fs = new Filesystem();
39530 if ($fs->isAbsolutePath($url)) {
39531 return 'file://' . strtr($url, '\\', '/');
39532 }
39533
39534 return $url;
39535 }
39536
39537
39538
39539
39540
39541
39542
39543
39544
39545
39546 protected function execute($command, $url)
39547 {
39548 if (null === $this->util) {
39549 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
39550 $this->util->setCacheCredentials($this->cacheCredentials);
39551 }
39552
39553 try {
39554 return $this->util->execute($command, $url);
39555 } catch (\RuntimeException $e) {
39556 if (null === $this->util->binaryVersion()) {
39557 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());
39558 }
39559
39560 throw new \RuntimeException(
39561 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
39562 );
39563 }
39564 }
39565
39566
39567
39568
39569
39570
39571
39572
39573
39574 protected function buildIdentifier($baseDir, $revision)
39575 {
39576 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
39577 }
39578 }
39579 <?php
39580
39581
39582
39583
39584
39585
39586
39587
39588
39589
39590
39591 namespace Composer\Repository\Vcs;
39592
39593 use Composer\Cache;
39594 use Composer\Downloader\TransportException;
39595 use Composer\Config;
39596 use Composer\Factory;
39597 use Composer\IO\IOInterface;
39598 use Composer\Json\JsonFile;
39599 use Composer\Util\ProcessExecutor;
39600 use Composer\Util\RemoteFilesystem;
39601 use Composer\Util\Filesystem;
39602
39603
39604
39605
39606
39607
39608 abstract class VcsDriver implements VcsDriverInterface
39609 {
39610
39611 protected $url;
39612
39613 protected $originUrl;
39614
39615 protected $repoConfig;
39616
39617 protected $io;
39618
39619 protected $config;
39620
39621 protected $process;
39622
39623 protected $remoteFilesystem;
39624
39625 protected $infoCache = array();
39626
39627 protected $cache;
39628
39629
39630
39631
39632
39633
39634
39635
39636
39637
39638 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
39639 {
39640 if (Filesystem::isLocalPath($repoConfig['url'])) {
39641 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
39642 }
39643
39644 $this->url = $repoConfig['url'];
39645 $this->originUrl = $repoConfig['url'];
39646 $this->repoConfig = $repoConfig;
39647 $this->io = $io;
39648 $this->config = $config;
39649 $this->process = $process ?: new ProcessExecutor($io);
39650 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
39651 }
39652
39653
39654
39655
39656
39657
39658
39659 protected function shouldCache($identifier)
39660 {
39661 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
39662 }
39663
39664
39665
39666
39667 public function getComposerInformation($identifier)
39668 {
39669 if (!isset($this->infoCache[$identifier])) {
39670 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
39671 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
39672 }
39673
39674 $composer = $this->getBaseComposerInformation($identifier);
39675
39676 if ($this->shouldCache($identifier)) {
39677 $this->cache->write($identifier, json_encode($composer));
39678 }
39679
39680 $this->infoCache[$identifier] = $composer;
39681 }
39682
39683 return $this->infoCache[$identifier];
39684 }
39685
39686 protected function getBaseComposerInformation($identifier)
39687 {
39688 $composerFileContent = $this->getFileContent('composer.json', $identifier);
39689
39690 if (!$composerFileContent) {
39691 return null;
39692 }
39693
39694 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
39695
39696 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
39697 $composer['time'] = $changeDate->format(DATE_RFC3339);
39698 }
39699
39700 return $composer;
39701 }
39702
39703
39704
39705
39706 public function hasComposerFile($identifier)
39707 {
39708 try {
39709 return (bool) $this->getComposerInformation($identifier);
39710 } catch (TransportException $e) {
39711 }
39712
39713 return false;
39714 }
39715
39716
39717
39718
39719
39720
39721
39722
39723 protected function getScheme()
39724 {
39725 if (extension_loaded('openssl')) {
39726 return 'https';
39727 }
39728
39729 return 'http';
39730 }
39731
39732
39733
39734
39735
39736
39737
39738
39739 protected function getContents($url)
39740 {
39741 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
39742
39743 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
39744 }
39745
39746
39747
39748
39749 public function cleanup()
39750 {
39751 return;
39752 }
39753 }
39754 <?php
39755
39756
39757
39758
39759
39760
39761
39762
39763
39764
39765
39766 namespace Composer\Repository\Vcs;
39767
39768 use Composer\Config;
39769 use Composer\IO\IOInterface;
39770
39771
39772
39773
39774 interface VcsDriverInterface
39775 {
39776
39777
39778
39779 public function initialize();
39780
39781
39782
39783
39784
39785
39786
39787 public function getComposerInformation($identifier);
39788
39789
39790
39791
39792
39793
39794
39795
39796 public function getFileContent($file, $identifier);
39797
39798
39799
39800
39801
39802
39803
39804 public function getChangeDate($identifier);
39805
39806
39807
39808
39809
39810
39811 public function getRootIdentifier();
39812
39813
39814
39815
39816
39817
39818 public function getBranches();
39819
39820
39821
39822
39823
39824
39825 public function getTags();
39826
39827
39828
39829
39830
39831 public function getDist($identifier);
39832
39833
39834
39835
39836
39837 public function getSource($identifier);
39838
39839
39840
39841
39842
39843
39844 public function getUrl();
39845
39846
39847
39848
39849
39850
39851
39852
39853 public function hasComposerFile($identifier);
39854
39855
39856
39857
39858 public function cleanup();
39859
39860
39861
39862
39863
39864
39865
39866
39867
39868
39869 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
39870 }
39871 <?php
39872
39873
39874
39875
39876
39877
39878
39879
39880
39881
39882
39883 namespace Composer\Repository;
39884
39885 use Composer\Downloader\TransportException;
39886 use Composer\Repository\Vcs\VcsDriverInterface;
39887 use Composer\Package\Version\VersionParser;
39888 use Composer\Package\Loader\ArrayLoader;
39889 use Composer\Package\Loader\ValidatingArrayLoader;
39890 use Composer\Package\Loader\InvalidPackageException;
39891 use Composer\Package\Loader\LoaderInterface;
39892 use Composer\EventDispatcher\EventDispatcher;
39893 use Composer\IO\IOInterface;
39894 use Composer\Config;
39895
39896
39897
39898
39899 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
39900 {
39901 protected $url;
39902 protected $packageName;
39903 protected $isVerbose;
39904 protected $isVeryVerbose;
39905 protected $io;
39906 protected $config;
39907 protected $versionParser;
39908 protected $type;
39909 protected $loader;
39910 protected $repoConfig;
39911 protected $branchErrorOccurred = false;
39912 private $drivers;
39913
39914 private $driver;
39915
39916 private $versionCache;
39917 private $emptyReferences = array();
39918
39919 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null, VersionCacheInterface $versionCache = null)
39920 {
39921 parent::__construct();
39922 $this->drivers = $drivers ?: array(
39923 'github' => 'Composer\Repository\Vcs\GitHubDriver',
39924 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
39925 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
39926 'git' => 'Composer\Repository\Vcs\GitDriver',
39927 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
39928 'hg' => 'Composer\Repository\Vcs\HgDriver',
39929 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
39930 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
39931
39932  'svn' => 'Composer\Repository\Vcs\SvnDriver',
39933 );
39934
39935 $this->url = $repoConfig['url'];
39936 $this->io = $io;
39937 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
39938 $this->isVerbose = $io->isVerbose();
39939 $this->isVeryVerbose = $io->isVeryVerbose();
39940 $this->config = $config;
39941 $this->repoConfig = $repoConfig;
39942 $this->versionCache = $versionCache;
39943 }
39944
39945 public function getRepoConfig()
39946 {
39947 return $this->repoConfig;
39948 }
39949
39950 public function setLoader(LoaderInterface $loader)
39951 {
39952 $this->loader = $loader;
39953 }
39954
39955 public function getDriver()
39956 {
39957 if ($this->driver) {
39958 return $this->driver;
39959 }
39960
39961 if (isset($this->drivers[$this->type])) {
39962 $class = $this->drivers[$this->type];
39963 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
39964 $this->driver->initialize();
39965
39966 return $this->driver;
39967 }
39968
39969 foreach ($this->drivers as $driver) {
39970 if ($driver::supports($this->io, $this->config, $this->url)) {
39971 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
39972 $this->driver->initialize();
39973
39974 return $this->driver;
39975 }
39976 }
39977
39978 foreach ($this->drivers as $driver) {
39979 if ($driver::supports($this->io, $this->config, $this->url, true)) {
39980 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
39981 $this->driver->initialize();
39982
39983 return $this->driver;
39984 }
39985 }
39986 }
39987
39988 public function hadInvalidBranches()
39989 {
39990 return $this->branchErrorOccurred;
39991 }
39992
39993 public function getEmptyReferences()
39994 {
39995 return $this->emptyReferences;
39996 }
39997
39998 protected function initialize()
39999 {
40000 parent::initialize();
40001
40002 $isVerbose = $this->isVerbose;
40003 $isVeryVerbose = $this->isVeryVerbose;
40004
40005 $driver = $this->getDriver();
40006 if (!$driver) {
40007 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
40008 }
40009
40010 $this->versionParser = new VersionParser;
40011 if (!$this->loader) {
40012 $this->loader = new ArrayLoader($this->versionParser);
40013 }
40014
40015 try {
40016 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
40017 $data = $driver->getComposerInformation($driver->getRootIdentifier());
40018 $this->packageName = !empty($data['name']) ? $data['name'] : null;
40019 }
40020 } catch (\Exception $e) {
40021 if ($isVeryVerbose) {
40022 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
40023 }
40024 }
40025
40026 foreach ($driver->getTags() as $tag => $identifier) {
40027 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
40028 if ($isVeryVerbose) {
40029 $this->io->writeError($msg);
40030 } elseif ($isVerbose) {
40031 $this->io->overwriteError($msg, false);
40032 }
40033
40034
40035  $tag = str_replace('release-', '', $tag);
40036
40037 $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose);
40038 if ($cachedPackage) {
40039 $this->addPackage($cachedPackage);
40040
40041 continue;
40042 } elseif ($cachedPackage === false) {
40043 $this->emptyReferences[] = $identifier;
40044
40045 continue;
40046 }
40047
40048 if (!$parsedTag = $this->validateTag($tag)) {
40049 if ($isVeryVerbose) {
40050 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
40051 }
40052 continue;
40053 }
40054
40055 try {
40056 if (!$data = $driver->getComposerInformation($identifier)) {
40057 if ($isVeryVerbose) {
40058 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
40059 }
40060 $this->emptyReferences[] = $identifier;
40061 continue;
40062 }
40063
40064
40065  if (isset($data['version'])) {
40066 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
40067 } else {
40068
40069  $data['version'] = $tag;
40070 $data['version_normalized'] = $parsedTag;
40071 }
40072
40073
40074  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
40075 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
40076
40077
40078  if ($data['version_normalized'] !== $parsedTag) {
40079 if ($isVeryVerbose) {
40080 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
40081 }
40082 continue;
40083 }
40084
40085 $tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
40086 if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
40087 if ($isVeryVerbose) {
40088 $this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
40089 }
40090 continue;
40091 }
40092
40093 if ($isVeryVerbose) {
40094 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
40095 }
40096
40097 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
40098 } catch (\Exception $e) {
40099 if ($e instanceof TransportException && $e->getCode() === 404) {
40100 $this->emptyReferences[] = $identifier;
40101 }
40102 if ($isVeryVerbose) {
40103 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
40104 }
40105 continue;
40106 }
40107 }
40108
40109 if (!$isVeryVerbose) {
40110 $this->io->overwriteError('', false);
40111 }
40112
40113 $branches = $driver->getBranches();
40114 foreach ($branches as $branch => $identifier) {
40115 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
40116 if ($isVeryVerbose) {
40117 $this->io->writeError($msg);
40118 } elseif ($isVerbose) {
40119 $this->io->overwriteError($msg, false);
40120 }
40121
40122 if ($branch === 'trunk' && isset($branches['master'])) {
40123 if ($isVeryVerbose) {
40124 $this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
40125 }
40126 continue;
40127 }
40128
40129 if (!$parsedBranch = $this->validateBranch($branch)) {
40130 if ($isVeryVerbose) {
40131 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
40132 }
40133 continue;
40134 }
40135
40136
40137  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
40138 $version = 'dev-' . $branch;
40139 } else {
40140 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
40141 $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
40142 }
40143
40144 $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose);
40145 if ($cachedPackage) {
40146 $this->addPackage($cachedPackage);
40147
40148 continue;
40149 } elseif ($cachedPackage === false) {
40150 $this->emptyReferences[] = $identifier;
40151
40152 continue;
40153 }
40154
40155 try {
40156 if (!$data = $driver->getComposerInformation($identifier)) {
40157 if ($isVeryVerbose) {
40158 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
40159 }
40160 $this->emptyReferences[] = $identifier;
40161 continue;
40162 }
40163
40164
40165  $data['version'] = $version;
40166 $data['version_normalized'] = $parsedBranch;
40167
40168 if ($isVeryVerbose) {
40169 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
40170 }
40171
40172 $packageData = $this->preProcess($driver, $data, $identifier);
40173 $package = $this->loader->load($packageData);
40174 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
40175 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
40176 }
40177 $this->addPackage($package);
40178 } catch (TransportException $e) {
40179 if ($e->getCode() === 404) {
40180 $this->emptyReferences[] = $identifier;
40181 }
40182 if ($isVeryVerbose) {
40183 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
40184 }
40185 continue;
40186 } catch (\Exception $e) {
40187 if (!$isVeryVerbose) {
40188 $this->io->writeError('');
40189 }
40190 $this->branchErrorOccurred = true;
40191 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
40192 $this->io->writeError('');
40193 continue;
40194 }
40195 }
40196 $driver->cleanup();
40197
40198 if (!$isVeryVerbose) {
40199 $this->io->overwriteError('', false);
40200 }
40201
40202 if (!$this->getPackages()) {
40203 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
40204 }
40205 }
40206
40207 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
40208 {
40209
40210  $dataPackageName = isset($data['name']) ? $data['name'] : null;
40211 $data['name'] = $this->packageName ?: $dataPackageName;
40212
40213 if (!isset($data['dist'])) {
40214 $data['dist'] = $driver->getDist($identifier);
40215 }
40216 if (!isset($data['source'])) {
40217 $data['source'] = $driver->getSource($identifier);
40218 }
40219
40220 return $data;
40221 }
40222
40223 private function validateBranch($branch)
40224 {
40225 try {
40226 return $this->versionParser->normalizeBranch($branch);
40227 } catch (\Exception $e) {
40228 }
40229
40230 return false;
40231 }
40232
40233 private function validateTag($version)
40234 {
40235 try {
40236 return $this->versionParser->normalize($version);
40237 } catch (\Exception $e) {
40238 }
40239
40240 return false;
40241 }
40242
40243 private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose)
40244 {
40245 if (!$this->versionCache) {
40246 return;
40247 }
40248
40249 $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
40250 if ($cachedPackage === false) {
40251 if ($isVeryVerbose) {
40252 $this->io->writeError('<warning>Skipped '.$version.', no composer file (cached from ref '.$identifier.')</warning>');
40253 }
40254
40255 return false;
40256 }
40257
40258 if ($cachedPackage) {
40259 $msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
40260 if ($isVeryVerbose) {
40261 $this->io->writeError($msg);
40262 } elseif ($isVerbose) {
40263 $this->io->overwriteError($msg, false);
40264 }
40265
40266 if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) {
40267 if ($isVeryVerbose) {
40268 $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>');
40269 }
40270 $cachedPackage = null;
40271 }
40272 }
40273
40274 if ($cachedPackage) {
40275 return $this->loader->load($cachedPackage);
40276 }
40277
40278 return null;
40279 }
40280 }
40281 <?php
40282
40283
40284
40285
40286
40287
40288
40289
40290
40291
40292
40293 namespace Composer\Repository;
40294
40295 interface VersionCacheInterface
40296 {
40297
40298
40299
40300
40301
40302 public function getVersionPackage($version, $identifier);
40303 }
40304 <?php
40305
40306
40307
40308
40309
40310
40311
40312
40313
40314
40315
40316 namespace Composer\Repository;
40317
40318 use Composer\Package\AliasPackage;
40319
40320
40321
40322
40323
40324
40325 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
40326 {
40327
40328
40329
40330 public function write()
40331 {
40332 }
40333
40334
40335
40336
40337 public function reload()
40338 {
40339 }
40340
40341
40342
40343
40344 public function getCanonicalPackages()
40345 {
40346 $packages = $this->getPackages();
40347
40348
40349  $packagesByName = array();
40350 foreach ($packages as $package) {
40351 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
40352 $packagesByName[$package->getName()] = $package;
40353 }
40354 }
40355
40356 $canonicalPackages = array();
40357
40358
40359  foreach ($packagesByName as $package) {
40360 while ($package instanceof AliasPackage) {
40361 $package = $package->getAliasOf();
40362 }
40363
40364 $canonicalPackages[] = $package;
40365 }
40366
40367 return $canonicalPackages;
40368 }
40369 }
40370 <?php
40371
40372
40373
40374
40375
40376
40377
40378
40379
40380
40381
40382 namespace Composer\Repository;
40383
40384 use Composer\Package\PackageInterface;
40385
40386
40387
40388
40389
40390
40391 interface WritableRepositoryInterface extends RepositoryInterface
40392 {
40393
40394
40395
40396 public function write();
40397
40398
40399
40400
40401
40402
40403 public function addPackage(PackageInterface $package);
40404
40405
40406
40407
40408
40409
40410 public function removePackage(PackageInterface $package);
40411
40412
40413
40414
40415
40416
40417 public function getCanonicalPackages();
40418
40419
40420
40421
40422 public function reload();
40423 }
40424 <?php
40425
40426
40427
40428
40429
40430
40431
40432
40433
40434
40435
40436 namespace Composer\Script;
40437
40438
40439
40440
40441
40442
40443 class CommandEvent extends Event
40444 {
40445 }
40446 <?php
40447
40448
40449
40450
40451
40452
40453
40454
40455
40456
40457
40458 namespace Composer\Script;
40459
40460 use Composer\Composer;
40461 use Composer\IO\IOInterface;
40462 use Composer\EventDispatcher\Event as BaseEvent;
40463
40464
40465
40466
40467
40468
40469
40470 class Event extends BaseEvent
40471 {
40472
40473
40474
40475 private $composer;
40476
40477
40478
40479
40480 private $io;
40481
40482
40483
40484
40485 private $devMode;
40486
40487
40488
40489
40490 private $originatingEvent;
40491
40492
40493
40494
40495
40496
40497
40498
40499
40500
40501
40502 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
40503 {
40504 parent::__construct($name, $args, $flags);
40505 $this->composer = $composer;
40506 $this->io = $io;
40507 $this->devMode = $devMode;
40508 $this->originatingEvent = null;
40509 }
40510
40511
40512
40513
40514
40515
40516 public function getComposer()
40517 {
40518 return $this->composer;
40519 }
40520
40521
40522
40523
40524
40525
40526 public function getIO()
40527 {
40528 return $this->io;
40529 }
40530
40531
40532
40533
40534
40535
40536 public function isDevMode()
40537 {
40538 return $this->devMode;
40539 }
40540
40541
40542
40543
40544
40545
40546 public function getOriginatingEvent()
40547 {
40548 return $this->originatingEvent;
40549 }
40550
40551
40552
40553
40554
40555
40556
40557 public function setOriginatingEvent(BaseEvent $event)
40558 {
40559 $this->originatingEvent = $this->calculateOriginatingEvent($event);
40560
40561 return $this;
40562 }
40563
40564
40565
40566
40567
40568
40569
40570 private function calculateOriginatingEvent(BaseEvent $event)
40571 {
40572 if ($event instanceof Event && $event->getOriginatingEvent()) {
40573 return $this->calculateOriginatingEvent($event->getOriginatingEvent());
40574 }
40575
40576 return $event;
40577 }
40578 }
40579 <?php
40580
40581
40582
40583
40584
40585
40586
40587
40588
40589
40590
40591 namespace Composer\Script;
40592
40593 use Composer\Installer\PackageEvent as BasePackageEvent;
40594
40595
40596
40597
40598
40599
40600 class PackageEvent extends BasePackageEvent
40601 {
40602 }
40603 <?php
40604
40605
40606
40607
40608
40609
40610
40611
40612
40613
40614
40615 namespace Composer\Script;
40616
40617
40618
40619
40620
40621
40622
40623 class ScriptEvents
40624 {
40625
40626
40627
40628
40629
40630
40631
40632 const PRE_INSTALL_CMD = 'pre-install-cmd';
40633
40634
40635
40636
40637
40638
40639
40640
40641 const POST_INSTALL_CMD = 'post-install-cmd';
40642
40643
40644
40645
40646
40647
40648
40649
40650 const PRE_UPDATE_CMD = 'pre-update-cmd';
40651
40652
40653
40654
40655
40656
40657
40658
40659 const POST_UPDATE_CMD = 'post-update-cmd';
40660
40661
40662
40663
40664
40665
40666
40667
40668 const PRE_STATUS_CMD = 'pre-status-cmd';
40669
40670
40671
40672
40673
40674
40675
40676
40677 const POST_STATUS_CMD = 'post-status-cmd';
40678
40679
40680
40681
40682
40683
40684
40685
40686 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
40687
40688
40689
40690
40691
40692
40693
40694
40695 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
40696
40697
40698
40699
40700
40701
40702
40703
40704 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
40705
40706
40707
40708
40709
40710
40711
40712
40713
40714 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
40715
40716
40717
40718
40719
40720
40721
40722
40723 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
40724
40725
40726
40727
40728
40729
40730
40731
40732 const POST_ARCHIVE_CMD = 'post-archive-cmd';
40733
40734
40735
40736
40737
40738
40739
40740
40741
40742
40743
40744 const PRE_PACKAGE_INSTALL = 'pre-package-install';
40745
40746
40747
40748
40749
40750
40751
40752
40753
40754 const POST_PACKAGE_INSTALL = 'post-package-install';
40755
40756
40757
40758
40759
40760
40761
40762
40763
40764 const PRE_PACKAGE_UPDATE = 'pre-package-update';
40765
40766
40767
40768
40769
40770
40771
40772
40773
40774 const POST_PACKAGE_UPDATE = 'post-package-update';
40775
40776
40777
40778
40779
40780
40781
40782
40783
40784 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
40785
40786
40787
40788
40789
40790
40791
40792
40793
40794 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
40795 }
40796 <?php
40797
40798
40799
40800
40801
40802
40803
40804
40805
40806
40807
40808 namespace Composer\SelfUpdate;
40809
40810
40811
40812
40813 class Keys
40814 {
40815 public static function fingerprint($path)
40816 {
40817 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
40818
40819 return implode(' ', array(
40820 substr($hash, 0, 8),
40821 substr($hash, 8, 8),
40822 substr($hash, 16, 8),
40823 substr($hash, 24, 8),
40824 '', 
40825  substr($hash, 32, 8),
40826 substr($hash, 40, 8),
40827 substr($hash, 48, 8),
40828 substr($hash, 56, 8),
40829 ));
40830 }
40831 }
40832 <?php
40833
40834
40835
40836
40837
40838
40839
40840
40841
40842
40843
40844 namespace Composer\SelfUpdate;
40845
40846 use Composer\Util\RemoteFilesystem;
40847 use Composer\Config;
40848 use Composer\Json\JsonFile;
40849
40850
40851
40852
40853 class Versions
40854 {
40855 private $rfs;
40856 private $config;
40857 private $channel;
40858
40859 public function __construct(Config $config, RemoteFilesystem $rfs)
40860 {
40861 $this->rfs = $rfs;
40862 $this->config = $config;
40863 }
40864
40865 public function getChannel()
40866 {
40867 if ($this->channel) {
40868 return $this->channel;
40869 }
40870
40871 $channelFile = $this->config->get('home').'/update-channel';
40872 if (file_exists($channelFile)) {
40873 $channel = trim(file_get_contents($channelFile));
40874 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
40875 return $this->channel = $channel;
40876 }
40877 }
40878
40879 return $this->channel = 'stable';
40880 }
40881
40882 public function setChannel($channel)
40883 {
40884 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
40885 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
40886 }
40887
40888 $channelFile = $this->config->get('home').'/update-channel';
40889 $this->channel = $channel;
40890 file_put_contents($channelFile, $channel.PHP_EOL);
40891 }
40892
40893 public function getLatest()
40894 {
40895 $protocol = extension_loaded('openssl') ? 'https' : 'http';
40896 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
40897
40898 foreach ($versions[$this->getChannel()] as $version) {
40899 if ($version['min-php'] <= PHP_VERSION_ID) {
40900 return $version;
40901 }
40902 }
40903
40904 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
40905 }
40906 }
40907 <?php
40908
40909
40910
40911
40912
40913
40914
40915
40916
40917
40918
40919 namespace Composer\Util;
40920
40921 use Composer\Config;
40922 use Composer\IO\IOInterface;
40923
40924
40925
40926
40927 class AuthHelper
40928 {
40929 protected $io;
40930 protected $config;
40931
40932 public function __construct(IOInterface $io, Config $config)
40933 {
40934 $this->io = $io;
40935 $this->config = $config;
40936 }
40937
40938 public function storeAuth($originUrl, $storeAuth)
40939 {
40940 $store = false;
40941 $configSource = $this->config->getAuthConfigSource();
40942 if ($storeAuth === true) {
40943 $store = $configSource;
40944 } elseif ($storeAuth === 'prompt') {
40945 $answer = $this->io->askAndValidate(
40946 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
40947 function ($value) {
40948 $input = strtolower(substr(trim($value), 0, 1));
40949 if (in_array($input, array('y','n'))) {
40950 return $input;
40951 }
40952 throw new \RuntimeException('Please answer (y)es or (n)o');
40953 },
40954 null,
40955 'y'
40956 );
40957
40958 if ($answer === 'y') {
40959 $store = $configSource;
40960 }
40961 }
40962 if ($store) {
40963 $store->addConfigSetting(
40964 'http-basic.'.$originUrl,
40965 $this->io->getAuthentication($originUrl)
40966 );
40967 }
40968 }
40969 }
40970 <?php
40971
40972
40973
40974
40975
40976
40977
40978
40979
40980
40981
40982 namespace Composer\Util;
40983
40984 use Composer\Factory;
40985 use Composer\IO\IOInterface;
40986 use Composer\Config;
40987 use Composer\Downloader\TransportException;
40988
40989
40990
40991
40992 class Bitbucket
40993 {
40994 private $io;
40995 private $config;
40996 private $process;
40997 private $remoteFilesystem;
40998 private $token = array();
40999 private $time;
41000
41001 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
41002
41003
41004
41005
41006
41007
41008
41009
41010
41011
41012 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
41013 {
41014 $this->io = $io;
41015 $this->config = $config;
41016 $this->process = $process ?: new ProcessExecutor($io);
41017 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
41018 $this->time = $time;
41019 }
41020
41021
41022
41023
41024 public function getToken()
41025 {
41026 if (!isset($this->token['access_token'])) {
41027 return '';
41028 }
41029
41030 return $this->token['access_token'];
41031 }
41032
41033
41034
41035
41036
41037
41038
41039 public function authorizeOAuth($originUrl)
41040 {
41041 if ($originUrl !== 'bitbucket.org') {
41042 return false;
41043 }
41044
41045
41046  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
41047 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
41048
41049 return true;
41050 }
41051
41052 return false;
41053 }
41054
41055
41056
41057
41058
41059 private function requestAccessToken($originUrl)
41060 {
41061 try {
41062 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
41063 'retry-auth-failure' => false,
41064 'http' => array(
41065 'method' => 'POST',
41066 'content' => 'grant_type=client_credentials',
41067 ),
41068 ));
41069
41070 $this->token = json_decode($json, true);
41071 } catch (TransportException $e) {
41072 if ($e->getCode() === 400) {
41073 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
41074 $this->io->writeError('This can have two reasons:');
41075 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
41076 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
41077
41078 return false;
41079 } elseif (in_array($e->getCode(), array(403, 401))) {
41080 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
41081 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
41082
41083 return false;
41084 }
41085
41086 throw $e;
41087 }
41088
41089 return true;
41090 }
41091
41092
41093
41094
41095
41096
41097
41098
41099
41100
41101 public function authorizeOAuthInteractively($originUrl, $message = null)
41102 {
41103 if ($message) {
41104 $this->io->writeError($message);
41105 }
41106
41107 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
41108 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
41109 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
41110 $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)');
41111
41112 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
41113
41114 if (!$consumerKey) {
41115 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
41116 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
41117
41118 return false;
41119 }
41120
41121 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
41122
41123 if (!$consumerSecret) {
41124 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
41125 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
41126
41127 return false;
41128 }
41129
41130 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
41131
41132 if (!$this->requestAccessToken($originUrl)) {
41133 return false;
41134 }
41135
41136
41137  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
41138
41139
41140  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
41141
41142 $this->io->writeError('<info>Consumer stored successfully.</info>');
41143
41144 return true;
41145 }
41146
41147
41148
41149
41150
41151
41152
41153
41154
41155 public function requestToken($originUrl, $consumerKey, $consumerSecret)
41156 {
41157 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
41158 return $this->token['access_token'];
41159 }
41160
41161 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
41162 if (!$this->requestAccessToken($originUrl)) {
41163 return '';
41164 }
41165
41166 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
41167
41168 return $this->token['access_token'];
41169 }
41170
41171
41172
41173
41174
41175
41176
41177 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
41178 {
41179 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
41180
41181 $time = null === $this->time ? time() : $this->time;
41182 $consumer = array(
41183 "consumer-key" => $consumerKey,
41184 "consumer-secret" => $consumerSecret,
41185 "access-token" => $this->token['access_token'],
41186 "access-token-expiration" => $time + $this->token['expires_in'],
41187 );
41188
41189 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
41190 }
41191
41192
41193
41194
41195
41196 private function getTokenFromConfig($originUrl)
41197 {
41198 $authConfig = $this->config->get('bitbucket-oauth');
41199
41200 if (
41201 !isset($authConfig[$originUrl]['access-token'])
41202 || !isset($authConfig[$originUrl]['access-token-expiration'])
41203 || time() > $authConfig[$originUrl]['access-token-expiration']
41204 ) {
41205 return false;
41206 }
41207
41208 $this->token = array(
41209 'access_token' => $authConfig[$originUrl]['access-token'],
41210 );
41211
41212 return true;
41213 }
41214 }
41215 <?php
41216
41217
41218
41219
41220
41221
41222
41223
41224
41225
41226
41227 namespace Composer\Util;
41228
41229
41230
41231
41232
41233
41234 class ComposerMirror
41235 {
41236 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
41237 {
41238 if ($reference) {
41239 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
41240 }
41241 $version = strpos($version, '/') === false ? $version : md5($version);
41242
41243 return str_replace(
41244 array('%package%', '%version%', '%reference%', '%type%'),
41245 array($packageName, $version, $reference, $type),
41246 $mirrorUrl
41247 );
41248 }
41249
41250 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
41251 {
41252 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
41253 $url = 'gh-'.$match[1].'/'.$match[2];
41254 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
41255 $url = 'bb-'.$match[1].'/'.$match[2];
41256 } else {
41257 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
41258 }
41259
41260 return str_replace(
41261 array('%package%', '%normalizedUrl%', '%type%'),
41262 array($packageName, $url, $type),
41263 $mirrorUrl
41264 );
41265 }
41266
41267 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
41268 {
41269 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
41270 }
41271 }
41272 <?php
41273
41274
41275
41276
41277
41278
41279
41280
41281
41282
41283
41284 namespace Composer\Util;
41285
41286 use Composer\Package\Loader\ArrayLoader;
41287 use Composer\Package\Loader\ValidatingArrayLoader;
41288 use Composer\Package\Loader\InvalidPackageException;
41289 use Composer\Json\JsonValidationException;
41290 use Composer\IO\IOInterface;
41291 use Composer\Json\JsonFile;
41292 use Composer\Spdx\SpdxLicenses;
41293
41294
41295
41296
41297
41298
41299
41300 class ConfigValidator
41301 {
41302 private $io;
41303
41304 public function __construct(IOInterface $io)
41305 {
41306 $this->io = $io;
41307 }
41308
41309
41310
41311
41312
41313
41314
41315
41316
41317 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
41318 {
41319 $errors = array();
41320 $publishErrors = array();
41321 $warnings = array();
41322
41323
41324  $laxValid = false;
41325 try {
41326 $json = new JsonFile($file, null, $this->io);
41327 $manifest = $json->read();
41328
41329 $json->validateSchema(JsonFile::LAX_SCHEMA);
41330 $laxValid = true;
41331 $json->validateSchema();
41332 } catch (JsonValidationException $e) {
41333 foreach ($e->getErrors() as $message) {
41334 if ($laxValid) {
41335 $publishErrors[] = $message;
41336 } else {
41337 $errors[] = $message;
41338 }
41339 }
41340 } catch (\Exception $e) {
41341 $errors[] = $e->getMessage();
41342
41343 return array($errors, $publishErrors, $warnings);
41344 }
41345
41346
41347  if (empty($manifest['license'])) {
41348 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
41349 } else {
41350 $licenses = (array) $manifest['license'];
41351
41352
41353  foreach ($licenses as $key => $license) {
41354 if ('proprietary' === $license) {
41355 unset($licenses[$key]);
41356 }
41357 }
41358
41359 $licenseValidator = new SpdxLicenses();
41360 foreach ($licenses as $license) {
41361 $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
41362 if ($spdxLicense && $spdxLicense[3]) {
41363 if (preg_match('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) {
41364 $warnings[] = sprintf(
41365 'License "%s" is a deprecated SPDX license identifier, use "'.str_replace('+', '', $license).'-or-later" instead',
41366 $license
41367 );
41368 } elseif (preg_match('{^[AL]?GPL-[123](\.[01])?$}i', $license)) {
41369 $warnings[] = sprintf(
41370 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead',
41371 $license
41372 );
41373 } else {
41374 $warnings[] = sprintf(
41375 'License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/',
41376 $license
41377 );
41378 }
41379 }
41380 }
41381 }
41382
41383 if (isset($manifest['version'])) {
41384 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
41385 }
41386
41387 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
41388 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
41389 $suggestName = strtolower($suggestName);
41390
41391 $publishErrors[] = sprintf(
41392 '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.',
41393 $manifest['name'],
41394 $suggestName
41395 );
41396 }
41397
41398 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
41399 $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.";
41400 }
41401
41402
41403  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
41404 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
41405
41406 if (!empty($requireOverrides)) {
41407 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
41408 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
41409 }
41410 }
41411
41412
41413  $require = isset($manifest['require']) ? $manifest['require'] : array();
41414 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
41415 $packages = array_merge($require, $requireDev);
41416 foreach ($packages as $package => $version) {
41417 if (preg_match('/#/', $version) === 1) {
41418 $warnings[] = sprintf(
41419 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
41420 $package
41421 );
41422 }
41423 }
41424
41425
41426  $scriptsDescriptions = isset($manifest['scripts-descriptions']) ? $manifest['scripts-descriptions'] : array();
41427 $scripts = isset($manifest['scripts']) ? $manifest['scripts'] : array();
41428 foreach ($scriptsDescriptions as $scriptName => $scriptDescription) {
41429 if (!array_key_exists($scriptName, $scripts)) {
41430 $warnings[] = sprintf(
41431 'Description for non-existent script "%s" found in "scripts-descriptions"',
41432 $scriptName
41433 );
41434 }
41435 }
41436
41437
41438  if (isset($manifest['autoload']['psr-0'][''])) {
41439 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
41440 }
41441 if (isset($manifest['autoload']['psr-4'][''])) {
41442 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
41443 }
41444
41445 try {
41446 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
41447 if (!isset($manifest['version'])) {
41448 $manifest['version'] = '1.0.0';
41449 }
41450 if (!isset($manifest['name'])) {
41451 $manifest['name'] = 'dummy/dummy';
41452 }
41453 $loader->load($manifest);
41454 } catch (InvalidPackageException $e) {
41455 $errors = array_merge($errors, $e->getErrors());
41456 }
41457
41458 $warnings = array_merge($warnings, $loader->getWarnings());
41459
41460 return array($errors, $publishErrors, $warnings);
41461 }
41462 }
41463 <?php
41464
41465
41466
41467
41468
41469
41470
41471
41472
41473
41474
41475 namespace Composer\Util;
41476
41477 use Composer\IO\IOInterface;
41478
41479
41480
41481
41482
41483
41484 class ErrorHandler
41485 {
41486 private static $io;
41487
41488
41489
41490
41491
41492
41493
41494
41495
41496
41497
41498
41499
41500 public static function handle($level, $message, $file, $line)
41501 {
41502
41503  if (!(error_reporting() & $level)) {
41504 return;
41505 }
41506
41507 if (filter_var(ini_get('xdebug.scream'), FILTER_VALIDATE_BOOLEAN)) {
41508 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
41509 "\na legitimately suppressed error that you were not supposed to see.";
41510 }
41511
41512 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
41513 throw new \ErrorException($message, 0, $level, $file, $line);
41514 }
41515
41516 if (self::$io) {
41517 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
41518 if (self::$io->isVerbose()) {
41519 self::$io->writeError('<warning>Stack trace:</warning>');
41520 self::$io->writeError(array_filter(array_map(function ($a) {
41521 if (isset($a['line'], $a['file'])) {
41522 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
41523 }
41524
41525 return null;
41526 }, array_slice(debug_backtrace(), 2))));
41527 }
41528 }
41529
41530 return true;
41531 }
41532
41533
41534
41535
41536
41537
41538 public static function register(IOInterface $io = null)
41539 {
41540 set_error_handler(array(__CLASS__, 'handle'));
41541 error_reporting(E_ALL | E_STRICT);
41542 self::$io = $io;
41543 }
41544 }
41545 <?php
41546
41547
41548
41549
41550
41551
41552
41553
41554
41555
41556
41557 namespace Composer\Util;
41558
41559 use RecursiveDirectoryIterator;
41560 use RecursiveIteratorIterator;
41561 use Symfony\Component\Filesystem\Exception\IOException;
41562 use Symfony\Component\Finder\Finder;
41563
41564
41565
41566
41567
41568 class Filesystem
41569 {
41570 private $processExecutor;
41571
41572 public function __construct(ProcessExecutor $executor = null)
41573 {
41574 $this->processExecutor = $executor ?: new ProcessExecutor();
41575 }
41576
41577 public function remove($file)
41578 {
41579 if (is_dir($file)) {
41580 return $this->removeDirectory($file);
41581 }
41582
41583 if (file_exists($file)) {
41584 return $this->unlink($file);
41585 }
41586
41587 return false;
41588 }
41589
41590
41591
41592
41593
41594
41595
41596 public function isDirEmpty($dir)
41597 {
41598 $finder = Finder::create()
41599 ->ignoreVCS(false)
41600 ->ignoreDotFiles(false)
41601 ->depth(0)
41602 ->in($dir);
41603
41604 return count($finder) === 0;
41605 }
41606
41607 public function emptyDirectory($dir, $ensureDirectoryExists = true)
41608 {
41609 if (file_exists($dir) && is_link($dir)) {
41610 $this->unlink($dir);
41611 }
41612
41613 if ($ensureDirectoryExists) {
41614 $this->ensureDirectoryExists($dir);
41615 }
41616
41617 if (is_dir($dir)) {
41618 $finder = Finder::create()
41619 ->ignoreVCS(false)
41620 ->ignoreDotFiles(false)
41621 ->depth(0)
41622 ->in($dir);
41623
41624 foreach ($finder as $path) {
41625 $this->remove((string) $path);
41626 }
41627 }
41628 }
41629
41630
41631
41632
41633
41634
41635
41636
41637
41638
41639
41640 public function removeDirectory($directory)
41641 {
41642 if ($this->isSymlinkedDirectory($directory)) {
41643 return $this->unlinkSymlinkedDirectory($directory);
41644 }
41645
41646 if ($this->isJunction($directory)) {
41647 return $this->removeJunction($directory);
41648 }
41649
41650 if (is_link($directory)) {
41651 return unlink($directory);
41652 }
41653
41654 if (!file_exists($directory) || !is_dir($directory)) {
41655 return true;
41656 }
41657
41658 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
41659 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
41660 }
41661
41662 if (!function_exists('proc_open')) {
41663 return $this->removeDirectoryPhp($directory);
41664 }
41665
41666 if (Platform::isWindows()) {
41667 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
41668 } else {
41669 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
41670 }
41671
41672 $result = $this->getProcess()->execute($cmd, $output) === 0;
41673
41674
41675  clearstatcache();
41676
41677 if ($result && !file_exists($directory)) {
41678 return true;
41679 }
41680
41681 return $this->removeDirectoryPhp($directory);
41682 }
41683
41684
41685
41686
41687
41688
41689
41690
41691
41692
41693
41694 public function removeDirectoryPhp($directory)
41695 {
41696 try {
41697 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
41698 } catch (\UnexpectedValueException $e) {
41699
41700  
41701  clearstatcache();
41702 usleep(100000);
41703 if (!is_dir($directory)) {
41704 return true;
41705 }
41706 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
41707 }
41708 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
41709
41710 foreach ($ri as $file) {
41711 if ($file->isDir()) {
41712 $this->rmdir($file->getPathname());
41713 } else {
41714 $this->unlink($file->getPathname());
41715 }
41716 }
41717
41718 return $this->rmdir($directory);
41719 }
41720
41721 public function ensureDirectoryExists($directory)
41722 {
41723 if (!is_dir($directory)) {
41724 if (file_exists($directory)) {
41725 throw new \RuntimeException(
41726 $directory.' exists and is not a directory.'
41727 );
41728 }
41729 if (!@mkdir($directory, 0777, true)) {
41730 throw new \RuntimeException(
41731 $directory.' does not exist and could not be created.'
41732 );
41733 }
41734 }
41735 }
41736
41737
41738
41739
41740
41741
41742
41743
41744 public function unlink($path)
41745 {
41746 $unlinked = @$this->unlinkImplementation($path);
41747 if (!$unlinked) {
41748
41749  if (Platform::isWindows()) {
41750 usleep(350000);
41751 $unlinked = @$this->unlinkImplementation($path);
41752 }
41753
41754 if (!$unlinked) {
41755 $error = error_get_last();
41756 $message = 'Could not delete '.$path.': ' . @$error['message'];
41757 if (Platform::isWindows()) {
41758 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
41759 }
41760
41761 throw new \RuntimeException($message);
41762 }
41763 }
41764
41765 return true;
41766 }
41767
41768
41769
41770
41771
41772
41773
41774
41775 public function rmdir($path)
41776 {
41777 $deleted = @rmdir($path);
41778 if (!$deleted) {
41779
41780  if (Platform::isWindows()) {
41781 usleep(350000);
41782 $deleted = @rmdir($path);
41783 }
41784
41785 if (!$deleted) {
41786 $error = error_get_last();
41787 $message = 'Could not delete '.$path.': ' . @$error['message'];
41788 if (Platform::isWindows()) {
41789 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
41790 }
41791
41792 throw new \RuntimeException($message);
41793 }
41794 }
41795
41796 return true;
41797 }
41798
41799
41800
41801
41802
41803
41804
41805
41806
41807
41808 public function copyThenRemove($source, $target)
41809 {
41810 $this->copy($source, $target);
41811 if (!is_dir($source)) {
41812 $this->unlink($source);
41813
41814 return;
41815 }
41816
41817 $this->removeDirectoryPhp($source);
41818 }
41819
41820
41821
41822
41823
41824
41825
41826
41827 public function copy($source, $target)
41828 {
41829 if (!is_dir($source)) {
41830 return copy($source, $target);
41831 }
41832
41833 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
41834 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
41835 $this->ensureDirectoryExists($target);
41836
41837 $result = true;
41838 foreach ($ri as $file) {
41839 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
41840 if ($file->isDir()) {
41841 $this->ensureDirectoryExists($targetPath);
41842 } else {
41843 $result = $result && copy($file->getPathname(), $targetPath);
41844 }
41845 }
41846
41847 return $result;
41848 }
41849
41850 public function rename($source, $target)
41851 {
41852 if (true === @rename($source, $target)) {
41853 return;
41854 }
41855
41856 if (!function_exists('proc_open')) {
41857 return $this->copyThenRemove($source, $target);
41858 }
41859
41860 if (Platform::isWindows()) {
41861
41862  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
41863 $result = $this->processExecutor->execute($command, $output);
41864
41865
41866  clearstatcache();
41867
41868 if (0 === $result) {
41869 $this->remove($source);
41870
41871 return;
41872 }
41873 } else {
41874
41875  
41876  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
41877 $result = $this->processExecutor->execute($command, $output);
41878
41879
41880  clearstatcache();
41881
41882 if (0 === $result) {
41883 return;
41884 }
41885 }
41886
41887 return $this->copyThenRemove($source, $target);
41888 }
41889
41890
41891
41892
41893
41894
41895
41896
41897
41898
41899 public function findShortestPath($from, $to, $directories = false)
41900 {
41901 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
41902 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
41903 }
41904
41905 $from = lcfirst($this->normalizePath($from));
41906 $to = lcfirst($this->normalizePath($to));
41907
41908 if ($directories) {
41909 $from = rtrim($from, '/') . '/dummy_file';
41910 }
41911
41912 if (dirname($from) === dirname($to)) {
41913 return './'.basename($to);
41914 }
41915
41916 $commonPath = $to;
41917 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
41918 $commonPath = strtr(dirname($commonPath), '\\', '/');
41919 }
41920
41921 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
41922 return $to;
41923 }
41924
41925 $commonPath = rtrim($commonPath, '/') . '/';
41926 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
41927 $commonPathCode = str_repeat('../', $sourcePathDepth);
41928
41929 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
41930 }
41931
41932
41933
41934
41935
41936
41937
41938
41939
41940
41941
41942 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
41943 {
41944 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
41945 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
41946 }
41947
41948 $from = lcfirst($this->normalizePath($from));
41949 $to = lcfirst($this->normalizePath($to));
41950
41951 if ($from === $to) {
41952 return $directories ? '__DIR__' : '__FILE__';
41953 }
41954
41955 $commonPath = $to;
41956 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
41957 $commonPath = strtr(dirname($commonPath), '\\', '/');
41958 }
41959
41960 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
41961 return var_export($to, true);
41962 }
41963
41964 $commonPath = rtrim($commonPath, '/') . '/';
41965 if (strpos($to, $from.'/') === 0) {
41966 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
41967 }
41968 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
41969 if ($staticCode) {
41970 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
41971 } else {
41972 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
41973 }
41974 $relTarget = substr($to, strlen($commonPath));
41975
41976 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
41977 }
41978
41979
41980
41981
41982
41983
41984
41985 public function isAbsolutePath($path)
41986 {
41987 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':' || substr($path, 0, 2) === '\\\\';
41988 }
41989
41990
41991
41992
41993
41994
41995
41996
41997
41998 public function size($path)
41999 {
42000 if (!file_exists($path)) {
42001 throw new \RuntimeException("$path does not exist.");
42002 }
42003 if (is_dir($path)) {
42004 return $this->directorySize($path);
42005 }
42006
42007 return filesize($path);
42008 }
42009
42010
42011
42012
42013
42014
42015
42016
42017 public function normalizePath($path)
42018 {
42019 $parts = array();
42020 $path = strtr($path, '\\', '/');
42021 $prefix = '';
42022 $absolute = false;
42023
42024
42025  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
42026 $prefix = $match[1];
42027 $path = substr($path, strlen($prefix));
42028 }
42029
42030 if (substr($path, 0, 1) === '/') {
42031 $absolute = true;
42032 $path = substr($path, 1);
42033 }
42034
42035 $up = false;
42036 foreach (explode('/', $path) as $chunk) {
42037 if ('..' === $chunk && ($absolute || $up)) {
42038 array_pop($parts);
42039 $up = !(empty($parts) || '..' === end($parts));
42040 } elseif ('.' !== $chunk && '' !== $chunk) {
42041 $parts[] = $chunk;
42042 $up = '..' !== $chunk;
42043 }
42044 }
42045
42046 return $prefix.($absolute ? '/' : '').implode('/', $parts);
42047 }
42048
42049
42050
42051
42052
42053
42054
42055 public static function isLocalPath($path)
42056 {
42057 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
42058 }
42059
42060 public static function getPlatformPath($path)
42061 {
42062 if (Platform::isWindows()) {
42063 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
42064 }
42065
42066 return preg_replace('{^file://}i', '', $path);
42067 }
42068
42069 protected function directorySize($directory)
42070 {
42071 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
42072 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
42073
42074 $size = 0;
42075 foreach ($ri as $file) {
42076 if ($file->isFile()) {
42077 $size += $file->getSize();
42078 }
42079 }
42080
42081 return $size;
42082 }
42083
42084 protected function getProcess()
42085 {
42086 return $this->processExecutor;
42087 }
42088
42089
42090
42091
42092
42093
42094
42095
42096
42097
42098 private function unlinkImplementation($path)
42099 {
42100 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
42101 return rmdir($path);
42102 }
42103
42104 return unlink($path);
42105 }
42106
42107
42108
42109
42110
42111
42112
42113
42114 public function relativeSymlink($target, $link)
42115 {
42116 $cwd = getcwd();
42117
42118 $relativePath = $this->findShortestPath($link, $target);
42119 chdir(dirname($link));
42120 $result = @symlink($relativePath, $link);
42121
42122 chdir($cwd);
42123
42124 return $result;
42125 }
42126
42127
42128
42129
42130
42131
42132
42133
42134 public function isSymlinkedDirectory($directory)
42135 {
42136 if (!is_dir($directory)) {
42137 return false;
42138 }
42139
42140 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
42141
42142 return is_link($resolved);
42143 }
42144
42145
42146
42147
42148
42149
42150 private function unlinkSymlinkedDirectory($directory)
42151 {
42152 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
42153
42154 return $this->unlink($resolved);
42155 }
42156
42157
42158
42159
42160
42161
42162
42163
42164 private function resolveSymlinkedDirectorySymlink($pathname)
42165 {
42166 if (!is_dir($pathname)) {
42167 return $pathname;
42168 }
42169
42170 $resolved = rtrim($pathname, '/');
42171
42172 if (!strlen($resolved)) {
42173 return $pathname;
42174 }
42175
42176 return $resolved;
42177 }
42178
42179
42180
42181
42182
42183
42184
42185 public function junction($target, $junction)
42186 {
42187 if (!Platform::isWindows()) {
42188 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
42189 }
42190 if (!is_dir($target)) {
42191 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
42192 }
42193 $cmd = sprintf(
42194 'mklink /J %s %s',
42195 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
42196 ProcessExecutor::escape(realpath($target))
42197 );
42198 if ($this->getProcess()->execute($cmd, $output) !== 0) {
42199 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
42200 }
42201 clearstatcache(true, $junction);
42202 }
42203
42204
42205
42206
42207
42208
42209
42210
42211
42212
42213
42214
42215
42216
42217
42218
42219
42220
42221
42222
42223
42224 public function isJunction($junction)
42225 {
42226 if (!Platform::isWindows()) {
42227 return false;
42228 }
42229
42230
42231  clearstatcache(true, $junction);
42232
42233 if (!is_dir($junction) || is_link($junction)) {
42234 return false;
42235 }
42236
42237 $stat = lstat($junction);
42238
42239
42240  return $stat ? 0x4000 !== ($stat['mode'] & 0xF000) : false;
42241 }
42242
42243
42244
42245
42246
42247
42248
42249 public function removeJunction($junction)
42250 {
42251 if (!Platform::isWindows()) {
42252 return false;
42253 }
42254 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
42255 if (!$this->isJunction($junction)) {
42256 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
42257 }
42258
42259 return $this->rmdir($junction);
42260 }
42261 }
42262 <?php
42263
42264
42265
42266
42267
42268
42269
42270
42271
42272
42273
42274 namespace Composer\Util;
42275
42276 use Composer\Config;
42277 use Composer\IO\IOInterface;
42278
42279
42280
42281
42282 class Git
42283 {
42284 private static $version;
42285
42286
42287 protected $io;
42288
42289 protected $config;
42290
42291 protected $process;
42292
42293 protected $filesystem;
42294
42295 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
42296 {
42297 $this->io = $io;
42298 $this->config = $config;
42299 $this->process = $process;
42300 $this->filesystem = $fs;
42301 }
42302
42303 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
42304 {
42305
42306  $this->config->prohibitUrlByConfig($url, $this->io);
42307
42308 if ($initialClone) {
42309 $origCwd = $cwd;
42310 $cwd = null;
42311 }
42312
42313 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
42314 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.');
42315 }
42316
42317 if (!$initialClone) {
42318
42319  $this->process->execute('git remote -v', $output, $cwd);
42320 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) {
42321 $this->io->setAuthentication($match[3], rawurldecode($match[1]), rawurldecode($match[2]));
42322 }
42323 }
42324
42325 $protocols = $this->config->get('github-protocols');
42326 if (!is_array($protocols)) {
42327 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
42328 }
42329
42330  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
42331 $messages = array();
42332 foreach ($protocols as $protocol) {
42333 if ('ssh' === $protocol) {
42334 $protoUrl = "git@" . $match[1] . ":" . $match[2];
42335 } else {
42336 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
42337 }
42338
42339 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
42340 return;
42341 }
42342 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
42343 if ($initialClone) {
42344 $this->filesystem->removeDirectory($origCwd);
42345 }
42346 }
42347
42348
42349  $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
42350 }
42351
42352
42353  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
42354
42355 $command = call_user_func($commandCallable, $url);
42356
42357 $auth = null;
42358 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
42359
42360  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)
42361 || preg_match('{^(https?)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)
42362 ) {
42363 if (!$this->io->hasAuthentication($match[1])) {
42364 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
42365 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
42366
42367 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
42368 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
42369 }
42370 }
42371
42372 if ($this->io->hasAuthentication($match[1])) {
42373 $auth = $this->io->getAuthentication($match[1]);
42374 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
42375 $command = call_user_func($commandCallable, $authUrl);
42376 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42377 return;
42378 }
42379 }
42380 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
42381  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
42382
42383 if (!$this->io->hasAuthentication($match[1])) {
42384 $message = 'Enter your Bitbucket credentials to access private repos';
42385
42386 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
42387 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
42388 $accessToken = $bitbucketUtil->getToken();
42389 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
42390 }
42391 } else { 
42392  $auth = $this->io->getAuthentication($match[1]);
42393
42394
42395  if ($auth['username'] !== 'x-token-auth') {
42396 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
42397 if (! empty($accessToken)) {
42398 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
42399 }
42400 }
42401 }
42402
42403 if ($this->io->hasAuthentication($match[1])) {
42404 $auth = $this->io->getAuthentication($match[1]);
42405 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
42406
42407 $command = call_user_func($commandCallable, $authUrl);
42408 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42409 return;
42410 }
42411 } else { 
42412  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
42413 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
42414 $command = call_user_func($commandCallable, $sshUrl);
42415 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42416 return;
42417 }
42418 }
42419 } elseif (
42420 preg_match('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)
42421 || preg_match('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}', $url, $match)
42422 ) {
42423 if ($match[1] === 'git') {
42424 $match[1] = 'https';
42425 }
42426
42427 if (!$this->io->hasAuthentication($match[2])) {
42428 $gitLabUtil = new GitLab($this->io, $this->config, $this->process);
42429 $message = 'Cloning failed, enter your GitLab credentials to access private repos';
42430
42431 if (!$gitLabUtil->authorizeOAuth($match[2]) && $this->io->isInteractive()) {
42432 $gitLabUtil->authorizeOAuthInteractively($match[1], $match[2], $message);
42433 }
42434 }
42435
42436 if ($this->io->hasAuthentication($match[2])) {
42437 $auth = $this->io->getAuthentication($match[2]);
42438 if ($auth['password'] === 'private-token' || $auth['password'] === 'oauth2' || $auth['password'] === 'gitlab-ci-token') {
42439 $authUrl = $match[1] . '://' . rawurlencode($auth['password']) . ':' . rawurlencode($auth['username']) . '@' . $match[2] . '/' . $match[3]; 
42440  } else {
42441 $authUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . '/' . $match[3];
42442 }
42443
42444 $command = call_user_func($commandCallable, $authUrl);
42445 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42446 return;
42447 }
42448 }
42449 } elseif ($this->isAuthenticationFailure($url, $match)) { 
42450  if (strpos($match[2], '@')) {
42451 list($authParts, $match[2]) = explode('@', $match[2], 2);
42452 }
42453
42454 $storeAuth = false;
42455 if ($this->io->hasAuthentication($match[2])) {
42456 $auth = $this->io->getAuthentication($match[2]);
42457 } elseif ($this->io->isInteractive()) {
42458 $defaultUsername = null;
42459 if (isset($authParts) && $authParts) {
42460 if (false !== strpos($authParts, ':')) {
42461 list($defaultUsername, ) = explode(':', $authParts, 2);
42462 } else {
42463 $defaultUsername = $authParts;
42464 }
42465 }
42466
42467 $this->io->writeError('    Authentication required (<info>' . $match[2] . '</info>):');
42468 $auth = array(
42469 'username' => $this->io->ask('      Username: ', $defaultUsername),
42470 'password' => $this->io->askAndHideAnswer('      Password: '),
42471 );
42472 $storeAuth = $this->config->get('store-auths');
42473 }
42474
42475 if ($auth) {
42476 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
42477
42478 $command = call_user_func($commandCallable, $authUrl);
42479 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
42480 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
42481 $authHelper = new AuthHelper($this->io, $this->config);
42482 $authHelper->storeAuth($match[2], $storeAuth);
42483
42484 return;
42485 }
42486 }
42487 }
42488
42489 $errorMsg = $this->process->getErrorOutput();
42490 if ($initialClone) {
42491 $this->filesystem->removeDirectory($origCwd);
42492 }
42493
42494 $this->throwException('Failed to execute ' . $command . "\n\n" . $errorMsg, $url);
42495 }
42496 }
42497
42498 public function syncMirror($url, $dir)
42499 {
42500
42501  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
42502 try {
42503 $commandCallable = function ($url) {
42504 $sanitizedUrl = preg_replace('{://([^@]+?):(.+?)@}', '://', $url);
42505
42506 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));
42507 };
42508 $this->runCommand($commandCallable, $url, $dir);
42509 } catch (\Exception $e) {
42510 return false;
42511 }
42512
42513 return true;
42514 }
42515
42516
42517  $this->filesystem->removeDirectory($dir);
42518
42519 $commandCallable = function ($url) use ($dir) {
42520 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
42521 };
42522
42523 $this->runCommand($commandCallable, $url, $dir, true);
42524
42525 return true;
42526 }
42527
42528 public function fetchRefOrSyncMirror($url, $dir, $ref)
42529 {
42530 if ($this->checkRefIsInMirror($url, $dir, $ref)) {
42531 return true;
42532 }
42533
42534 if ($this->syncMirror($url, $dir)) {
42535 return $this->checkRefIsInMirror($url, $dir, $ref);
42536 }
42537
42538 return false;
42539 }
42540
42541 private function checkRefIsInMirror($url, $dir, $ref)
42542 {
42543 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
42544 $escapedRef = ProcessExecutor::escape($ref.'^{commit}');
42545 $exitCode = $this->process->execute(sprintf('git rev-parse --quiet --verify %s', $escapedRef), $ignoredOutput, $dir);
42546 if ($exitCode === 0) {
42547 return true;
42548 }
42549 }
42550
42551 return false;
42552 }
42553
42554 private function isAuthenticationFailure($url, &$match)
42555 {
42556 if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
42557 return false;
42558 }
42559
42560 $authFailures = array(
42561 'fatal: Authentication failed',
42562 'remote error: Invalid username or password.',
42563 'error: 401 Unauthorized',
42564 'fatal: unable to access',
42565 'fatal: could not read Username',
42566 );
42567
42568 $errorOutput = $this->process->getErrorOutput();
42569 foreach ($authFailures as $authFailure) {
42570 if (strpos($errorOutput, $authFailure) !== false) {
42571 return true;
42572 }
42573 }
42574
42575 return false;
42576 }
42577
42578 public static function cleanEnv()
42579 {
42580 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
42581 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');
42582 }
42583
42584
42585  if (getenv('GIT_ASKPASS') !== 'echo') {
42586 putenv('GIT_ASKPASS=echo');
42587 unset($_SERVER['GIT_ASKPASS']);
42588 }
42589
42590
42591  if (getenv('GIT_DIR')) {
42592 putenv('GIT_DIR');
42593 unset($_SERVER['GIT_DIR']);
42594 }
42595 if (getenv('GIT_WORK_TREE')) {
42596 putenv('GIT_WORK_TREE');
42597 unset($_SERVER['GIT_WORK_TREE']);
42598 }
42599
42600
42601  if (getenv('LANGUAGE') !== 'C') {
42602 putenv('LANGUAGE=C');
42603 }
42604
42605
42606  putenv("DYLD_LIBRARY_PATH");
42607 unset($_SERVER['DYLD_LIBRARY_PATH']);
42608 }
42609
42610 public static function getGitHubDomainsRegex(Config $config)
42611 {
42612 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
42613 }
42614
42615 public static function getGitLabDomainsRegex(Config $config)
42616 {
42617 return '(' . implode('|', array_map('preg_quote', $config->get('gitlab-domains'))) . ')';
42618 }
42619
42620 public static function sanitizeUrl($message)
42621 {
42622 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
42623 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
42624 return '://***:***@';
42625 }
42626
42627 return '://' . $m[1] . ':***@';
42628 }, $message);
42629 }
42630
42631 private function throwException($message, $url)
42632 {
42633
42634  clearstatcache();
42635
42636 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
42637 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()));
42638 }
42639
42640 throw new \RuntimeException(self::sanitizeUrl($message));
42641 }
42642
42643
42644
42645
42646
42647
42648 public function getVersion()
42649 {
42650 if (isset(self::$version)) {
42651 return self::$version;
42652 }
42653 if (0 !== $this->process->execute('git --version', $output)) {
42654 return;
42655 }
42656 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
42657 return self::$version = $matches[1];
42658 }
42659 }
42660 }
42661 <?php
42662
42663
42664
42665
42666
42667
42668
42669
42670
42671
42672
42673 namespace Composer\Util;
42674
42675 use Composer\Factory;
42676 use Composer\IO\IOInterface;
42677 use Composer\Config;
42678 use Composer\Downloader\TransportException;
42679
42680
42681
42682
42683 class GitHub
42684 {
42685 protected $io;
42686 protected $config;
42687 protected $process;
42688 protected $remoteFilesystem;
42689
42690
42691
42692
42693
42694
42695
42696
42697
42698 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
42699 {
42700 $this->io = $io;
42701 $this->config = $config;
42702 $this->process = $process ?: new ProcessExecutor($io);
42703 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
42704 }
42705
42706
42707
42708
42709
42710
42711
42712 public function authorizeOAuth($originUrl)
42713 {
42714 if (!in_array($originUrl, $this->config->get('github-domains'))) {
42715 return false;
42716 }
42717
42718
42719  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
42720 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
42721
42722 return true;
42723 }
42724
42725 return false;
42726 }
42727
42728
42729
42730
42731
42732
42733
42734
42735
42736
42737 public function authorizeOAuthInteractively($originUrl, $message = null)
42738 {
42739 if ($message) {
42740 $this->io->writeError($message);
42741 }
42742
42743 $note = 'Composer';
42744 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
42745 $note .= ' on ' . trim($output);
42746 }
42747 $note .= ' ' . date('Y-m-d Hi');
42748
42749 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
42750 $this->io->writeError(sprintf('Head to %s', $url));
42751 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
42752
42753 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
42754
42755 if (!$token) {
42756 $this->io->writeError('<warning>No token given, aborting.</warning>');
42757 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
42758
42759 return false;
42760 }
42761
42762 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
42763
42764 try {
42765 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
42766
42767 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
42768 'retry-auth-failure' => false,
42769 ));
42770 } catch (TransportException $e) {
42771 if (in_array($e->getCode(), array(403, 401))) {
42772 $this->io->writeError('<error>Invalid token provided.</error>');
42773 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
42774
42775 return false;
42776 }
42777
42778 throw $e;
42779 }
42780
42781
42782  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
42783 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
42784
42785 $this->io->writeError('<info>Token stored successfully.</info>');
42786
42787 return true;
42788 }
42789
42790
42791
42792
42793
42794
42795
42796
42797 public function getRateLimit(array $headers)
42798 {
42799 $rateLimit = array(
42800 'limit' => '?',
42801 'reset' => '?',
42802 );
42803
42804 foreach ($headers as $header) {
42805 $header = trim($header);
42806 if (false === strpos($header, 'X-RateLimit-')) {
42807 continue;
42808 }
42809 list($type, $value) = explode(':', $header, 2);
42810 switch ($type) {
42811 case 'X-RateLimit-Limit':
42812 $rateLimit['limit'] = (int) trim($value);
42813 break;
42814 case 'X-RateLimit-Reset':
42815 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
42816 break;
42817 }
42818 }
42819
42820 return $rateLimit;
42821 }
42822
42823
42824
42825
42826
42827
42828
42829
42830 public function isRateLimited(array $headers)
42831 {
42832 foreach ($headers as $header) {
42833 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
42834 return true;
42835 }
42836 }
42837
42838 return false;
42839 }
42840 }
42841 <?php
42842
42843
42844
42845
42846
42847
42848
42849
42850
42851
42852
42853 namespace Composer\Util;
42854
42855 use Composer\IO\IOInterface;
42856 use Composer\Config;
42857 use Composer\Factory;
42858 use Composer\Downloader\TransportException;
42859 use Composer\Json\JsonFile;
42860
42861
42862
42863
42864 class GitLab
42865 {
42866 protected $io;
42867 protected $config;
42868 protected $process;
42869 protected $remoteFilesystem;
42870
42871
42872
42873
42874
42875
42876
42877
42878
42879 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
42880 {
42881 $this->io = $io;
42882 $this->config = $config;
42883 $this->process = $process ?: new ProcessExecutor($io);
42884 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
42885 }
42886
42887
42888
42889
42890
42891
42892
42893
42894 public function authorizeOAuth($originUrl)
42895 {
42896
42897  $bcOriginUrl = preg_replace('{:\d+}', '', $originUrl);
42898
42899 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true) && !in_array($bcOriginUrl, $this->config->get('gitlab-domains'), true)) {
42900 return false;
42901 }
42902
42903
42904  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
42905 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
42906
42907 return true;
42908 }
42909
42910
42911  $authTokens = $this->config->get('gitlab-token');
42912
42913 if (isset($authTokens[$originUrl])) {
42914 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
42915
42916 return true;
42917 }
42918
42919 if (isset($authTokens[$bcOriginUrl])) {
42920 $this->io->setAuthentication($originUrl, $authTokens[$bcOriginUrl], 'private-token');
42921
42922 return true;
42923 }
42924
42925 return false;
42926 }
42927
42928
42929
42930
42931
42932
42933
42934
42935
42936
42937
42938
42939
42940 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
42941 {
42942 if ($message) {
42943 $this->io->writeError($message);
42944 }
42945
42946 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
42947 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
42948
42949 $attemptCounter = 0;
42950
42951 while ($attemptCounter++ < 5) {
42952 try {
42953 $response = $this->createToken($scheme, $originUrl);
42954 } catch (TransportException $e) {
42955
42956  
42957  if (in_array($e->getCode(), array(403, 401))) {
42958 if (401 === $e->getCode()) {
42959 $this->io->writeError('Bad credentials.');
42960 } else {
42961 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
42962 }
42963
42964 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
42965 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
42966
42967 continue;
42968 }
42969
42970 throw $e;
42971 }
42972
42973 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
42974
42975
42976  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
42977
42978 return true;
42979 }
42980
42981 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
42982 }
42983
42984 private function createToken($scheme, $originUrl)
42985 {
42986 $username = $this->io->ask('Username: ');
42987 $password = $this->io->askAndHideAnswer('Password: ');
42988
42989 $headers = array('Content-Type: application/x-www-form-urlencoded');
42990
42991 $apiUrl = $originUrl;
42992 $data = http_build_query(array(
42993 'username' => $username,
42994 'password' => $password,
42995 'grant_type' => 'password',
42996 ), null, '&');
42997 $options = array(
42998 'retry-auth-failure' => false,
42999 'http' => array(
43000 'method' => 'POST',
43001 'header' => $headers,
43002 'content' => $data,
43003 ),
43004 );
43005
43006 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
43007
43008 $this->io->writeError('Token successfully created');
43009
43010 return JsonFile::parseJson($json);
43011 }
43012 }
43013 <?php
43014
43015
43016
43017
43018
43019
43020
43021
43022
43023
43024
43025 namespace Composer\Util;
43026
43027 use Composer\Config;
43028 use Composer\IO\IOInterface;
43029
43030
43031
43032
43033 class Hg
43034 {
43035
43036
43037
43038 private $io;
43039
43040
43041
43042
43043 private $config;
43044
43045
43046
43047
43048 private $process;
43049
43050 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process)
43051 {
43052 $this->io = $io;
43053 $this->config = $config;
43054 $this->process = $process;
43055 }
43056
43057 public function runCommand($commandCallable, $url, $cwd)
43058 {
43059 $this->config->prohibitUrlByConfig($url, $this->io);
43060
43061
43062  $command = call_user_func($commandCallable, $url);
43063
43064 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43065 return;
43066 }
43067
43068
43069  if (preg_match('{^(https?)://((.+)(?:\:(.+))?@)?([^/]+)(/.*)?}mi', $url, $match) && $this->io->hasAuthentication($match[5])) {
43070 $auth = $this->io->getAuthentication($match[5]);
43071 $authenticatedUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[5] . (!empty($match[6]) ? $match[6] : null);
43072
43073 $command = call_user_func($commandCallable, $authenticatedUrl);
43074
43075 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43076 return;
43077 }
43078
43079 $error = $this->process->getErrorOutput();
43080 } else {
43081 $error = 'The given URL (' . $url . ') does not match the required format (http(s)://(username:password@)example.com/path-to-repository)';
43082 }
43083
43084 $this->throwException('Failed to clone ' . $url . ', ' . "\n\n" . $error, $url);
43085 }
43086
43087 public static function sanitizeUrl($message)
43088 {
43089 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
43090 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
43091 return '://***:***@';
43092 }
43093
43094 return '://' . $m[1] . ':***@';
43095 }, $message);
43096 }
43097
43098 private function throwException($message, $url)
43099 {
43100 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
43101 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()));
43102 }
43103
43104 throw new \RuntimeException(self::sanitizeUrl($message));
43105 }
43106 }
43107 <?php
43108
43109
43110
43111
43112
43113
43114
43115
43116
43117
43118
43119 namespace Composer\Util;
43120
43121 use Composer\XdebugHandler\XdebugHandler;
43122
43123
43124
43125
43126
43127
43128
43129
43130 class IniHelper
43131 {
43132
43133
43134
43135
43136
43137
43138
43139
43140 public static function getAll()
43141 {
43142 return XdebugHandler::getAllIniFiles();
43143 }
43144
43145
43146
43147
43148
43149
43150 public static function getMessage()
43151 {
43152 $paths = self::getAll();
43153
43154 if (empty($paths[0])) {
43155 array_shift($paths);
43156 }
43157
43158 $ini = array_shift($paths);
43159
43160 if (empty($ini)) {
43161 return 'A php.ini file does not exist. You will have to create one.';
43162 }
43163
43164 if (!empty($paths)) {
43165 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
43166 }
43167
43168 return 'The php.ini used by your command-line PHP is: '.$ini;
43169 }
43170 }
43171 <?php
43172
43173
43174
43175
43176
43177
43178
43179
43180
43181
43182
43183 namespace Composer\Util;
43184
43185
43186
43187
43188 class NoProxyPattern
43189 {
43190
43191
43192
43193 protected $rules = array();
43194
43195
43196
43197
43198 public function __construct($pattern)
43199 {
43200 $this->rules = preg_split("/[\s,]+/", $pattern);
43201 }
43202
43203
43204
43205
43206
43207
43208
43209
43210 public function test($url)
43211 {
43212 $host = parse_url($url, PHP_URL_HOST);
43213 $port = parse_url($url, PHP_URL_PORT);
43214
43215 if (empty($port)) {
43216 switch (parse_url($url, PHP_URL_SCHEME)) {
43217 case 'http':
43218 $port = 80;
43219 break;
43220 case 'https':
43221 $port = 443;
43222 break;
43223 }
43224 }
43225
43226 foreach ($this->rules as $rule) {
43227 if ($rule == '*') {
43228 return true;
43229 }
43230
43231 $match = false;
43232
43233 list($ruleHost) = explode(':', $rule);
43234 list($base) = explode('/', $ruleHost);
43235
43236 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
43237
43238
43239 if (!isset($ip)) {
43240 $ip = gethostbyname($host);
43241 }
43242
43243 if (strpos($ruleHost, '/') === false) {
43244 $match = $ip === $ruleHost;
43245 } else {
43246
43247  
43248  if ($ip === $host) {
43249 $match = false;
43250 } else {
43251
43252  $match = self::inCIDRBlock($ruleHost, $ip);
43253 }
43254 }
43255 } else {
43256
43257
43258 $haystack = '.' . trim($host, '.') . '.';
43259 $needle = '.'. trim($ruleHost, '.') .'.';
43260 $match = stripos(strrev($haystack), strrev($needle)) === 0;
43261 }
43262
43263
43264  if ($match && strpos($rule, ':') !== false) {
43265 list(, $rulePort) = explode(':', $rule);
43266 if (!empty($rulePort) && $port != $rulePort) {
43267 $match = false;
43268 }
43269 }
43270
43271 if ($match) {
43272 return true;
43273 }
43274 }
43275
43276 return false;
43277 }
43278
43279
43280
43281
43282
43283
43284
43285
43286
43287
43288
43289 private static function inCIDRBlock($cidr, $ip)
43290 {
43291
43292  list($base, $bits) = explode('/', $cidr);
43293
43294
43295  list($a, $b, $c, $d) = explode('.', $base);
43296
43297
43298  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
43299 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
43300
43301
43302  $low = $i & $mask;
43303
43304
43305  $high = $i | (~$mask & 0xFFFFFFFF);
43306
43307
43308  list($a, $b, $c, $d) = explode('.', $ip);
43309
43310
43311  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
43312
43313
43314  
43315  return $check >= $low && $check <= $high;
43316 }
43317 }
43318 <?php
43319
43320
43321 namespace Composer\Util;
43322
43323 use Composer\Package\Link;
43324 use Composer\Package\PackageInterface;
43325
43326 class PackageSorter
43327 {
43328
43329
43330
43331
43332
43333
43334
43335
43336 public static function sortPackages(array $packages) {
43337 $usageList = array();
43338
43339 foreach ($packages as $package) { 
43340 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { 
43341 $target = $link->getTarget();
43342 $usageList[$target][] = $package->getName();
43343 }
43344 }
43345 $computing = array();
43346 $computed = array();
43347 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
43348
43349  if (isset($computed[$name])) {
43350 return $computed[$name];
43351 }
43352
43353
43354  if (isset($computing[$name])) {
43355 return 0;
43356 }
43357
43358 $computing[$name] = true;
43359 $weight = 0;
43360
43361 if (isset($usageList[$name])) {
43362 foreach ($usageList[$name] as $user) {
43363 $weight -= 1 - $computeImportance($user);
43364 }
43365 }
43366
43367 unset($computing[$name]);
43368 $computed[$name] = $weight;
43369
43370 return $weight;
43371 };
43372
43373 $weightList = array();
43374
43375 foreach ($packages as $name => $package) {
43376 $weight = $computeImportance($name);
43377 $weightList[$name] = $weight;
43378 }
43379
43380 $stable_sort = function (&$array) {
43381 static $transform, $restore;
43382
43383 $i = 0;
43384
43385 if (!$transform) {
43386 $transform = function (&$v, $k) use (&$i) {
43387 $v = array($v, ++$i, $k, $v);
43388 };
43389
43390 $restore = function (&$v) {
43391 $v = $v[3];
43392 };
43393 }
43394
43395 array_walk($array, $transform);
43396 asort($array);
43397 array_walk($array, $restore);
43398 };
43399
43400 $stable_sort($weightList);
43401
43402 $sortedPackages = array();
43403
43404 foreach (array_keys($weightList) as $name) {
43405 $sortedPackages[] = $packages[$name];
43406 }
43407 return $sortedPackages;
43408 }
43409 }
43410 <?php
43411
43412
43413
43414
43415
43416
43417
43418
43419
43420
43421
43422 namespace Composer\Util;
43423
43424 use Composer\IO\IOInterface;
43425 use Symfony\Component\Process\Process;
43426
43427
43428
43429
43430 class Perforce
43431 {
43432 protected $path;
43433 protected $p4Depot;
43434 protected $p4Client;
43435 protected $p4User;
43436 protected $p4Password;
43437 protected $p4Port;
43438 protected $p4Stream;
43439 protected $p4ClientSpec;
43440 protected $p4DepotType;
43441 protected $p4Branch;
43442 protected $process;
43443 protected $uniquePerforceClientName;
43444 protected $windowsFlag;
43445 protected $commandResult;
43446
43447 protected $io;
43448
43449 protected $filesystem;
43450
43451 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
43452 {
43453 $this->windowsFlag = $isWindows;
43454 $this->p4Port = $port;
43455 $this->initializePath($path);
43456 $this->process = $process;
43457 $this->initialize($repoConfig);
43458 $this->io = $io;
43459 }
43460
43461 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
43462 {
43463 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
43464 }
43465
43466 public static function checkServerExists($url, ProcessExecutor $processExecutor)
43467 {
43468 $output = null;
43469
43470 return 0 === $processExecutor->execute('p4 -p ' . ProcessExecutor::escape($url) . ' info -s', $output);
43471 }
43472
43473 public function initialize($repoConfig)
43474 {
43475 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
43476 if (!$repoConfig) {
43477 return;
43478 }
43479 if (isset($repoConfig['unique_perforce_client_name'])) {
43480 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
43481 }
43482
43483 if (isset($repoConfig['depot'])) {
43484 $this->p4Depot = $repoConfig['depot'];
43485 }
43486 if (isset($repoConfig['branch'])) {
43487 $this->p4Branch = $repoConfig['branch'];
43488 }
43489 if (isset($repoConfig['p4user'])) {
43490 $this->p4User = $repoConfig['p4user'];
43491 } else {
43492 $this->p4User = $this->getP4variable('P4USER');
43493 }
43494 if (isset($repoConfig['p4password'])) {
43495 $this->p4Password = $repoConfig['p4password'];
43496 }
43497 }
43498
43499 public function initializeDepotAndBranch($depot, $branch)
43500 {
43501 if (isset($depot)) {
43502 $this->p4Depot = $depot;
43503 }
43504 if (isset($branch)) {
43505 $this->p4Branch = $branch;
43506 }
43507 }
43508
43509 public function generateUniquePerforceClientName()
43510 {
43511 return gethostname() . "_" . time();
43512 }
43513
43514 public function cleanupClientSpec()
43515 {
43516 $client = $this->getClient();
43517 $task = 'client -d ' . ProcessExecutor::escape($client);
43518 $useP4Client = false;
43519 $command = $this->generateP4Command($task, $useP4Client);
43520 $this->executeCommand($command);
43521 $clientSpec = $this->getP4ClientSpec();
43522 $fileSystem = $this->getFilesystem();
43523 $fileSystem->remove($clientSpec);
43524 }
43525
43526 protected function executeCommand($command)
43527 {
43528 $this->commandResult = '';
43529
43530 return $this->process->execute($command, $this->commandResult);
43531 }
43532
43533 public function getClient()
43534 {
43535 if (!isset($this->p4Client)) {
43536 $cleanStreamName = str_replace(array('//', '/', '@'), array('', '_', ''), $this->getStream());
43537 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
43538 }
43539
43540 return $this->p4Client;
43541 }
43542
43543 protected function getPath()
43544 {
43545 return $this->path;
43546 }
43547
43548 public function initializePath($path)
43549 {
43550 $this->path = $path;
43551 $fs = $this->getFilesystem();
43552 $fs->ensureDirectoryExists($path);
43553 }
43554
43555 protected function getPort()
43556 {
43557 return $this->p4Port;
43558 }
43559
43560 public function setStream($stream)
43561 {
43562 $this->p4Stream = $stream;
43563 $index = strrpos($stream, '/');
43564
43565  if ($index > 2) {
43566 $this->p4DepotType = 'stream';
43567 }
43568 }
43569
43570 public function isStream()
43571 {
43572 return (strcmp($this->p4DepotType, 'stream') === 0);
43573 }
43574
43575 public function getStream()
43576 {
43577 if (!isset($this->p4Stream)) {
43578 if ($this->isStream()) {
43579 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
43580 } else {
43581 $this->p4Stream = '//' . $this->p4Depot;
43582 }
43583 }
43584
43585 return $this->p4Stream;
43586 }
43587
43588 public function getStreamWithoutLabel($stream)
43589 {
43590 $index = strpos($stream, '@');
43591 if ($index === false) {
43592 return $stream;
43593 }
43594
43595 return substr($stream, 0, $index);
43596 }
43597
43598 public function getP4ClientSpec()
43599 {
43600 return $this->path . '/' . $this->getClient() . '.p4.spec';
43601 }
43602
43603 public function getUser()
43604 {
43605 return $this->p4User;
43606 }
43607
43608 public function setUser($user)
43609 {
43610 $this->p4User = $user;
43611 }
43612
43613 public function queryP4User()
43614 {
43615 $this->getUser();
43616 if (strlen($this->p4User) > 0) {
43617 return;
43618 }
43619 $this->p4User = $this->getP4variable('P4USER');
43620 if (strlen($this->p4User) > 0) {
43621 return;
43622 }
43623 $this->p4User = $this->io->ask('Enter P4 User:');
43624 if ($this->windowsFlag) {
43625 $command = 'p4 set P4USER=' . $this->p4User;
43626 } else {
43627 $command = 'export P4USER=' . $this->p4User;
43628 }
43629 $this->executeCommand($command);
43630 }
43631
43632 protected function getP4variable($name)
43633 {
43634 if ($this->windowsFlag) {
43635 $command = 'p4 set';
43636 $this->executeCommand($command);
43637 $result = trim($this->commandResult);
43638 $resArray = explode(PHP_EOL, $result);
43639 foreach ($resArray as $line) {
43640 $fields = explode('=', $line);
43641 if (strcmp($name, $fields[0]) == 0) {
43642 $index = strpos($fields[1], ' ');
43643 if ($index === false) {
43644 $value = $fields[1];
43645 } else {
43646 $value = substr($fields[1], 0, $index);
43647 }
43648 $value = trim($value);
43649
43650 return $value;
43651 }
43652 }
43653
43654 return null;
43655 }
43656
43657 $command = 'echo $' . $name;
43658 $this->executeCommand($command);
43659 $result = trim($this->commandResult);
43660
43661 return $result;
43662 }
43663
43664 public function queryP4Password()
43665 {
43666 if (isset($this->p4Password)) {
43667 return $this->p4Password;
43668 }
43669 $password = $this->getP4variable('P4PASSWD');
43670 if (strlen($password) <= 0) {
43671 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
43672 }
43673 $this->p4Password = $password;
43674
43675 return $password;
43676 }
43677
43678 public function generateP4Command($command, $useClient = true)
43679 {
43680 $p4Command = 'p4 ';
43681 $p4Command .= '-u ' . $this->getUser() . ' ';
43682 if ($useClient) {
43683 $p4Command .= '-c ' . $this->getClient() . ' ';
43684 }
43685 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ' . $command;
43686
43687 return $p4Command;
43688 }
43689
43690 public function isLoggedIn()
43691 {
43692 $command = $this->generateP4Command('login -s', false);
43693 $exitCode = $this->executeCommand($command);
43694 if ($exitCode) {
43695 $errorOutput = $this->process->getErrorOutput();
43696 $index = strpos($errorOutput, $this->getUser());
43697 if ($index === false) {
43698 $index = strpos($errorOutput, 'p4');
43699 if ($index === false) {
43700 return false;
43701 }
43702 throw new \Exception('p4 command not found in path: ' . $errorOutput);
43703 }
43704 throw new \Exception('Invalid user name: ' . $this->getUser());
43705 }
43706
43707 return true;
43708 }
43709
43710 public function connectClient()
43711 {
43712 $p4CreateClientCommand = $this->generateP4Command(
43713 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
43714 );
43715 $this->executeCommand($p4CreateClientCommand);
43716 }
43717
43718 public function syncCodeBase($sourceReference)
43719 {
43720 $prevDir = getcwd();
43721 chdir($this->path);
43722 $p4SyncCommand = $this->generateP4Command('sync -f ');
43723 if (null !== $sourceReference) {
43724 $p4SyncCommand .= '@' . $sourceReference;
43725 }
43726 $this->executeCommand($p4SyncCommand);
43727 chdir($prevDir);
43728 }
43729
43730 public function writeClientSpecToFile($spec)
43731 {
43732 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
43733 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
43734 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
43735 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
43736 fwrite($spec, 'Description:' . PHP_EOL);
43737 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
43738 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
43739 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
43740 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
43741 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
43742 if ($this->isStream()) {
43743 fwrite($spec, 'Stream:' . PHP_EOL);
43744 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
43745 } else {
43746 fwrite(
43747 $spec,
43748 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
43749 );
43750 }
43751 }
43752
43753 public function writeP4ClientSpec()
43754 {
43755 $clientSpec = $this->getP4ClientSpec();
43756 $spec = fopen($clientSpec, 'w');
43757 try {
43758 $this->writeClientSpecToFile($spec);
43759 } catch (\Exception $e) {
43760 fclose($spec);
43761 throw $e;
43762 }
43763 fclose($spec);
43764 }
43765
43766 protected function read($pipe, $name)
43767 {
43768 if (feof($pipe)) {
43769 return;
43770 }
43771 $line = fgets($pipe);
43772 while ($line !== false) {
43773 $line = fgets($pipe);
43774 }
43775 }
43776
43777 public function windowsLogin($password)
43778 {
43779 $command = $this->generateP4Command(' login -a');
43780
43781
43782  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
43783 $process = Process::fromShellCommandline($command, null, null, $password);
43784 } else {
43785 $process = new Process($command, null, null, $password);
43786 }
43787
43788 return $process->run();
43789 }
43790
43791 public function p4Login()
43792 {
43793 $this->queryP4User();
43794 if (!$this->isLoggedIn()) {
43795 $password = $this->queryP4Password();
43796 if ($this->windowsFlag) {
43797 $this->windowsLogin($password);
43798 } else {
43799 $command = 'echo ' . ProcessExecutor::escape($password) . ' | ' . $this->generateP4Command(' login -a', false);
43800 $exitCode = $this->executeCommand($command);
43801 $result = trim($this->commandResult);
43802 if ($exitCode) {
43803 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
43804 }
43805 }
43806 }
43807 }
43808
43809 public function getComposerInformation($identifier)
43810 {
43811 $composerFileContent = $this->getFileContent('composer.json', $identifier);
43812
43813 if (!$composerFileContent) {
43814 return;
43815 }
43816
43817 return json_decode($composerFileContent, true);
43818 }
43819
43820 public function getFileContent($file, $identifier)
43821 {
43822 $path = $this->getFilePath($file, $identifier);
43823
43824 $command = $this->generateP4Command(' print ' . ProcessExecutor::escape($path));
43825 $this->executeCommand($command);
43826 $result = $this->commandResult;
43827
43828 if (!trim($result)) {
43829 return null;
43830 }
43831
43832 return $result;
43833 }
43834
43835 public function getFilePath($file, $identifier)
43836 {
43837 $index = strpos($identifier, '@');
43838 if ($index === false) {
43839 $path = $identifier. '/' . $file;
43840
43841 return $path;
43842 }
43843
43844 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
43845 $command = $this->generateP4Command(' files ' . ProcessExecutor::escape($path), false);
43846 $this->executeCommand($command);
43847 $result = $this->commandResult;
43848 $index2 = strpos($result, 'no such file(s).');
43849 if ($index2 === false) {
43850 $index3 = strpos($result, 'change');
43851 if ($index3 !== false) {
43852 $phrase = trim(substr($result, $index3));
43853 $fields = explode(' ', $phrase);
43854
43855 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
43856 }
43857 }
43858
43859 return null;
43860 }
43861
43862 public function getBranches()
43863 {
43864 $possibleBranches = array();
43865 if (!$this->isStream()) {
43866 $possibleBranches[$this->p4Branch] = $this->getStream();
43867 } else {
43868 $command = $this->generateP4Command('streams '.ProcessExecutor::escape('//' . $this->p4Depot . '/...'));
43869 $this->executeCommand($command);
43870 $result = $this->commandResult;
43871 $resArray = explode(PHP_EOL, $result);
43872 foreach ($resArray as $line) {
43873 $resBits = explode(' ', $line);
43874 if (count($resBits) > 4) {
43875 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
43876 $possibleBranches[$branch] = $resBits[1];
43877 }
43878 }
43879 }
43880 $command = $this->generateP4Command('changes '. ProcessExecutor::escape($this->getStream() . '/...'), false);
43881 $this->executeCommand($command);
43882 $result = $this->commandResult;
43883 $resArray = explode(PHP_EOL, $result);
43884 $lastCommit = $resArray[0];
43885 $lastCommitArr = explode(' ', $lastCommit);
43886 $lastCommitNum = $lastCommitArr[1];
43887
43888 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
43889
43890 return $branches;
43891 }
43892
43893 public function getTags()
43894 {
43895 $command = $this->generateP4Command('labels');
43896 $this->executeCommand($command);
43897 $result = $this->commandResult;
43898 $resArray = explode(PHP_EOL, $result);
43899 $tags = array();
43900 foreach ($resArray as $line) {
43901 if (strpos($line, 'Label') !== false) {
43902 $fields = explode(' ', $line);
43903 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
43904 }
43905 }
43906
43907 return $tags;
43908 }
43909
43910 public function checkStream()
43911 {
43912 $command = $this->generateP4Command('depots', false);
43913 $this->executeCommand($command);
43914 $result = $this->commandResult;
43915 $resArray = explode(PHP_EOL, $result);
43916 foreach ($resArray as $line) {
43917 if (strpos($line, 'Depot') !== false) {
43918 $fields = explode(' ', $line);
43919 if (strcmp($this->p4Depot, $fields[1]) === 0) {
43920 $this->p4DepotType = $fields[3];
43921
43922 return $this->isStream();
43923 }
43924 }
43925 }
43926
43927 return false;
43928 }
43929
43930
43931
43932
43933
43934 protected function getChangeList($reference)
43935 {
43936 $index = strpos($reference, '@');
43937 if ($index === false) {
43938 return null;
43939 }
43940 $label = substr($reference, $index);
43941 $command = $this->generateP4Command(' changes -m1 ' . ProcessExecutor::escape($label));
43942 $this->executeCommand($command);
43943 $changes = $this->commandResult;
43944 if (strpos($changes, 'Change') !== 0) {
43945 return null;
43946 }
43947 $fields = explode(' ', $changes);
43948
43949 return $fields[1];
43950 }
43951
43952
43953
43954
43955
43956
43957 public function getCommitLogs($fromReference, $toReference)
43958 {
43959 $fromChangeList = $this->getChangeList($fromReference);
43960 if ($fromChangeList === null) {
43961 return null;
43962 }
43963 $toChangeList = $this->getChangeList($toReference);
43964 if ($toChangeList === null) {
43965 return null;
43966 }
43967 $index = strpos($fromReference, '@');
43968 $main = substr($fromReference, 0, $index) . '/...';
43969 $command = $this->generateP4Command('filelog ' . ProcessExecutor::escape($main . '@' . $fromChangeList. ',' . $toChangeList));
43970 $this->executeCommand($command);
43971
43972 return $this->commandResult;
43973 }
43974
43975 public function getFilesystem()
43976 {
43977 if (empty($this->filesystem)) {
43978 $this->filesystem = new Filesystem($this->process);
43979 }
43980
43981 return $this->filesystem;
43982 }
43983
43984 public function setFilesystem(Filesystem $fs)
43985 {
43986 $this->filesystem = $fs;
43987 }
43988 }
43989 <?php
43990
43991
43992
43993
43994
43995
43996
43997
43998
43999
44000
44001 namespace Composer\Util;
44002
44003
44004
44005
44006
44007
44008 class Platform
44009 {
44010
44011
44012
44013
44014
44015
44016 public static function expandPath($path)
44017 {
44018 if (preg_match('#^~[\\/]#', $path)) {
44019 return self::getUserDirectory() . substr($path, 1);
44020 }
44021
44022 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
44023
44024  if (Platform::isWindows() && $matches['var'] == 'HOME') {
44025 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
44026 }
44027
44028 return getenv($matches['var']) . $matches['path'];
44029 }, $path);
44030 }
44031
44032
44033
44034
44035
44036 public static function getUserDirectory()
44037 {
44038 if (false !== ($home = getenv('HOME'))) {
44039 return $home;
44040 }
44041
44042 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
44043 return $home;
44044 }
44045
44046 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
44047 $info = posix_getpwuid(posix_getuid());
44048
44049 return $info['dir'];
44050 }
44051
44052 throw new \RuntimeException('Could not determine user directory');
44053 }
44054
44055
44056
44057
44058 public static function isWindows()
44059 {
44060 return defined('PHP_WINDOWS_VERSION_BUILD');
44061 }
44062
44063
44064
44065
44066
44067 public static function strlen($str)
44068 {
44069 static $useMbString = null;
44070 if (null === $useMbString) {
44071 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
44072 }
44073
44074 if ($useMbString) {
44075 return mb_strlen($str, '8bit');
44076 }
44077
44078 return strlen($str);
44079 }
44080 }
44081 <?php
44082
44083
44084
44085
44086
44087
44088
44089
44090
44091
44092
44093 namespace Composer\Util;
44094
44095 use Composer\IO\IOInterface;
44096 use Symfony\Component\Process\Process;
44097 use Symfony\Component\Process\ProcessUtils;
44098
44099
44100
44101
44102 class ProcessExecutor
44103 {
44104 protected static $timeout = 300;
44105
44106 protected $captureOutput;
44107 protected $errorOutput;
44108 protected $io;
44109
44110 public function __construct(IOInterface $io = null)
44111 {
44112 $this->io = $io;
44113 }
44114
44115
44116
44117
44118
44119
44120
44121
44122
44123
44124 public function execute($command, &$output = null, $cwd = null)
44125 {
44126 if ($this->io && $this->io->isDebug()) {
44127 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
44128 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
44129 return '://***:***@';
44130 }
44131
44132 return '://'.$m['user'].':***@';
44133 }, $command);
44134 $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand);
44135 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
44136 }
44137
44138
44139  
44140  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
44141 $cwd = realpath(getcwd());
44142 }
44143
44144 $this->captureOutput = func_num_args() > 1;
44145 $this->errorOutput = null;
44146
44147
44148  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
44149 $process = Process::fromShellCommandline($command, $cwd, null, null, static::getTimeout());
44150 } else {
44151 $process = new Process($command, $cwd, null, null, static::getTimeout());
44152 }
44153
44154 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
44155 $process->run($callback);
44156
44157 if ($this->captureOutput && !is_callable($output)) {
44158 $output = $process->getOutput();
44159 }
44160
44161 $this->errorOutput = $process->getErrorOutput();
44162
44163 return $process->getExitCode();
44164 }
44165
44166 public function splitLines($output)
44167 {
44168 $output = trim($output);
44169
44170 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
44171 }
44172
44173
44174
44175
44176
44177
44178 public function getErrorOutput()
44179 {
44180 return $this->errorOutput;
44181 }
44182
44183 public function outputHandler($type, $buffer)
44184 {
44185 if ($this->captureOutput) {
44186 return;
44187 }
44188
44189 if (null === $this->io) {
44190 echo $buffer;
44191
44192 return;
44193 }
44194
44195 if (Process::ERR === $type) {
44196 $this->io->writeError($buffer, false);
44197 } else {
44198 $this->io->write($buffer, false);
44199 }
44200 }
44201
44202 public static function getTimeout()
44203 {
44204 return static::$timeout;
44205 }
44206
44207 public static function setTimeout($timeout)
44208 {
44209 static::$timeout = $timeout;
44210 }
44211
44212
44213
44214
44215
44216
44217
44218
44219 public static function escape($argument)
44220 {
44221 return self::escapeArgument($argument);
44222 }
44223
44224
44225
44226
44227
44228
44229
44230
44231 private static function escapeArgument($argument)
44232 {
44233
44234  
44235  
44236  
44237  if ('\\' === DIRECTORY_SEPARATOR) {
44238 if ('' === $argument) {
44239 return escapeshellarg($argument);
44240 }
44241
44242 $escapedArgument = '';
44243 $quote = false;
44244 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
44245 if ('"' === $part) {
44246 $escapedArgument .= '\\"';
44247 } elseif (self::isSurroundedBy($part, '%')) {
44248
44249  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
44250 } else {
44251
44252  if ('\\' === substr($part, -1)) {
44253 $part .= '\\';
44254 }
44255 $quote = true;
44256 $escapedArgument .= $part;
44257 }
44258 }
44259 if ($quote) {
44260 $escapedArgument = '"'.$escapedArgument.'"';
44261 }
44262
44263 return $escapedArgument;
44264 }
44265
44266 return "'".str_replace("'", "'\\''", $argument)."'";
44267 }
44268
44269 private static function isSurroundedBy($arg, $char)
44270 {
44271 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
44272 }
44273 }
44274 <?php
44275
44276
44277
44278
44279
44280
44281
44282
44283
44284
44285
44286 namespace Composer\Util;
44287
44288 use Composer\Config;
44289 use Composer\Composer;
44290 use Composer\Semver\Constraint\Constraint;
44291 use Composer\Package\Version\VersionParser;
44292 use Composer\IO\IOInterface;
44293 use Composer\Downloader\TransportException;
44294 use Composer\CaBundle\CaBundle;
44295 use Psr\Log\LoggerInterface;
44296
44297
44298
44299
44300
44301
44302 class RemoteFilesystem
44303 {
44304 private $io;
44305 private $config;
44306 private $scheme;
44307 private $bytesMax;
44308 private $originUrl;
44309 private $fileUrl;
44310 private $fileName;
44311 private $retry;
44312 private $progress;
44313 private $lastProgress;
44314 private $options = array();
44315 private $peerCertificateMap = array();
44316 private $disableTls = false;
44317 private $retryAuthFailure;
44318 private $lastHeaders;
44319 private $storeAuth;
44320 private $degradedMode = false;
44321 private $redirects;
44322 private $maxRedirects = 20;
44323
44324
44325
44326
44327
44328
44329
44330
44331
44332 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
44333 {
44334 $this->io = $io;
44335
44336
44337  
44338  if ($disableTls === false) {
44339 $this->options = $this->getTlsDefaults($options);
44340 } else {
44341 $this->disableTls = true;
44342 }
44343
44344
44345  $this->options = array_replace_recursive($this->options, $options);
44346 $this->config = $config;
44347 }
44348
44349
44350
44351
44352
44353
44354
44355
44356
44357
44358
44359
44360 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
44361 {
44362 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
44363 }
44364
44365
44366
44367
44368
44369
44370
44371
44372
44373
44374
44375 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
44376 {
44377 return $this->get($originUrl, $fileUrl, $options, null, $progress);
44378 }
44379
44380
44381
44382
44383
44384
44385 public function getOptions()
44386 {
44387 return $this->options;
44388 }
44389
44390
44391
44392
44393
44394
44395 public function setOptions(array $options)
44396 {
44397 $this->options = array_replace_recursive($this->options, $options);
44398 }
44399
44400
44401
44402
44403
44404
44405 public function isTlsDisabled()
44406 {
44407 return $this->disableTls === true;
44408 }
44409
44410
44411
44412
44413
44414
44415 public function getLastHeaders()
44416 {
44417 return $this->lastHeaders;
44418 }
44419
44420
44421
44422
44423
44424
44425 public function findHeaderValue(array $headers, $name)
44426 {
44427 $value = null;
44428 foreach ($headers as $header) {
44429 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
44430 $value = $match[1];
44431 } elseif (preg_match('{^HTTP/}i', $header)) {
44432
44433  
44434  $value = null;
44435 }
44436 }
44437
44438 return $value;
44439 }
44440
44441
44442
44443
44444
44445 public function findStatusCode(array $headers)
44446 {
44447 $value = null;
44448 foreach ($headers as $header) {
44449 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
44450
44451  
44452  $value = (int) $match[1];
44453 }
44454 }
44455
44456 return $value;
44457 }
44458
44459
44460
44461
44462
44463 public function findStatusMessage(array $headers)
44464 {
44465 $value = null;
44466 foreach ($headers as $header) {
44467 if (preg_match('{^HTTP/\S+ \d+}i', $header)) {
44468
44469  
44470  $value = $header;
44471 }
44472 }
44473
44474 return $value;
44475 }
44476
44477
44478
44479
44480
44481
44482
44483
44484
44485
44486
44487
44488
44489
44490
44491 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
44492 {
44493 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
44494 $originUrl = 'github.com';
44495 }
44496
44497
44498  
44499  if (
44500 $this->config
44501 && is_array($this->config->get('gitlab-domains'))
44502 && false === strpos($originUrl, '/')
44503 && !in_array($originUrl, $this->config->get('gitlab-domains'))
44504 ) {
44505 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
44506 if (0 === strpos($gitlabDomain, $originUrl)) {
44507 $originUrl = $gitlabDomain;
44508 break;
44509 }
44510 }
44511 unset($gitlabDomain);
44512 }
44513
44514 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
44515 $this->bytesMax = 0;
44516 $this->originUrl = $originUrl;
44517 $this->fileUrl = $fileUrl;
44518 $this->fileName = $fileName;
44519 $this->progress = $progress;
44520 $this->lastProgress = null;
44521 $this->retryAuthFailure = true;
44522 $this->lastHeaders = array();
44523 $this->redirects = 1; 
44524
44525
44526  if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
44527 $this->io->setAuthentication($originUrl, rawurldecode($match[1]), rawurldecode($match[2]));
44528 }
44529
44530 $tempAdditionalOptions = $additionalOptions;
44531 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
44532 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
44533
44534 unset($tempAdditionalOptions['retry-auth-failure']);
44535 }
44536
44537 $isRedirect = false;
44538 if (isset($tempAdditionalOptions['redirects'])) {
44539 $this->redirects = $tempAdditionalOptions['redirects'];
44540 $isRedirect = true;
44541
44542 unset($tempAdditionalOptions['redirects']);
44543 }
44544
44545 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
44546 unset($tempAdditionalOptions);
44547
44548 $origFileUrl = $fileUrl;
44549
44550 if (isset($options['github-token'])) {
44551
44552  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
44553 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
44554 }
44555 unset($options['github-token']);
44556 }
44557
44558 if (isset($options['gitlab-token'])) {
44559 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
44560 unset($options['gitlab-token']);
44561 }
44562
44563 if (isset($options['http'])) {
44564 $options['http']['ignore_errors'] = true;
44565 }
44566
44567 if ($this->degradedMode && substr($fileUrl, 0, 26) === 'http://repo.packagist.org/') {
44568
44569  $fileUrl = 'http://' . gethostbyname('repo.packagist.org') . substr($fileUrl, 20);
44570 $degradedPackagist = true;
44571 }
44572
44573 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
44574
44575 $actualContextOptions = stream_context_get_options($ctx);
44576 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
44577 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $this->stripCredentialsFromUrl($origFileUrl) . $usingProxy, true, IOInterface::DEBUG);
44578 unset($origFileUrl, $actualContextOptions);
44579
44580
44581  if ((!preg_match('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
44582 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
44583 }
44584
44585 if ($this->progress && !$isRedirect) {
44586 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
44587 }
44588
44589 $errorMessage = '';
44590 $errorCode = 0;
44591 $result = false;
44592 set_error_handler(function ($code, $msg) use (&$errorMessage) {
44593 if ($errorMessage) {
44594 $errorMessage .= "\n";
44595 }
44596 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
44597
44598 return true;
44599 });
44600 try {
44601 $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header);
44602
44603 if (!empty($http_response_header[0])) {
44604 $statusCode = $this->findStatusCode($http_response_header);
44605 if ($statusCode >= 400 && $this->findHeaderValue($http_response_header, 'content-type') === 'application/json') {
44606 self::outputWarnings($this->io, $originUrl, json_decode($result, true));
44607 }
44608
44609 if (in_array($statusCode, array(401, 403)) && $this->retryAuthFailure) {
44610 $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), null, $http_response_header);
44611 }
44612 }
44613
44614 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
44615 if ($contentLength && Platform::strlen($result) < $contentLength) {
44616
44617  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
44618 $e->setHeaders($http_response_header);
44619 $e->setStatusCode($this->findStatusCode($http_response_header));
44620 $e->setResponse($result);
44621 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
44622
44623 throw $e;
44624 }
44625
44626 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
44627
44628  $params = stream_context_get_params($ctx);
44629 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
44630 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
44631
44632
44633  if ($expectedPeerFingerprint !== $peerFingerprint) {
44634 throw new TransportException('Peer fingerprint did not match');
44635 }
44636 }
44637 } catch (\Exception $e) {
44638 if ($e instanceof TransportException && !empty($http_response_header[0])) {
44639 $e->setHeaders($http_response_header);
44640 $e->setStatusCode($this->findStatusCode($http_response_header));
44641 }
44642 if ($e instanceof TransportException && $result !== false) {
44643 $e->setResponse($result);
44644 }
44645 $result = false;
44646 }
44647 if ($errorMessage && !filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
44648 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
44649 }
44650 restore_error_handler();
44651 if (isset($e) && !$this->retry) {
44652 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
44653 $this->degradedMode = true;
44654 $this->io->writeError('');
44655 $this->io->writeError(array(
44656 '<error>'.$e->getMessage().'</error>',
44657 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
44658 ));
44659
44660 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44661 }
44662
44663 throw $e;
44664 }
44665
44666 $statusCode = null;
44667 $contentType = null;
44668 $locationHeader = null;
44669 if (!empty($http_response_header[0])) {
44670 $statusCode = $this->findStatusCode($http_response_header);
44671 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
44672 $locationHeader = $this->findHeaderValue($http_response_header, 'location');
44673 }
44674
44675
44676  if ($originUrl === 'bitbucket.org'
44677 && !$this->isPublicBitBucketDownload($fileUrl)
44678 && substr($fileUrl, -4) === '.zip'
44679 && (!$locationHeader || substr($locationHeader, -4) !== '.zip')
44680 && $contentType && preg_match('{^text/html\b}i', $contentType)
44681 ) {
44682 $result = false;
44683 if ($this->retryAuthFailure) {
44684 $this->promptAuthAndRetry(401);
44685 }
44686 }
44687
44688
44689  if ($statusCode === 404
44690 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
44691 && false !== strpos($fileUrl, 'archive.zip')
44692 ) {
44693 $result = false;
44694 if ($this->retryAuthFailure) {
44695 $this->promptAuthAndRetry(401);
44696 }
44697 }
44698
44699
44700  $hasFollowedRedirect = false;
44701 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
44702 $hasFollowedRedirect = true;
44703 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
44704 }
44705
44706
44707  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
44708 if (!$this->retry) {
44709 if ($this->progress && !$this->retry && !$isRedirect) {
44710 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
44711 }
44712
44713 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
44714 $e->setHeaders($http_response_header);
44715 $e->setResponse($result);
44716 $e->setStatusCode($statusCode);
44717 throw $e;
44718 }
44719 $result = false;
44720 }
44721
44722 if ($this->progress && !$this->retry && !$isRedirect) {
44723 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
44724 }
44725
44726
44727  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
44728 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
44729 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
44730
44731 if ($decode) {
44732 try {
44733 if (PHP_VERSION_ID >= 50400) {
44734 $result = zlib_decode($result);
44735 } else {
44736
44737  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
44738 }
44739
44740 if (!$result) {
44741 throw new TransportException('Failed to decode zlib stream');
44742 }
44743 } catch (\Exception $e) {
44744 if ($this->degradedMode) {
44745 throw $e;
44746 }
44747
44748 $this->degradedMode = true;
44749 $this->io->writeError(array(
44750 '',
44751 '<error>Failed to decode response: '.$e->getMessage().'</error>',
44752 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
44753 ));
44754
44755 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44756 }
44757 }
44758 }
44759
44760
44761  if (false !== $result && null !== $fileName && !$isRedirect) {
44762 if ('' === $result) {
44763 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
44764 }
44765
44766 $errorMessage = '';
44767 set_error_handler(function ($code, $msg) use (&$errorMessage) {
44768 if ($errorMessage) {
44769 $errorMessage .= "\n";
44770 }
44771 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
44772
44773 return true;
44774 });
44775 $result = (bool) file_put_contents($fileName, $result);
44776 restore_error_handler();
44777 if (false === $result) {
44778 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
44779 }
44780 }
44781
44782
44783  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
44784
44785  
44786  
44787  
44788  
44789  
44790  
44791  
44792  
44793  
44794  
44795  
44796  
44797  
44798  
44799  
44800  if (CaBundle::isOpensslParseSafe()) {
44801 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
44802
44803 if ($certDetails) {
44804 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
44805
44806 $this->retry = true;
44807 }
44808 } else {
44809 $this->io->writeError('');
44810 $this->io->writeError(sprintf(
44811 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
44812 PHP_VERSION
44813 ));
44814 }
44815 }
44816
44817 if ($this->retry) {
44818 $this->retry = false;
44819
44820 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44821
44822 if ($this->storeAuth && $this->config) {
44823 $authHelper = new AuthHelper($this->io, $this->config);
44824 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
44825 $this->storeAuth = false;
44826 }
44827
44828 return $result;
44829 }
44830
44831 if (false === $result) {
44832 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
44833 if (!empty($http_response_header[0])) {
44834 $e->setHeaders($http_response_header);
44835 }
44836
44837 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
44838 $this->degradedMode = true;
44839 $this->io->writeError('');
44840 $this->io->writeError(array(
44841 '<error>'.$e->getMessage().'</error>',
44842 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
44843 ));
44844
44845 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
44846 }
44847
44848 throw $e;
44849 }
44850
44851 if (!empty($http_response_header[0])) {
44852 $this->lastHeaders = $http_response_header;
44853 }
44854
44855 return $result;
44856 }
44857
44858
44859
44860
44861
44862
44863
44864
44865
44866
44867 protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null)
44868 {
44869 try {
44870 $e = null;
44871 $result = file_get_contents($fileUrl, false, $context);
44872 } catch (\Throwable $e) {
44873 } catch (\Exception $e) {
44874 }
44875
44876 $responseHeaders = isset($http_response_header) ? $http_response_header : array();
44877
44878 if (null !== $e) {
44879 throw $e;
44880 }
44881
44882 return $result;
44883 }
44884
44885
44886
44887
44888
44889
44890
44891
44892
44893
44894
44895
44896 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
44897 {
44898 switch ($notificationCode) {
44899 case STREAM_NOTIFY_FAILURE:
44900 if (400 === $messageCode) {
44901
44902  
44903  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
44904 }
44905 break;
44906
44907 case STREAM_NOTIFY_FILE_SIZE_IS:
44908 $this->bytesMax = $bytesMax;
44909 break;
44910
44911 case STREAM_NOTIFY_PROGRESS:
44912 if ($this->bytesMax > 0 && $this->progress) {
44913 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
44914
44915 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
44916 $this->lastProgress = $progression;
44917 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
44918 }
44919 }
44920 break;
44921
44922 default:
44923 break;
44924 }
44925 }
44926
44927 protected function promptAuthAndRetry($httpStatus, $reason = null, $warning = null, $headers = array())
44928 {
44929 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
44930 $gitHubUtil = new GitHub($this->io, $this->config, null);
44931 $message = "\n";
44932
44933 $rateLimited = $gitHubUtil->isRateLimited($headers);
44934 if ($rateLimited) {
44935 $rateLimit = $gitHubUtil->getRateLimit($headers);
44936 if ($this->io->hasAuthentication($this->originUrl)) {
44937 $message = 'Review your configured GitHub OAuth token or enter a new one to go over the API rate limit.';
44938 } else {
44939 $message = 'Create a GitHub OAuth token to go over the API rate limit.';
44940 }
44941
44942 $message = sprintf(
44943 '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.',
44944 $rateLimit['limit'],
44945 $rateLimit['reset']
44946 )."\n";
44947 } else {
44948 $message .= 'Could not fetch '.$this->fileUrl.', please ';
44949 if ($this->io->hasAuthentication($this->originUrl)) {
44950 $message .= 'review your configured GitHub OAuth token or enter a new one to access private repos';
44951 } else {
44952 $message .= 'create a GitHub OAuth token to access private repos';
44953 }
44954 }
44955
44956 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
44957 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
44958 ) {
44959 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
44960 }
44961 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
44962 $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');
44963 $gitLabUtil = new GitLab($this->io, $this->config, null);
44964
44965 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && in_array($auth['password'], array('gitlab-ci-token', 'private-token'), true)) {
44966 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
44967 }
44968
44969 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
44970 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
44971 ) {
44972 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
44973 }
44974 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
44975 $askForOAuthToken = true;
44976 if ($this->io->hasAuthentication($this->originUrl)) {
44977 $auth = $this->io->getAuthentication($this->originUrl);
44978 if ($auth['username'] !== 'x-token-auth') {
44979 $bitbucketUtil = new Bitbucket($this->io, $this->config);
44980 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
44981 if (!empty($accessToken)) {
44982 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
44983 $askForOAuthToken = false;
44984 }
44985 } else {
44986 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
44987 }
44988 }
44989
44990 if ($askForOAuthToken) {
44991 $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');
44992 $bitBucketUtil = new Bitbucket($this->io, $this->config);
44993 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
44994 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
44995 ) {
44996 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
44997 }
44998 }
44999 } else {
45000
45001  if ($httpStatus === 404) {
45002 return;
45003 }
45004
45005
45006  if (!$this->io->isInteractive()) {
45007 if ($httpStatus === 401) {
45008 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
45009 }
45010 if ($httpStatus === 403) {
45011 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
45012 }
45013
45014 throw new TransportException($message, $httpStatus);
45015 }
45016
45017  if ($this->io->hasAuthentication($this->originUrl)) {
45018 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
45019 }
45020
45021 $this->io->writeError('    Authentication required (<info>'.$this->originUrl.'</info>):');
45022 $username = $this->io->ask('      Username: ');
45023 $password = $this->io->askAndHideAnswer('      Password: ');
45024 $this->io->setAuthentication($this->originUrl, $username, $password);
45025 $this->storeAuth = $this->config->get('store-auths');
45026 }
45027
45028 $this->retry = true;
45029 throw new TransportException('RETRY');
45030 }
45031
45032 protected function getOptionsForUrl($originUrl, $additionalOptions)
45033 {
45034 $tlsOptions = array();
45035
45036
45037  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
45038 $host = parse_url($this->fileUrl, PHP_URL_HOST);
45039
45040 if (PHP_VERSION_ID < 50304) {
45041
45042  
45043  
45044  
45045
45046 if ($host === 'github.com' || $host === 'api.github.com') {
45047 $host = '*.github.com';
45048 }
45049 }
45050
45051 $tlsOptions['ssl']['CN_match'] = $host;
45052 $tlsOptions['ssl']['SNI_server_name'] = $host;
45053
45054 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
45055
45056 if (isset($this->peerCertificateMap[$urlAuthority])) {
45057
45058  $certMap = $this->peerCertificateMap[$urlAuthority];
45059
45060 $this->io->writeError('', true, IOInterface::DEBUG);
45061 $this->io->writeError(sprintf(
45062 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
45063 $certMap['cn'],
45064 $urlAuthority
45065 ), true, IOInterface::DEBUG);
45066
45067 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
45068 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
45069 } elseif (!CaBundle::isOpensslParseSafe() && $host === 'repo.packagist.org') {
45070
45071  $tlsOptions['ssl']['CN_match'] = 'packagist.org';
45072 }
45073 }
45074
45075 $headers = array();
45076
45077 if (extension_loaded('zlib')) {
45078 $headers[] = 'Accept-Encoding: gzip';
45079 }
45080
45081 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
45082 if (!$this->degradedMode) {
45083
45084  
45085  $options['http']['protocol_version'] = 1.1;
45086 $headers[] = 'Connection: close';
45087 }
45088
45089 if ($this->io->hasAuthentication($originUrl)) {
45090 $auth = $this->io->getAuthentication($originUrl);
45091 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
45092 $options['github-token'] = $auth['username'];
45093 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
45094 if ($auth['password'] === 'oauth2') {
45095 $headers[] = 'Authorization: Bearer '.$auth['username'];
45096 } elseif ($auth['password'] === 'private-token' || $auth['password'] === 'gitlab-ci-token') {
45097 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
45098 }
45099 } elseif ('bitbucket.org' === $originUrl
45100 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
45101 ) {
45102 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
45103 $headers[] = 'Authorization: Bearer ' . $auth['password'];
45104 }
45105 } else {
45106 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
45107 $headers[] = 'Authorization: Basic '.$authStr;
45108 }
45109 }
45110
45111 $options['http']['follow_location'] = 0;
45112
45113 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
45114 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
45115 }
45116 foreach ($headers as $header) {
45117 $options['http']['header'][] = $header;
45118 }
45119
45120 return $options;
45121 }
45122
45123 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
45124 {
45125 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
45126 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
45127
45128  $targetUrl = $locationHeader;
45129 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
45130
45131  $targetUrl = $this->scheme.':'.$locationHeader;
45132 } elseif ('/' === $locationHeader[0]) {
45133
45134  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
45135
45136
45137  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
45138 } else {
45139
45140  
45141  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
45142 }
45143 }
45144
45145 if (!empty($targetUrl)) {
45146 $this->redirects++;
45147
45148 $this->io->writeError('', true, IOInterface::DEBUG);
45149 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $this->stripCredentialsFromUrl($targetUrl)), true, IOInterface::DEBUG);
45150
45151 $additionalOptions['redirects'] = $this->redirects;
45152
45153 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
45154 }
45155
45156 if (!$this->retry) {
45157 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
45158 $e->setHeaders($http_response_header);
45159 $e->setResponse($result);
45160
45161 throw $e;
45162 }
45163
45164 return false;
45165 }
45166
45167
45168
45169
45170
45171
45172 private function getTlsDefaults(array $options)
45173 {
45174 $ciphers = implode(':', array(
45175 'ECDHE-RSA-AES128-GCM-SHA256',
45176 'ECDHE-ECDSA-AES128-GCM-SHA256',
45177 'ECDHE-RSA-AES256-GCM-SHA384',
45178 'ECDHE-ECDSA-AES256-GCM-SHA384',
45179 'DHE-RSA-AES128-GCM-SHA256',
45180 'DHE-DSS-AES128-GCM-SHA256',
45181 'kEDH+AESGCM',
45182 'ECDHE-RSA-AES128-SHA256',
45183 'ECDHE-ECDSA-AES128-SHA256',
45184 'ECDHE-RSA-AES128-SHA',
45185 'ECDHE-ECDSA-AES128-SHA',
45186 'ECDHE-RSA-AES256-SHA384',
45187 'ECDHE-ECDSA-AES256-SHA384',
45188 'ECDHE-RSA-AES256-SHA',
45189 'ECDHE-ECDSA-AES256-SHA',
45190 'DHE-RSA-AES128-SHA256',
45191 'DHE-RSA-AES128-SHA',
45192 'DHE-DSS-AES128-SHA256',
45193 'DHE-RSA-AES256-SHA256',
45194 'DHE-DSS-AES256-SHA',
45195 'DHE-RSA-AES256-SHA',
45196 'AES128-GCM-SHA256',
45197 'AES256-GCM-SHA384',
45198 'AES128-SHA256',
45199 'AES256-SHA256',
45200 'AES128-SHA',
45201 'AES256-SHA',
45202 'AES',
45203 'CAMELLIA',
45204 'DES-CBC3-SHA',
45205 '!aNULL',
45206 '!eNULL',
45207 '!EXPORT',
45208 '!DES',
45209 '!RC4',
45210 '!MD5',
45211 '!PSK',
45212 '!aECDH',
45213 '!EDH-DSS-DES-CBC3-SHA',
45214 '!EDH-RSA-DES-CBC3-SHA',
45215 '!KRB5-DES-CBC3-SHA',
45216 ));
45217
45218
45219
45220
45221
45222
45223
45224 $defaults = array(
45225 'ssl' => array(
45226 'ciphers' => $ciphers,
45227 'verify_peer' => true,
45228 'verify_depth' => 7,
45229 'SNI_enabled' => true,
45230 'capture_peer_cert' => true,
45231 ),
45232 );
45233
45234 if (isset($options['ssl'])) {
45235 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
45236 }
45237
45238 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
45239
45240
45241
45242
45243
45244 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
45245 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
45246
45247 if (is_dir($result)) {
45248 $defaults['ssl']['capath'] = $result;
45249 } else {
45250 $defaults['ssl']['cafile'] = $result;
45251 }
45252 }
45253
45254 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
45255 throw new TransportException('The configured cafile was not valid or could not be read.');
45256 }
45257
45258 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
45259 throw new TransportException('The configured capath was not valid or could not be read.');
45260 }
45261
45262
45263
45264
45265 if (PHP_VERSION_ID >= 50413) {
45266 $defaults['ssl']['disable_compression'] = true;
45267 }
45268
45269 return $defaults;
45270 }
45271
45272
45273
45274
45275
45276
45277 private function getCertificateCnAndFp($url, $options)
45278 {
45279 if (PHP_VERSION_ID >= 50600) {
45280 throw new \BadMethodCallException(sprintf(
45281 '%s must not be used on PHP >= 5.6',
45282 __METHOD__
45283 ));
45284 }
45285
45286 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
45287 'ssl' => array(
45288 'capture_peer_cert' => true,
45289 'verify_peer' => false, 
45290  ), ),
45291 ));
45292
45293
45294  
45295  if (false === $handle = @fopen($url, 'rb', false, $context)) {
45296 return;
45297 }
45298
45299
45300  fclose($handle);
45301 $handle = null;
45302
45303 $params = stream_context_get_params($context);
45304
45305 if (!empty($params['options']['ssl']['peer_certificate'])) {
45306 $peerCertificate = $params['options']['ssl']['peer_certificate'];
45307
45308 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
45309 return array(
45310 'cn' => $commonName,
45311 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
45312 );
45313 }
45314 }
45315 }
45316
45317 private function getUrlAuthority($url)
45318 {
45319 $defaultPorts = array(
45320 'ftp' => 21,
45321 'http' => 80,
45322 'https' => 443,
45323 'ssh2.sftp' => 22,
45324 'ssh2.scp' => 22,
45325 );
45326
45327 $scheme = parse_url($url, PHP_URL_SCHEME);
45328
45329 if (!isset($defaultPorts[$scheme])) {
45330 throw new \InvalidArgumentException(sprintf(
45331 'Could not get default port for unknown scheme: %s',
45332 $scheme
45333 ));
45334 }
45335
45336 $defaultPort = $defaultPorts[$scheme];
45337 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
45338
45339 return parse_url($url, PHP_URL_HOST).':'.$port;
45340 }
45341
45342
45343
45344
45345
45346
45347
45348
45349 private function isPublicBitBucketDownload($urlToBitBucketFile)
45350 {
45351 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
45352 if (strpos($domain, 'bitbucket.org') === false) {
45353
45354  
45355  return true;
45356 }
45357
45358 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
45359
45360
45361  
45362  $pathParts = explode('/', $path);
45363
45364 return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
45365 }
45366
45367 public static function outputWarnings(IOInterface $io, $url, $data)
45368 {
45369 foreach (array('warning', 'info') as $type) {
45370 if (empty($data[$type])) {
45371 continue;
45372 }
45373
45374 if (!empty($data[$type . '-versions'])) {
45375 $versionParser = new VersionParser();
45376 $constraint = $versionParser->parseConstraints($data[$type . '-versions']);
45377 $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion()));
45378 if (!$constraint->matches($composer)) {
45379 continue;
45380 }
45381 }
45382
45383 $io->writeError('<'.$type.'>'.ucfirst($type).' from '.$url.': '.$data[$type].'</'.$type.'>');
45384 }
45385 }
45386
45387 public static function getOrigin($urlOrPath)
45388 {
45389 $hostPort = parse_url($urlOrPath, PHP_URL_HOST);
45390 if (!$hostPort) {
45391 return $urlOrPath;
45392 }
45393 if (parse_url($urlOrPath, PHP_URL_PORT)) {
45394 $hostPort .= ':'.parse_url($urlOrPath, PHP_URL_PORT);
45395 }
45396
45397 return $hostPort;
45398 }
45399
45400 private function stripCredentialsFromUrl($url)
45401 {
45402
45403  
45404  return preg_replace('{([&?]access_token=)[^&]+}', '$1***', $url);
45405 }
45406 }
45407 <?php
45408
45409
45410
45411
45412
45413
45414
45415
45416
45417
45418
45419 namespace Composer\Util;
45420
45421
45422
45423
45424
45425
45426 class Silencer
45427 {
45428
45429
45430
45431 private static $stack = array();
45432
45433
45434
45435
45436
45437
45438
45439 public static function suppress($mask = null)
45440 {
45441 if (!isset($mask)) {
45442 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
45443 }
45444 $old = error_reporting();
45445 self::$stack[] = $old;
45446 error_reporting($old & ~$mask);
45447
45448 return $old;
45449 }
45450
45451
45452
45453
45454 public static function restore()
45455 {
45456 if (!empty(self::$stack)) {
45457 error_reporting(array_pop(self::$stack));
45458 }
45459 }
45460
45461
45462
45463
45464
45465
45466
45467
45468
45469
45470 public static function call($callable )
45471 {
45472 try {
45473 self::suppress();
45474 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
45475 self::restore();
45476
45477 return $result;
45478 } catch (\Exception $e) {
45479
45480  self::restore();
45481 throw $e;
45482 }
45483 }
45484 }
45485 <?php
45486
45487
45488
45489
45490
45491
45492
45493
45494
45495
45496
45497 namespace Composer\Util;
45498
45499 use Composer\Spdx\SpdxLicenses;
45500
45501 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
45502
45503
45504
45505
45506 class SpdxLicense extends SpdxLicenses
45507 {
45508 }
45509 <?php
45510
45511
45512
45513
45514
45515
45516
45517
45518
45519
45520
45521 namespace Composer\Util;
45522
45523 use Composer\Composer;
45524
45525
45526
45527
45528
45529
45530
45531 final class StreamContextFactory
45532 {
45533
45534
45535
45536
45537
45538
45539
45540
45541
45542 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
45543 {
45544 $options = array('http' => array(
45545
45546  'follow_location' => 1,
45547 'max_redirects' => 20,
45548 ));
45549
45550
45551  if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
45552 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
45553 }
45554
45555
45556  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
45557 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
45558 }
45559
45560
45561  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
45562 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
45563 }
45564
45565
45566  if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
45567 $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
45568 if ($pattern->test($url)) {
45569 unset($proxy);
45570 }
45571 }
45572
45573 if (!empty($proxy)) {
45574 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
45575 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
45576
45577 if (isset($proxy['port'])) {
45578 $proxyURL .= ":" . $proxy['port'];
45579 } elseif ('http://' == substr($proxyURL, 0, 7)) {
45580 $proxyURL .= ":80";
45581 } elseif ('https://' == substr($proxyURL, 0, 8)) {
45582 $proxyURL .= ":443";
45583 }
45584
45585
45586  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
45587
45588 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
45589 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
45590 }
45591
45592 $options['http']['proxy'] = $proxyURL;
45593
45594
45595  switch (parse_url($url, PHP_URL_SCHEME)) {
45596 case 'http': 
45597  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
45598 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
45599 $options['http']['request_fulluri'] = true;
45600 }
45601 break;
45602 case 'https': 
45603  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
45604 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
45605 $options['http']['request_fulluri'] = true;
45606 }
45607 break;
45608 }
45609
45610
45611  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
45612 $options['ssl']['SNI_enabled'] = true;
45613 if (PHP_VERSION_ID < 50600) {
45614 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
45615 }
45616 }
45617
45618
45619  if (isset($proxy['user'])) {
45620 $auth = rawurldecode($proxy['user']);
45621 if (isset($proxy['pass'])) {
45622 $auth .= ':' . rawurldecode($proxy['pass']);
45623 }
45624 $auth = base64_encode($auth);
45625
45626
45627  if (isset($defaultOptions['http']['header'])) {
45628 if (is_string($defaultOptions['http']['header'])) {
45629 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
45630 }
45631 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
45632 } else {
45633 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
45634 }
45635 }
45636 }
45637
45638 $options = array_replace_recursive($options, $defaultOptions);
45639
45640 if (isset($options['http']['header'])) {
45641 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
45642 }
45643
45644 if (defined('HHVM_VERSION')) {
45645 $phpVersion = 'HHVM ' . HHVM_VERSION;
45646 } else {
45647 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
45648 }
45649
45650 if (!isset($options['http']['header']) || false === stripos(implode('', $options['http']['header']), 'user-agent')) {
45651 $options['http']['header'][] = sprintf(
45652 'User-Agent: Composer/%s (%s; %s; %s%s)',
45653 Composer::getVersion(),
45654 function_exists('php_uname') ? php_uname('s') : 'Unknown',
45655 function_exists('php_uname') ? php_uname('r') : 'Unknown',
45656 $phpVersion,
45657 getenv('CI') ? '; CI' : ''
45658 );
45659 }
45660
45661 return stream_context_create($options, $defaultParams);
45662 }
45663
45664
45665
45666
45667
45668
45669
45670
45671
45672
45673
45674 private static function fixHttpHeaderField($header)
45675 {
45676 if (!is_array($header)) {
45677 $header = explode("\r\n", $header);
45678 }
45679 uasort($header, function ($el) {
45680 return stripos($el, 'content-type') === 0 ? 1 : -1;
45681 });
45682
45683 return $header;
45684 }
45685 }
45686 <?php
45687
45688
45689
45690
45691
45692
45693
45694
45695
45696
45697
45698 namespace Composer\Util;
45699
45700 use Composer\Config;
45701 use Composer\IO\IOInterface;
45702
45703
45704
45705
45706
45707 class Svn
45708 {
45709 const MAX_QTY_AUTH_TRIES = 5;
45710
45711
45712
45713
45714 protected $credentials;
45715
45716
45717
45718
45719 protected $hasAuth;
45720
45721
45722
45723
45724 protected $io;
45725
45726
45727
45728
45729 protected $url;
45730
45731
45732
45733
45734 protected $cacheCredentials = true;
45735
45736
45737
45738
45739 protected $process;
45740
45741
45742
45743
45744 protected $qtyAuthTries = 0;
45745
45746
45747
45748
45749 protected $config;
45750
45751
45752
45753
45754 private static $version;
45755
45756
45757
45758
45759
45760
45761
45762 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
45763 {
45764 $this->url = $url;
45765 $this->io = $io;
45766 $this->config = $config;
45767 $this->process = $process ?: new ProcessExecutor($io);
45768 }
45769
45770 public static function cleanEnv()
45771 {
45772
45773  putenv("DYLD_LIBRARY_PATH");
45774 unset($_SERVER['DYLD_LIBRARY_PATH']);
45775 }
45776
45777
45778
45779
45780
45781
45782
45783
45784
45785
45786
45787
45788
45789
45790 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
45791 {
45792
45793  $this->config->prohibitUrlByConfig($url, $this->io);
45794
45795 return $this->executeWithAuthRetry($command, $cwd, $url, $path, $verbose);
45796 }
45797
45798
45799
45800
45801
45802
45803
45804
45805
45806
45807
45808
45809
45810 public function executeLocal($command, $path, $cwd = null, $verbose = false)
45811 {
45812
45813  return $this->executeWithAuthRetry($command, $cwd, '', $path, $verbose);
45814 }
45815
45816 private function executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose)
45817 {
45818
45819  $command = $this->getCommand($svnCommand, $url, $path);
45820
45821 $output = null;
45822 $io = $this->io;
45823 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
45824 if ($type !== 'out') {
45825 return;
45826 }
45827 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
45828 return;
45829 }
45830 $output .= $buffer;
45831 if ($verbose) {
45832 $io->writeError($buffer, false);
45833 }
45834 };
45835 $status = $this->process->execute($command, $handler, $cwd);
45836 if (0 === $status) {
45837 return $output;
45838 }
45839
45840 $errorOutput = $this->process->getErrorOutput();
45841 $fullOutput = implode("\n", array($output, $errorOutput));
45842
45843
45844  if (false === stripos($fullOutput, 'Could not authenticate to server:')
45845 && false === stripos($fullOutput, 'authorization failed')
45846 && false === stripos($fullOutput, 'svn: E170001:')
45847 && false === stripos($fullOutput, 'svn: E215004:')) {
45848 throw new \RuntimeException($fullOutput);
45849 }
45850
45851 if (!$this->hasAuth()) {
45852 $this->doAuthDance();
45853 }
45854
45855
45856  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
45857
45858  return $this->executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose);
45859 }
45860
45861 throw new \RuntimeException(
45862 'wrong credentials provided ('.$fullOutput.')'
45863 );
45864 }
45865
45866
45867
45868
45869 public function setCacheCredentials($cacheCredentials)
45870 {
45871 $this->cacheCredentials = $cacheCredentials;
45872 }
45873
45874
45875
45876
45877
45878
45879
45880 protected function doAuthDance()
45881 {
45882
45883  if (!$this->io->isInteractive()) {
45884 throw new \RuntimeException(
45885 'can not ask for authentication in non interactive mode'
45886 );
45887 }
45888
45889 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
45890
45891 $this->hasAuth = true;
45892 $this->credentials['username'] = $this->io->ask("Username: ");
45893 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
45894
45895 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
45896
45897 return $this;
45898 }
45899
45900
45901
45902
45903
45904
45905
45906
45907
45908
45909 protected function getCommand($cmd, $url, $path = null)
45910 {
45911 $cmd = sprintf(
45912 '%s %s%s %s',
45913 $cmd,
45914 '--non-interactive ',
45915 $this->getCredentialString(),
45916 ProcessExecutor::escape($url)
45917 );
45918
45919 if ($path) {
45920 $cmd .= ' ' . ProcessExecutor::escape($path);
45921 }
45922
45923 return $cmd;
45924 }
45925
45926
45927
45928
45929
45930
45931
45932
45933 protected function getCredentialString()
45934 {
45935 if (!$this->hasAuth()) {
45936 return '';
45937 }
45938
45939 return sprintf(
45940 ' %s--username %s --password %s ',
45941 $this->getAuthCache(),
45942 ProcessExecutor::escape($this->getUsername()),
45943 ProcessExecutor::escape($this->getPassword())
45944 );
45945 }
45946
45947
45948
45949
45950
45951
45952
45953 protected function getPassword()
45954 {
45955 if ($this->credentials === null) {
45956 throw new \LogicException("No svn auth detected.");
45957 }
45958
45959 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
45960 }
45961
45962
45963
45964
45965
45966
45967
45968 protected function getUsername()
45969 {
45970 if ($this->credentials === null) {
45971 throw new \LogicException("No svn auth detected.");
45972 }
45973
45974 return $this->credentials['username'];
45975 }
45976
45977
45978
45979
45980
45981
45982 protected function hasAuth()
45983 {
45984 if (null !== $this->hasAuth) {
45985 return $this->hasAuth;
45986 }
45987
45988 if (false === $this->createAuthFromConfig()) {
45989 $this->createAuthFromUrl();
45990 }
45991
45992 return $this->hasAuth;
45993 }
45994
45995
45996
45997
45998
45999
46000 protected function getAuthCache()
46001 {
46002 return $this->cacheCredentials ? '' : '--no-auth-cache ';
46003 }
46004
46005
46006
46007
46008
46009
46010 private function createAuthFromConfig()
46011 {
46012 if (!$this->config->has('http-basic')) {
46013 return $this->hasAuth = false;
46014 }
46015
46016 $authConfig = $this->config->get('http-basic');
46017
46018 $host = parse_url($this->url, PHP_URL_HOST);
46019 if (isset($authConfig[$host])) {
46020 $this->credentials['username'] = $authConfig[$host]['username'];
46021 $this->credentials['password'] = $authConfig[$host]['password'];
46022
46023 return $this->hasAuth = true;
46024 }
46025
46026 return $this->hasAuth = false;
46027 }
46028
46029
46030
46031
46032
46033
46034 private function createAuthFromUrl()
46035 {
46036 $uri = parse_url($this->url);
46037 if (empty($uri['user'])) {
46038 return $this->hasAuth = false;
46039 }
46040
46041 $this->credentials['username'] = $uri['user'];
46042 if (!empty($uri['pass'])) {
46043 $this->credentials['password'] = $uri['pass'];
46044 }
46045
46046 return $this->hasAuth = true;
46047 }
46048
46049
46050
46051
46052
46053
46054 public function binaryVersion()
46055 {
46056 if (!self::$version) {
46057 if (0 === $this->process->execute('svn --version', $output)) {
46058 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match)) {
46059 self::$version = $match[1];
46060 }
46061 }
46062 }
46063
46064 return self::$version;
46065 }
46066 }
46067 <?php
46068
46069
46070
46071
46072
46073
46074
46075
46076
46077
46078
46079 namespace Composer\Util;
46080
46081 use Composer\CaBundle\CaBundle;
46082
46083
46084
46085
46086 final class TlsHelper
46087 {
46088
46089
46090
46091
46092
46093
46094
46095
46096
46097 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
46098 {
46099 $names = self::getCertificateNames($certificate);
46100
46101 if (empty($names)) {
46102 return false;
46103 }
46104
46105 $combinedNames = array_merge($names['san'], array($names['cn']));
46106 $hostname = strtolower($hostname);
46107
46108 foreach ($combinedNames as $certName) {
46109 $matcher = self::certNameMatcher($certName);
46110
46111 if ($matcher && $matcher($hostname)) {
46112 $cn = $names['cn'];
46113
46114 return true;
46115 }
46116 }
46117
46118 return false;
46119 }
46120
46121
46122
46123
46124
46125
46126
46127
46128 public static function getCertificateNames($certificate)
46129 {
46130 if (is_array($certificate)) {
46131 $info = $certificate;
46132 } elseif (CaBundle::isOpensslParseSafe()) {
46133 $info = openssl_x509_parse($certificate, false);
46134 }
46135
46136 if (!isset($info['subject']['commonName'])) {
46137 return null;
46138 }
46139
46140 $commonName = strtolower($info['subject']['commonName']);
46141 $subjectAltNames = array();
46142
46143 if (isset($info['extensions']['subjectAltName'])) {
46144 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
46145 $subjectAltNames = array_filter(array_map(function ($name) {
46146 if (0 === strpos($name, 'DNS:')) {
46147 return strtolower(ltrim(substr($name, 4)));
46148 }
46149
46150 return null;
46151 }, $subjectAltNames));
46152 $subjectAltNames = array_values($subjectAltNames);
46153 }
46154
46155 return array(
46156 'cn' => $commonName,
46157 'san' => $subjectAltNames,
46158 );
46159 }
46160
46161
46162
46163
46164
46165
46166
46167
46168
46169
46170
46171
46172
46173
46174
46175
46176
46177
46178
46179
46180
46181
46182
46183
46184
46185
46186
46187
46188
46189
46190
46191
46192
46193
46194
46195
46196
46197
46198
46199
46200 public static function getCertificateFingerprint($certificate)
46201 {
46202 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
46203 $pubkeypem = $pubkeydetails['key'];
46204
46205  $start = '-----BEGIN PUBLIC KEY-----';
46206 $end = '-----END PUBLIC KEY-----';
46207 $pemtrim = substr($pubkeypem, strpos($pubkeypem, $start) + strlen($start), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
46208 $der = base64_decode($pemtrim);
46209
46210 return sha1($der);
46211 }
46212
46213
46214
46215
46216
46217
46218
46219
46220
46221 public static function isOpensslParseSafe()
46222 {
46223 return CaBundle::isOpensslParseSafe();
46224 }
46225
46226
46227
46228
46229
46230
46231
46232
46233 private static function certNameMatcher($certName)
46234 {
46235 $wildcards = substr_count($certName, '*');
46236
46237 if (0 === $wildcards) {
46238
46239  return function ($hostname) use ($certName) {
46240 return $hostname === $certName;
46241 };
46242 }
46243
46244 if (1 === $wildcards) {
46245 $components = explode('.', $certName);
46246
46247 if (3 > count($components)) {
46248
46249  return;
46250 }
46251
46252 $firstComponent = $components[0];
46253
46254
46255  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
46256 return;
46257 }
46258
46259 $wildcardRegex = preg_quote($certName);
46260 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
46261 $wildcardRegex = "{^{$wildcardRegex}$}";
46262
46263 return function ($hostname) use ($wildcardRegex) {
46264 return 1 === preg_match($wildcardRegex, $hostname);
46265 };
46266 }
46267 }
46268 }
46269 <?php
46270
46271
46272
46273
46274
46275
46276
46277
46278
46279
46280
46281 namespace Composer\Util;
46282
46283 use Composer\Config;
46284
46285
46286
46287
46288 class Url
46289 {
46290 public static function updateDistReference(Config $config, $url, $ref)
46291 {
46292 $host = parse_url($url, PHP_URL_HOST);
46293
46294 if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
46295 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
46296
46297  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
46298 } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
46299
46300  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
46301 } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
46302
46303  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
46304 }
46305 } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
46306 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
46307
46308  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4];
46309 }
46310 } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
46311 if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
46312
46313  $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
46314 }
46315 } elseif (in_array($host, $config->get('github-domains'), true)) {
46316 $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url);
46317 } elseif (in_array($host, $config->get('gitlab-domains'), true)) {
46318 $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url);
46319 }
46320
46321 return $url;
46322 }
46323 }
46324 <?php
46325
46326
46327
46328
46329
46330
46331
46332
46333
46334
46335
46336 namespace Composer\Util;
46337
46338
46339
46340
46341 class Zip
46342 {
46343
46344
46345
46346
46347
46348
46349
46350
46351 public static function getComposerJson($pathToZip)
46352 {
46353 if (!extension_loaded('zip')) {
46354 throw new \RuntimeException('The Zip Util requires PHP\'s zip extension');
46355 }
46356
46357 $zip = new \ZipArchive();
46358 if ($zip->open($pathToZip) !== true) {
46359 return null;
46360 }
46361
46362 if (0 == $zip->numFiles) {
46363 $zip->close();
46364
46365 return null;
46366 }
46367
46368 $foundFileIndex = self::locateFile($zip, 'composer.json');
46369 if (false === $foundFileIndex) {
46370 $zip->close();
46371
46372 return null;
46373 }
46374
46375 $content = null;
46376 $configurationFileName = $zip->getNameIndex($foundFileIndex);
46377 $stream = $zip->getStream($configurationFileName);
46378
46379 if (false !== $stream) {
46380 $content = stream_get_contents($stream);
46381 }
46382
46383 $zip->close();
46384
46385 return $content;
46386 }
46387
46388
46389
46390
46391
46392
46393
46394
46395
46396 private static function locateFile(\ZipArchive $zip, $filename)
46397 {
46398 $indexOfShortestMatch = false;
46399 $lengthOfShortestMatch = -1;
46400
46401 for ($i = 0; $i < $zip->numFiles; $i++) {
46402 $stat = $zip->statIndex($i);
46403 if (strcmp(basename($stat['name']), $filename) === 0) {
46404 $directoryName = dirname($stat['name']);
46405 if ($directoryName === '.') {
46406
46407  
46408  return $i;
46409 }
46410
46411 if (strpos($directoryName, '\\') !== false ||
46412 strpos($directoryName, '/') !== false) {
46413
46414  continue;
46415 }
46416
46417 $length = strlen($stat['name']);
46418 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
46419
46420  $contents = $zip->getFromIndex($i);
46421 if ($contents !== false) {
46422 $indexOfShortestMatch = $i;
46423 $lengthOfShortestMatch = $length;
46424 }
46425 }
46426 }
46427 }
46428
46429 return $indexOfShortestMatch;
46430 }
46431 }
46432 <?php
46433
46434
46435
46436
46437
46438
46439
46440
46441
46442
46443
46444 namespace Composer;
46445
46446 use Symfony\Component\Console\Output\OutputInterface;
46447
46448 trigger_error('The ' . __NAMESPACE__ . '\XdebugHandler class is deprecated, use Composer\XdebugHandler\XdebugHandler instead,', E_USER_DEPRECATED);
46449
46450
46451
46452
46453 class XdebugHandler extends XdebugHandler\XdebugHandler
46454 {
46455 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
46456 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
46457
46458 public function __construct(OutputInterface $output)
46459 {
46460 parent::__construct('composer', '--ansi');
46461 }
46462 }
46463 <?php
46464
46465
46466
46467
46468
46469
46470
46471
46472
46473
46474
46475 function includeIfExists($file)
46476 {
46477 return file_exists($file) ? include $file : false;
46478 }
46479
46480 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
46481 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
46482 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
46483 exit(1);
46484 }
46485
46486 return $loader;
46487 <?php
46488
46489 /*
46490  * This file is part of Composer.
46491  *
46492  * (c) Nils Adermann <naderman@naderman.de>
46493  *     Jordi Boggiano <j.boggiano@seld.be>
46494  *
46495  * For the full copyright and license information, please view the LICENSE
46496  * file that was distributed with this source code.
46497  */
46498
46499 namespace Composer\Autoload;
46500
46501 /**
46502  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
46503  *
46504  *     $loader = new \Composer\Autoload\ClassLoader();
46505  *
46506  *     // register classes with namespaces
46507  *     $loader->add('Symfony\Component', __DIR__.'/component');
46508  *     $loader->add('Symfony',           __DIR__.'/framework');
46509  *
46510  *     // activate the autoloader
46511  *     $loader->register();
46512  *
46513  *     // to enable searching the include path (eg. for PEAR packages)
46514  *     $loader->setUseIncludePath(true);
46515  *
46516  * In this example, if you try to use a class in the Symfony\Component
46517  * namespace or one of its children (Symfony\Component\Console for instance),
46518  * the autoloader will first look for the class under the component/
46519  * directory, and it will then fallback to the framework/ directory if not
46520  * found before giving up.
46521  *
46522  * This class is loosely based on the Symfony UniversalClassLoader.
46523  *
46524  * @author Fabien Potencier <fabien@symfony.com>
46525  * @author Jordi Boggiano <j.boggiano@seld.be>
46526  * @see    http://www.php-fig.org/psr/psr-0/
46527  * @see    http://www.php-fig.org/psr/psr-4/
46528  */
46529 class ClassLoader
46530 {
46531     // PSR-4
46532     private $prefixLengthsPsr4 = array();
46533     private $prefixDirsPsr4 = array();
46534     private $fallbackDirsPsr4 = array();
46535
46536     // PSR-0
46537     private $prefixesPsr0 = array();
46538     private $fallbackDirsPsr0 = array();
46539
46540     private $useIncludePath = false;
46541     private $classMap = array();
46542     private $classMapAuthoritative = false;
46543     private $missingClasses = array();
46544     private $apcuPrefix;
46545
46546     public function getPrefixes()
46547     {
46548         if (!empty($this->prefixesPsr0)) {
46549             return call_user_func_array('array_merge', $this->prefixesPsr0);
46550         }
46551
46552         return array();
46553     }
46554
46555     public function getPrefixesPsr4()
46556     {
46557         return $this->prefixDirsPsr4;
46558     }
46559
46560     public function getFallbackDirs()
46561     {
46562         return $this->fallbackDirsPsr0;
46563     }
46564
46565     public function getFallbackDirsPsr4()
46566     {
46567         return $this->fallbackDirsPsr4;
46568     }
46569
46570     public function getClassMap()
46571     {
46572         return $this->classMap;
46573     }
46574
46575     /**
46576      * @param array $classMap Class to filename map
46577      */
46578     public function addClassMap(array $classMap)
46579     {
46580         if ($this->classMap) {
46581             $this->classMap = array_merge($this->classMap, $classMap);
46582         } else {
46583             $this->classMap = $classMap;
46584         }
46585     }
46586
46587     /**
46588      * Registers a set of PSR-0 directories for a given prefix, either
46589      * appending or prepending to the ones previously set for this prefix.
46590      *
46591      * @param string       $prefix  The prefix
46592      * @param array|string $paths   The PSR-0 root directories
46593      * @param bool         $prepend Whether to prepend the directories
46594      */
46595     public function add($prefix, $paths, $prepend = false)
46596     {
46597         if (!$prefix) {
46598             if ($prepend) {
46599                 $this->fallbackDirsPsr0 = array_merge(
46600                     (array) $paths,
46601                     $this->fallbackDirsPsr0
46602                 );
46603             } else {
46604                 $this->fallbackDirsPsr0 = array_merge(
46605                     $this->fallbackDirsPsr0,
46606                     (array) $paths
46607                 );
46608             }
46609
46610             return;
46611         }
46612
46613         $first = $prefix[0];
46614         if (!isset($this->prefixesPsr0[$first][$prefix])) {
46615             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
46616
46617             return;
46618         }
46619         if ($prepend) {
46620             $this->prefixesPsr0[$first][$prefix] = array_merge(
46621                 (array) $paths,
46622                 $this->prefixesPsr0[$first][$prefix]
46623             );
46624         } else {
46625             $this->prefixesPsr0[$first][$prefix] = array_merge(
46626                 $this->prefixesPsr0[$first][$prefix],
46627                 (array) $paths
46628             );
46629         }
46630     }
46631
46632     /**
46633      * Registers a set of PSR-4 directories for a given namespace, either
46634      * appending or prepending to the ones previously set for this namespace.
46635      *
46636      * @param string       $prefix  The prefix/namespace, with trailing '\\'
46637      * @param array|string $paths   The PSR-4 base directories
46638      * @param bool         $prepend Whether to prepend the directories
46639      *
46640      * @throws \InvalidArgumentException
46641      */
46642     public function addPsr4($prefix, $paths, $prepend = false)
46643     {
46644         if (!$prefix) {
46645             // Register directories for the root namespace.
46646             if ($prepend) {
46647                 $this->fallbackDirsPsr4 = array_merge(
46648                     (array) $paths,
46649                     $this->fallbackDirsPsr4
46650                 );
46651             } else {
46652                 $this->fallbackDirsPsr4 = array_merge(
46653                     $this->fallbackDirsPsr4,
46654                     (array) $paths
46655                 );
46656             }
46657         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
46658             // Register directories for a new namespace.
46659             $length = strlen($prefix);
46660             if ('\\' !== $prefix[$length - 1]) {
46661                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
46662             }
46663             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
46664             $this->prefixDirsPsr4[$prefix] = (array) $paths;
46665         } elseif ($prepend) {
46666             // Prepend directories for an already registered namespace.
46667             $this->prefixDirsPsr4[$prefix] = array_merge(
46668                 (array) $paths,
46669                 $this->prefixDirsPsr4[$prefix]
46670             );
46671         } else {
46672             // Append directories for an already registered namespace.
46673             $this->prefixDirsPsr4[$prefix] = array_merge(
46674                 $this->prefixDirsPsr4[$prefix],
46675                 (array) $paths
46676             );
46677         }
46678     }
46679
46680     /**
46681      * Registers a set of PSR-0 directories for a given prefix,
46682      * replacing any others previously set for this prefix.
46683      *
46684      * @param string       $prefix The prefix
46685      * @param array|string $paths  The PSR-0 base directories
46686      */
46687     public function set($prefix, $paths)
46688     {
46689         if (!$prefix) {
46690             $this->fallbackDirsPsr0 = (array) $paths;
46691         } else {
46692             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
46693         }
46694     }
46695
46696     /**
46697      * Registers a set of PSR-4 directories for a given namespace,
46698      * replacing any others previously set for this namespace.
46699      *
46700      * @param string       $prefix The prefix/namespace, with trailing '\\'
46701      * @param array|string $paths  The PSR-4 base directories
46702      *
46703      * @throws \InvalidArgumentException
46704      */
46705     public function setPsr4($prefix, $paths)
46706     {
46707         if (!$prefix) {
46708             $this->fallbackDirsPsr4 = (array) $paths;
46709         } else {
46710             $length = strlen($prefix);
46711             if ('\\' !== $prefix[$length - 1]) {
46712                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
46713             }
46714             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
46715             $this->prefixDirsPsr4[$prefix] = (array) $paths;
46716         }
46717     }
46718
46719     /**
46720      * Turns on searching the include path for class files.
46721      *
46722      * @param bool $useIncludePath
46723      */
46724     public function setUseIncludePath($useIncludePath)
46725     {
46726         $this->useIncludePath = $useIncludePath;
46727     }
46728
46729     /**
46730      * Can be used to check if the autoloader uses the include path to check
46731      * for classes.
46732      *
46733      * @return bool
46734      */
46735     public function getUseIncludePath()
46736     {
46737         return $this->useIncludePath;
46738     }
46739
46740     /**
46741      * Turns off searching the prefix and fallback directories for classes
46742      * that have not been registered with the class map.
46743      *
46744      * @param bool $classMapAuthoritative
46745      */
46746     public function setClassMapAuthoritative($classMapAuthoritative)
46747     {
46748         $this->classMapAuthoritative = $classMapAuthoritative;
46749     }
46750
46751     /**
46752      * Should class lookup fail if not found in the current class map?
46753      *
46754      * @return bool
46755      */
46756     public function isClassMapAuthoritative()
46757     {
46758         return $this->classMapAuthoritative;
46759     }
46760
46761     /**
46762      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
46763      *
46764      * @param string|null $apcuPrefix
46765      */
46766     public function setApcuPrefix($apcuPrefix)
46767     {
46768         $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
46769     }
46770
46771     /**
46772      * The APCu prefix in use, or null if APCu caching is not enabled.
46773      *
46774      * @return string|null
46775      */
46776     public function getApcuPrefix()
46777     {
46778         return $this->apcuPrefix;
46779     }
46780
46781     /**
46782      * Registers this instance as an autoloader.
46783      *
46784      * @param bool $prepend Whether to prepend the autoloader or not
46785      */
46786     public function register($prepend = false)
46787     {
46788         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
46789     }
46790
46791     /**
46792      * Unregisters this instance as an autoloader.
46793      */
46794     public function unregister()
46795     {
46796         spl_autoload_unregister(array($this, 'loadClass'));
46797     }
46798
46799     /**
46800      * Loads the given class or interface.
46801      *
46802      * @param  string    $class The name of the class
46803      * @return bool|null True if loaded, null otherwise
46804      */
46805     public function loadClass($class)
46806     {
46807         if ($file = $this->findFile($class)) {
46808             includeFile($file);
46809
46810             return true;
46811         }
46812     }
46813
46814     /**
46815      * Finds the path to the file where the class is defined.
46816      *
46817      * @param string $class The name of the class
46818      *
46819      * @return string|false The path if found, false otherwise
46820      */
46821     public function findFile($class)
46822     {
46823         // class map lookup
46824         if (isset($this->classMap[$class])) {
46825             return $this->classMap[$class];
46826         }
46827         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
46828             return false;
46829         }
46830         if (null !== $this->apcuPrefix) {
46831             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
46832             if ($hit) {
46833                 return $file;
46834             }
46835         }
46836
46837         $file = $this->findFileWithExtension($class, '.php');
46838
46839         // Search for Hack files if we are running on HHVM
46840         if (false === $file && defined('HHVM_VERSION')) {
46841             $file = $this->findFileWithExtension($class, '.hh');
46842         }
46843
46844         if (null !== $this->apcuPrefix) {
46845             apcu_add($this->apcuPrefix.$class, $file);
46846         }
46847
46848         if (false === $file) {
46849             // Remember that this class does not exist.
46850             $this->missingClasses[$class] = true;
46851         }
46852
46853         return $file;
46854     }
46855
46856     private function findFileWithExtension($class, $ext)
46857     {
46858         // PSR-4 lookup
46859         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
46860
46861         $first = $class[0];
46862         if (isset($this->prefixLengthsPsr4[$first])) {
46863             $subPath = $class;
46864             while (false !== $lastPos = strrpos($subPath, '\\')) {
46865                 $subPath = substr($subPath, 0, $lastPos);
46866                 $search = $subPath . '\\';
46867                 if (isset($this->prefixDirsPsr4[$search])) {
46868                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
46869                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
46870                         if (file_exists($file = $dir . $pathEnd)) {
46871                             return $file;
46872                         }
46873                     }
46874                 }
46875             }
46876         }
46877
46878         // PSR-4 fallback dirs
46879         foreach ($this->fallbackDirsPsr4 as $dir) {
46880             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
46881                 return $file;
46882             }
46883         }
46884
46885         // PSR-0 lookup
46886         if (false !== $pos = strrpos($class, '\\')) {
46887             // namespaced class name
46888             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
46889                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
46890         } else {
46891             // PEAR-like class name
46892             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
46893         }
46894
46895         if (isset($this->prefixesPsr0[$first])) {
46896             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
46897                 if (0 === strpos($class, $prefix)) {
46898                     foreach ($dirs as $dir) {
46899                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
46900                             return $file;
46901                         }
46902                     }
46903                 }
46904             }
46905         }
46906
46907         // PSR-0 fallback dirs
46908         foreach ($this->fallbackDirsPsr0 as $dir) {
46909             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
46910                 return $file;
46911             }
46912         }
46913
46914         // PSR-0 include paths.
46915         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
46916             return $file;
46917         }
46918
46919         return false;
46920     }
46921 }
46922
46923 /**
46924  * Scope isolated include.
46925  *
46926  * Prevents access to $this/self from included files.
46927  */
46928 function includeFile($file)
46929 {
46930     include $file;
46931 }
46932 {
46933     "$schema": "http://json-schema.org/draft-04/schema#",
46934     "description": "A representation of packages metadata.",
46935     "type": "object",
46936     "oneOf": [
46937         { "required": [ "packages" ] },
46938         { "required": [ "providers" ] },
46939         { "required": [ "provider-includes", "providers-url" ] }
46940     ],
46941     "properties": {
46942         "packages": {
46943             "type": ["object", "array"],
46944             "description": "A hashmap of package names in the form of <vendor>/<name>.",
46945             "additionalProperties": { "$ref": "#/definitions/versions" }
46946         },
46947         "providers-url": {
46948             "type": "string",
46949             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
46950         },
46951         "provider-includes": {
46952             "type": "object",
46953             "description": "A hashmap of provider listings.",
46954             "additionalProperties": { "$ref": "#/definitions/provider" }
46955         },
46956         "providers": {
46957             "type": "object",
46958             "description": "A hashmap of package names in the form of <vendor>/<name>.",
46959             "additionalProperties": { "$ref": "#/definitions/provider" }
46960         },
46961         "notify-batch": {
46962             "type": "string",
46963             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
46964         },
46965         "search": {
46966             "type": "string",
46967             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
46968         },
46969         "warning": {
46970             "type": "string",
46971             "description": "A message that will be output by Composer as a warning when this source is consulted."
46972         }
46973     },
46974     "definitions": {
46975         "versions": {
46976             "type": "object",
46977             "description": "A hashmap of versions and their metadata.",
46978             "additionalProperties": { "$ref": "#/definitions/version" }
46979         },
46980         "version": {
46981             "type": "object",
46982             "oneOf": [
46983                 { "$ref": "#/definitions/package" },
46984                 { "$ref": "#/definitions/metapackage" }
46985             ]
46986         },
46987         "package-base": {
46988             "properties": {
46989                 "name": { "type": "string" },
46990                 "type": { "type": "string" },
46991                 "version": { "type": "string" },
46992                 "version_normalized": {
46993                     "type": "string",
46994                     "description": "Normalized version, optional but can save computational time on client side."
46995                 },
46996                 "autoload": { "type": "object" },
46997                 "require": { "type": "object" },
46998                 "replace": { "type": "object" },
46999                 "conflict": { "type": "object" },
47000                 "provide": { "type": "object" },
47001                 "time": { "type": "string" }
47002             },
47003             "additionalProperties": true
47004         },
47005         "package": {
47006             "allOf": [
47007                 { "$ref": "#/definitions/package-base" },
47008                 {
47009                     "properties": {
47010                         "dist": { "type": "object" },
47011                         "source": { "type": "object" }
47012                     }
47013                 },
47014                 { "oneOf": [
47015                     { "required": [ "name", "version", "source" ] },
47016                     { "required": [ "name", "version", "dist" ] }
47017                 ] }
47018             ]
47019         },
47020         "metapackage": {
47021             "allOf": [
47022                 { "$ref": "#/definitions/package-base" },
47023                 {
47024                     "properties": {
47025                         "type": { "type": "string", "enum": [ "metapackage" ] }
47026                     },
47027                     "required": [ "name", "version", "type" ]
47028                 }
47029             ]
47030         },
47031         "provider": {
47032             "type": "object",
47033             "properties": {
47034                 "sha256": {
47035                     "type": "string",
47036                     "description": "Hash value that can be used to validate the resource."
47037                 }
47038             }
47039         }
47040     }
47041 }
47042 {
47043     "$schema": "http://json-schema.org/draft-04/schema#",
47044     "name": "Package",
47045     "type": "object",
47046     "additionalProperties": false,
47047     "required": [ "name", "description" ],
47048     "properties": {
47049         "name": {
47050             "type": "string",
47051             "description": "Package name, including 'vendor-name/' prefix."
47052         },
47053         "type": {
47054             "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.",
47055             "type": "string",
47056             "pattern": "^[a-z0-9-]+$"
47057         },
47058         "target-dir": {
47059             "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.",
47060             "type": "string"
47061         },
47062         "description": {
47063             "type": "string",
47064             "description": "Short package description."
47065         },
47066         "keywords": {
47067             "type": "array",
47068             "items": {
47069                 "type": "string",
47070                 "description": "A tag/keyword that this package relates to."
47071             }
47072         },
47073         "homepage": {
47074             "type": "string",
47075             "description": "Homepage URL for the project.",
47076             "format": "uri"
47077         },
47078         "readme": {
47079             "type": "string",
47080             "description": "Relative path to the readme document."
47081         },
47082         "version": {
47083             "type": "string",
47084             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
47085             "pattern": "^v?\\d+(((\\.\\d+)?\\.\\d+)?\\.\\d+)?"
47086         },
47087         "time": {
47088             "type": "string",
47089             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
47090         },
47091         "license": {
47092             "type": ["string", "array"],
47093             "description": "License name. Or an array of license names."
47094         },
47095         "authors": {
47096             "$ref": "#/definitions/authors"
47097         },
47098         "require": {
47099             "type": "object",
47100             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
47101             "additionalProperties": {
47102                 "type": "string"
47103             }
47104         },
47105         "replace": {
47106             "type": "object",
47107             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
47108             "additionalProperties": {
47109                 "type": "string"
47110             }
47111         },
47112         "conflict": {
47113             "type": "object",
47114             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
47115             "additionalProperties": {
47116                 "type": "string"
47117             }
47118         },
47119         "provide": {
47120             "type": "object",
47121             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
47122             "additionalProperties": {
47123                 "type": "string"
47124             }
47125         },
47126         "require-dev": {
47127             "type": "object",
47128             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
47129             "additionalProperties": {
47130                 "type": "string"
47131             }
47132         },
47133         "suggest": {
47134             "type": "object",
47135             "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).",
47136             "additionalProperties": {
47137                 "type": "string"
47138             }
47139         },
47140         "config": {
47141             "type": "object",
47142             "description": "Composer options.",
47143             "properties": {
47144                 "process-timeout": {
47145                     "type": "integer",
47146                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
47147                 },
47148                 "use-include-path": {
47149                     "type": "boolean",
47150                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
47151                 },
47152                 "preferred-install": {
47153                     "type": ["string", "object"],
47154                     "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\"}."
47155                 },
47156                 "notify-on-install": {
47157                     "type": "boolean",
47158                     "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."
47159                 },
47160                 "github-protocols": {
47161                     "type": "array",
47162                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
47163                     "items": {
47164                         "type": "string"
47165                     }
47166                 },
47167                 "github-oauth": {
47168                     "type": "object",
47169                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
47170                     "additionalProperties": {
47171                         "type": "string"
47172                     }
47173                 },
47174                 "gitlab-oauth": {
47175                     "type": "object",
47176                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
47177                     "additionalProperties": {
47178                         "type": "string"
47179                     }
47180                 },
47181                 "gitlab-token": {
47182                     "type": "object",
47183                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
47184                     "additionalProperties": true
47185                 },
47186                 "disable-tls": {
47187                     "type": "boolean",
47188                     "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."
47189                 },
47190                 "secure-http": {
47191                     "type": "boolean",
47192                     "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."
47193                 },
47194                 "cafile": {
47195                     "type": "string",
47196                     "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."
47197                 },
47198                 "capath": {
47199                     "type": "string",
47200                     "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."
47201                 },
47202                 "http-basic": {
47203                     "type": "object",
47204                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
47205                     "additionalProperties": {
47206                         "type": "object",
47207                         "required": ["username", "password"],
47208                         "properties": {
47209                             "username": {
47210                                 "type": "string",
47211                                 "description": "The username used for HTTP Basic authentication"
47212                             },
47213                             "password": {
47214                                 "type": "string",
47215                                 "description": "The password used for HTTP Basic authentication"
47216                             }
47217                         }
47218                     }
47219                 },
47220                 "store-auths": {
47221                     "type": ["string", "boolean"],
47222                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
47223                 },
47224                 "platform": {
47225                     "type": "object",
47226                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
47227                     "additionalProperties": {
47228                         "type": "string"
47229                     }
47230                 },
47231                 "vendor-dir": {
47232                     "type": "string",
47233                     "description": "The location where all packages are installed, defaults to \"vendor\"."
47234                 },
47235                 "bin-dir": {
47236                     "type": "string",
47237                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
47238                 },
47239                 "data-dir": {
47240                     "type": "string",
47241                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
47242                 },
47243                 "cache-dir": {
47244                     "type": "string",
47245                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
47246                 },
47247                 "cache-files-dir": {
47248                     "type": "string",
47249                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
47250                 },
47251                 "cache-repo-dir": {
47252                     "type": "string",
47253                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
47254                 },
47255                 "cache-vcs-dir": {
47256                     "type": "string",
47257                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
47258                 },
47259                 "cache-ttl": {
47260                     "type": "integer",
47261                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
47262                 },
47263                 "cache-files-ttl": {
47264                     "type": "integer",
47265                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
47266                 },
47267                 "cache-files-maxsize": {
47268                     "type": ["string", "integer"],
47269                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
47270                 },
47271                 "bin-compat": {
47272                     "enum": ["auto", "full"],
47273                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
47274                 },
47275                 "discard-changes": {
47276                     "type": ["string", "boolean"],
47277                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
47278                 },
47279                 "autoloader-suffix": {
47280                     "type": "string",
47281                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
47282                 },
47283                 "optimize-autoloader": {
47284                     "type": "boolean",
47285                     "description": "Always optimize when dumping the autoloader."
47286                 },
47287                 "prepend-autoloader": {
47288                     "type": "boolean",
47289                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
47290                 },
47291                 "classmap-authoritative": {
47292                     "type": "boolean",
47293                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
47294                 },
47295                 "apcu-autoloader": {
47296                     "type": "boolean",
47297                     "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."
47298                 },
47299                 "github-domains": {
47300                     "type": "array",
47301                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
47302                     "items": {
47303                         "type": "string"
47304                     }
47305                 },
47306                 "github-expose-hostname": {
47307                     "type": "boolean",
47308                     "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."
47309                 },
47310                 "gitlab-domains": {
47311                     "type": "array",
47312                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
47313                     "items": {
47314                         "type": "string"
47315                     }
47316                 },
47317                 "use-github-api": {
47318                     "type": "boolean",
47319                     "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."
47320                 },
47321                 "archive-format": {
47322                     "type": "string",
47323                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
47324                 },
47325                 "archive-dir": {
47326                     "type": "string",
47327                     "description": "The default archive path when not provided on cli, defaults to \".\"."
47328                 },
47329                 "htaccess-protect": {
47330                     "type": "boolean",
47331                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
47332                 },
47333                 "sort-packages": {
47334                     "type": "boolean",
47335                     "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
47336                 }
47337             }
47338         },
47339         "extra": {
47340             "type": ["object", "array"],
47341             "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.",
47342             "additionalProperties": true
47343         },
47344         "autoload": {
47345             "$ref": "#/definitions/autoload"
47346         },
47347         "autoload-dev": {
47348             "type": "object",
47349             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
47350             "properties": {
47351                 "psr-0": {
47352                     "type": "object",
47353                     "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.",
47354                     "additionalProperties": {
47355                         "type": ["string", "array"],
47356                         "items": {
47357                             "type": "string"
47358                         }
47359                     }
47360                 },
47361                 "psr-4": {
47362                     "type": "object",
47363                     "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.",
47364                     "additionalProperties": {
47365                         "type": ["string", "array"],
47366                         "items": {
47367                             "type": "string"
47368                         }
47369                     }
47370                 },
47371                 "classmap": {
47372                     "type": "array",
47373                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
47374                 },
47375                 "files": {
47376                     "type": "array",
47377                     "description": "This is an array of files that are always required on every request."
47378                 }
47379             }
47380         },
47381         "archive": {
47382             "type": ["object"],
47383             "description": "Options for creating package archives for distribution.",
47384             "properties": {
47385                 "exclude": {
47386                     "type": "array",
47387                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
47388                 }
47389             }
47390         },
47391         "repositories": {
47392             "type": ["object", "array"],
47393             "description": "A set of additional repositories where packages can be found.",
47394             "additionalProperties": {
47395                 "oneOf": [
47396                     { "$ref": "#/definitions/repository" },
47397                     { "type": "boolean", "enum": [false] }
47398                 ]
47399             },
47400             "items": {
47401                 "oneOf": [
47402                     { "$ref": "#/definitions/repository" },
47403                     {
47404                         "type": "object",
47405                         "additionalProperties": { "type": "boolean", "enum": [false] },
47406                         "minProperties": 1,
47407                         "maxProperties": 1
47408                     }
47409                 ]
47410             }
47411         },
47412         "minimum-stability": {
47413             "type": ["string"],
47414             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
47415             "pattern": "^dev|alpha|beta|rc|RC|stable$"
47416         },
47417         "prefer-stable": {
47418             "type": ["boolean"],
47419             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
47420         },
47421         "bin": {
47422             "type": ["string", "array"],
47423             "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
47424             "items": {
47425                 "type": "string"
47426             }
47427         },
47428         "include-path": {
47429             "type": ["array"],
47430             "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.",
47431             "items": {
47432                 "type": "string"
47433             }
47434         },
47435         "scripts": {
47436             "type": ["object"],
47437             "description": "Script listeners that will be executed before/after some events.",
47438             "properties": {
47439                 "pre-install-cmd": {
47440                     "type": ["array", "string"],
47441                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
47442                 },
47443                 "post-install-cmd": {
47444                     "type": ["array", "string"],
47445                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
47446                 },
47447                 "pre-update-cmd": {
47448                     "type": ["array", "string"],
47449                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
47450                 },
47451                 "post-update-cmd": {
47452                     "type": ["array", "string"],
47453                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
47454                 },
47455                 "pre-status-cmd": {
47456                     "type": ["array", "string"],
47457                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
47458                 },
47459                 "post-status-cmd": {
47460                     "type": ["array", "string"],
47461                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
47462                 },
47463                 "pre-package-install": {
47464                     "type": ["array", "string"],
47465                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
47466                 },
47467                 "post-package-install": {
47468                     "type": ["array", "string"],
47469                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
47470                 },
47471                 "pre-package-update": {
47472                     "type": ["array", "string"],
47473                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
47474                 },
47475                 "post-package-update": {
47476                     "type": ["array", "string"],
47477                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
47478                 },
47479                 "pre-package-uninstall": {
47480                     "type": ["array", "string"],
47481                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
47482                 },
47483                 "post-package-uninstall": {
47484                     "type": ["array", "string"],
47485                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
47486                 },
47487                 "pre-autoload-dump": {
47488                     "type": ["array", "string"],
47489                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
47490                 },
47491                 "post-autoload-dump": {
47492                     "type": ["array", "string"],
47493                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
47494                 },
47495                 "post-root-package-install": {
47496                     "type": ["array", "string"],
47497                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
47498                 },
47499                 "post-create-project-cmd": {
47500                     "type": ["array", "string"],
47501                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
47502                 }
47503             }
47504         },
47505         "scripts-descriptions": {
47506             "type": ["object"],
47507             "description": "Descriptions for custom commands, shown in console help.",
47508             "additionalProperties": {
47509                 "type": "string"
47510             }
47511         },
47512         "support": {
47513             "type": "object",
47514             "properties": {
47515                 "email": {
47516                     "type": "string",
47517                     "description": "Email address for support.",
47518                     "format": "email"
47519                 },
47520                 "issues": {
47521                     "type": "string",
47522                     "description": "URL to the issue tracker.",
47523                     "format": "uri"
47524                 },
47525                 "forum": {
47526                     "type": "string",
47527                     "description": "URL to the forum.",
47528                     "format": "uri"
47529                 },
47530                 "wiki": {
47531                     "type": "string",
47532                     "description": "URL to the wiki.",
47533                     "format": "uri"
47534                 },
47535                 "irc": {
47536                     "type": "string",
47537                     "description": "IRC channel for support, as irc://server/channel.",
47538                     "format": "uri"
47539                 },
47540                 "chat": {
47541                     "type": "string",
47542                     "description": "URL to the support chat.",
47543                     "format": "uri"
47544                 },
47545                 "source": {
47546                     "type": "string",
47547                     "description": "URL to browse or download the sources.",
47548                     "format": "uri"
47549                 },
47550                 "docs": {
47551                     "type": "string",
47552                     "description": "URL to the documentation.",
47553                     "format": "uri"
47554                 },
47555                 "rss": {
47556                     "type": "string",
47557                     "description": "URL to the RSS feed.",
47558                     "format": "uri"
47559                 }
47560             }
47561         },
47562         "non-feature-branches": {
47563             "type": ["array"],
47564             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
47565             "items": {
47566                 "type": "string"
47567             }
47568         },
47569         "abandoned": {
47570             "type": ["boolean", "string"],
47571             "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."
47572         },
47573         "_comment": {
47574             "type": ["array", "string"],
47575             "description": "A key to store comments in"
47576         }
47577     },
47578     "definitions": {
47579         "authors": {
47580             "type": "array",
47581             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
47582             "items": {
47583                 "type": "object",
47584                 "additionalProperties": false,
47585                 "required": [ "name"],
47586                 "properties": {
47587                     "name": {
47588                         "type": "string",
47589                         "description": "Full name of the author."
47590                     },
47591                     "email": {
47592                         "type": "string",
47593                         "description": "Email address of the author.",
47594                         "format": "email"
47595                     },
47596                     "homepage": {
47597                         "type": "string",
47598                         "description": "Homepage URL for the author.",
47599                         "format": "uri"
47600                     },
47601                     "role": {
47602                         "type": "string",
47603                         "description": "Author's role in the project."
47604                     }
47605                 }
47606             }
47607         },
47608         "autoload": {
47609             "type": "object",
47610             "description": "Description of how the package can be autoloaded.",
47611             "properties": {
47612                 "psr-0": {
47613                     "type": "object",
47614                     "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.",
47615                     "additionalProperties": {
47616                         "type": ["string", "array"],
47617                         "items": {
47618                             "type": "string"
47619                         }
47620                     }
47621                 },
47622                 "psr-4": {
47623                     "type": "object",
47624                     "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.",
47625                     "additionalProperties": {
47626                         "type": ["string", "array"],
47627                         "items": {
47628                             "type": "string"
47629                         }
47630                     }
47631                 },
47632                 "classmap": {
47633                     "type": "array",
47634                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
47635                 },
47636                 "files": {
47637                     "type": "array",
47638                     "description": "This is an array of files that are always required on every request."
47639                 },
47640                 "exclude-from-classmap": {
47641                     "type": "array",
47642                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
47643                 }
47644             }
47645         },
47646         "repository": {
47647             "type": "object",
47648             "oneOf": [
47649                 { "$ref": "#/definitions/composer-repository" },
47650                 { "$ref": "#/definitions/vcs-repository" },
47651                 { "$ref": "#/definitions/path-repository" },
47652                 { "$ref": "#/definitions/artifact-repository" },
47653                 { "$ref": "#/definitions/pear-repository" },
47654                 { "$ref": "#/definitions/package-repository" }
47655             ]
47656         },
47657         "composer-repository": {
47658             "type": "object",
47659             "required": ["type", "url"],
47660             "properties": {
47661                 "type": { "type": "string", "enum": ["composer"] },
47662                 "url": { "type": "string" },
47663                 "options": {
47664                     "type": "object",
47665                     "additionalProperties": true
47666                 },
47667                 "allow_ssl_downgrade": { "type": "boolean" },
47668                 "force-lazy-providers": { "type": "boolean" }
47669             }
47670         },
47671         "vcs-repository": {
47672             "type": "object",
47673             "required": ["type", "url"],
47674             "properties": {
47675                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
47676                 "url": { "type": "string" },
47677                 "no-api": { "type": "boolean" },
47678                 "secure-http": { "type": "boolean" },
47679                 "svn-cache-credentials": { "type": "boolean" },
47680                 "trunk-path": { "type": ["string", "boolean"] },
47681                 "branches-path": { "type": ["string", "boolean"] },
47682                 "tags-path": { "type": ["string", "boolean"] },
47683                 "package-path": { "type": "string" },
47684                 "depot": { "type": "string" },
47685                 "branch": { "type": "string" },
47686                 "unique_perforce_client_name": { "type": "string" },
47687                 "p4user": { "type": "string" },
47688                 "p4password": { "type": "string" }
47689             }
47690         },
47691         "path-repository": {
47692             "type": "object",
47693             "required": ["type", "url"],
47694             "properties": {
47695                 "type": { "type": "string", "enum": ["path"] },
47696                 "url": { "type": "string" },
47697                 "options": {
47698                     "type": "object",
47699                     "properties": {
47700                         "symlink": { "type": ["boolean", "null"] }
47701                     },
47702                     "additionalProperties": true
47703                 }
47704             }
47705         },
47706         "artifact-repository": {
47707             "type": "object",
47708             "required": ["type", "url"],
47709             "properties": {
47710                 "type": { "type": "string", "enum": ["artifact"] },
47711                 "url": { "type": "string" }
47712             }
47713         },
47714         "pear-repository": {
47715             "type": "object",
47716             "required": ["type", "url"],
47717             "properties": {
47718                 "type": { "type": "string", "enum": ["pear"] },
47719                 "url": { "type": "string" },
47720                 "vendor-alias": { "type": "string" }
47721             }
47722         },
47723         "package-repository": {
47724             "type": "object",
47725             "required": ["type", "package"],
47726             "properties": {
47727                 "type": { "type": "string", "enum": ["package"] },
47728                 "package": {
47729                     "oneOf": [
47730                         { "$ref": "#/definitions/inline-package" },
47731                         {
47732                             "type": "array",
47733                             "items": { "$ref": "#/definitions/inline-package" }
47734                         }
47735                     ]
47736                 }
47737             }
47738         },
47739         "inline-package": {
47740             "type": "object",
47741             "required": ["name", "version"],
47742             "properties": {
47743                 "name": {
47744                     "type": "string",
47745                     "description": "Package name, including 'vendor-name/' prefix."
47746                 },
47747                 "type": {
47748                     "type": "string"
47749                 },
47750                 "target-dir": {
47751                     "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.",
47752                     "type": "string"
47753                 },
47754                 "description": {
47755                     "type": "string"
47756                 },
47757                 "keywords": {
47758                     "type": "array",
47759                     "items": {
47760                         "type": "string"
47761                     }
47762                 },
47763                 "homepage": {
47764                     "type": "string",
47765                     "format": "uri"
47766                 },
47767                 "version": {
47768                     "type": "string"
47769                 },
47770                 "time": {
47771                     "type": "string"
47772                 },
47773                 "license": {
47774                     "type": [
47775                         "string",
47776                         "array"
47777                     ]
47778                 },
47779                 "authors": {
47780                     "$ref": "#/definitions/authors"
47781                 },
47782                 "require": {
47783                     "type": "object",
47784                     "additionalProperties": {
47785                         "type": "string"
47786                     }
47787                 },
47788                 "replace": {
47789                     "type": "object",
47790                     "additionalProperties": {
47791                         "type": "string"
47792                     }
47793                 },
47794                 "conflict": {
47795                     "type": "object",
47796                     "additionalProperties": {
47797                         "type": "string"
47798                     }
47799                 },
47800                 "provide": {
47801                     "type": "object",
47802                     "additionalProperties": {
47803                         "type": "string"
47804                     }
47805                 },
47806                 "require-dev": {
47807                     "type": "object",
47808                     "additionalProperties": {
47809                         "type": "string"
47810                     }
47811                 },
47812                 "suggest": {
47813                     "type": "object",
47814                     "additionalProperties": {
47815                         "type": "string"
47816                     }
47817                 },
47818                 "extra": {
47819                     "type": ["object", "array"],
47820                     "additionalProperties": true
47821                 },
47822                 "autoload": {
47823                     "$ref": "#/definitions/autoload"
47824                 },
47825                 "archive": {
47826                     "type": ["object"],
47827                     "properties": {
47828                         "exclude": {
47829                             "type": "array"
47830                         }
47831                     }
47832                 },
47833                 "bin": {
47834                     "type": ["string", "array"],
47835                     "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
47836                     "items": {
47837                         "type": "string"
47838                     }
47839                 },
47840                 "include-path": {
47841                     "type": ["array"],
47842                     "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.",
47843                     "items": {
47844                         "type": "string"
47845                     }
47846                 },
47847                 "source": {
47848                     "type": "object",
47849                     "required": ["type", "url", "reference"],
47850                     "properties": {
47851                         "type": {
47852                             "type": "string"
47853                         },
47854                         "url": {
47855                             "type": "string"
47856                         },
47857                         "reference": {
47858                             "type": "string"
47859                         },
47860                         "mirrors": {
47861                             "type": "array"
47862                         }
47863                     }
47864                 },
47865                 "dist": {
47866                     "type": "object",
47867                     "required": ["type", "url"],
47868                     "properties": {
47869                         "type": {
47870                             "type": "string"
47871                         },
47872                         "url": {
47873                             "type": "string"
47874                         },
47875                         "reference": {
47876                             "type": "string"
47877                         },
47878                         "shasum": {
47879                             "type": "string"
47880                         },
47881                         "mirrors": {
47882                             "type": "array"
47883                         }
47884                     }
47885                 }
47886             },
47887             "additionalProperties": true
47888         }
47889     }
47890 }
47891 {
47892     "389-exception": [
47893         "389 Directory Server Exception"
47894     ],
47895     "Autoconf-exception-2.0": [
47896         "Autoconf exception 2.0"
47897     ],
47898     "Autoconf-exception-3.0": [
47899         "Autoconf exception 3.0"
47900     ],
47901     "Bison-exception-2.2": [
47902         "Bison exception 2.2"
47903     ],
47904     "Bootloader-exception": [
47905         "Bootloader Distribution Exception"
47906     ],
47907     "Classpath-exception-2.0": [
47908         "Classpath exception 2.0"
47909     ],
47910     "CLISP-exception-2.0": [
47911         "CLISP exception 2.0"
47912     ],
47913     "DigiRule-FOSS-exception": [
47914         "DigiRule FOSS License Exception"
47915     ],
47916     "eCos-exception-2.0": [
47917         "eCos exception 2.0"
47918     ],
47919     "Fawkes-Runtime-exception": [
47920         "Fawkes Runtime Exception"
47921     ],
47922     "FLTK-exception": [
47923         "FLTK exception"
47924     ],
47925     "Font-exception-2.0": [
47926         "Font exception 2.0"
47927     ],
47928     "freertos-exception-2.0": [
47929         "FreeRTOS Exception 2.0"
47930     ],
47931     "GCC-exception-2.0": [
47932         "GCC Runtime Library exception 2.0"
47933     ],
47934     "GCC-exception-3.1": [
47935         "GCC Runtime Library exception 3.1"
47936     ],
47937     "gnu-javamail-exception": [
47938         "GNU JavaMail exception"
47939     ],
47940     "GPL-CC-1.0": [
47941         "GPL Cooperation Commitment 1.0"
47942     ],
47943     "i2p-gpl-java-exception": [
47944         "i2p GPL+Java Exception"
47945     ],
47946     "Libtool-exception": [
47947         "Libtool Exception"
47948     ],
47949     "Linux-syscall-note": [
47950         "Linux Syscall Note"
47951     ],
47952     "LLVM-exception": [
47953         "LLVM Exception"
47954     ],
47955     "LZMA-exception": [
47956         "LZMA exception"
47957     ],
47958     "mif-exception": [
47959         "Macros and Inline Functions Exception"
47960     ],
47961     "Nokia-Qt-exception-1.1": [
47962         "Nokia Qt LGPL exception 1.1"
47963     ],
47964     "OCaml-LGPL-linking-exception": [
47965         "OCaml LGPL Linking Exception"
47966     ],
47967     "OCCT-exception-1.0": [
47968         "Open CASCADE Exception 1.0"
47969     ],
47970     "OpenJDK-assembly-exception-1.0": [
47971         "OpenJDK Assembly exception 1.0"
47972     ],
47973     "openvpn-openssl-exception": [
47974         "OpenVPN OpenSSL Exception"
47975     ],
47976     "PS-or-PDF-font-exception-20170817": [
47977         "PS/PDF font exception (2017-08-17)"
47978     ],
47979     "Qt-GPL-exception-1.0": [
47980         "Qt GPL exception 1.0"
47981     ],
47982     "Qt-LGPL-exception-1.1": [
47983         "Qt LGPL exception 1.1"
47984     ],
47985     "Qwt-exception-1.0": [
47986         "Qwt exception 1.0"
47987     ],
47988     "Swift-exception": [
47989         "Swift Exception"
47990     ],
47991     "u-boot-exception-2.0": [
47992         "U-Boot exception 2.0"
47993     ],
47994     "Universal-FOSS-exception-1.0": [
47995         "Universal FOSS Exception, Version 1.0"
47996     ],
47997     "WxWindows-exception-3.1": [
47998         "WxWindows Library Exception 3.1"
47999     ]
48000 }{
48001     "0BSD": [
48002         "BSD Zero Clause License",
48003         true,
48004         false
48005     ],
48006     "AAL": [
48007         "Attribution Assurance License",
48008         true,
48009         false
48010     ],
48011     "Abstyles": [
48012         "Abstyles License",
48013         false,
48014         false
48015     ],
48016     "Adobe-2006": [
48017         "Adobe Systems Incorporated Source Code License Agreement",
48018         false,
48019         false
48020     ],
48021     "Adobe-Glyph": [
48022         "Adobe Glyph List License",
48023         false,
48024         false
48025     ],
48026     "ADSL": [
48027         "Amazon Digital Services License",
48028         false,
48029         false
48030     ],
48031     "AFL-1.1": [
48032         "Academic Free License v1.1",
48033         true,
48034         false
48035     ],
48036     "AFL-1.2": [
48037         "Academic Free License v1.2",
48038         true,
48039         false
48040     ],
48041     "AFL-2.0": [
48042         "Academic Free License v2.0",
48043         true,
48044         false
48045     ],
48046     "AFL-2.1": [
48047         "Academic Free License v2.1",
48048         true,
48049         false
48050     ],
48051     "AFL-3.0": [
48052         "Academic Free License v3.0",
48053         true,
48054         false
48055     ],
48056     "Afmparse": [
48057         "Afmparse License",
48058         false,
48059         false
48060     ],
48061     "AGPL-1.0": [
48062         "Affero General Public License v1.0",
48063         false,
48064         true
48065     ],
48066     "AGPL-1.0-only": [
48067         "Affero General Public License v1.0 only",
48068         false,
48069         false
48070     ],
48071     "AGPL-1.0-or-later": [
48072         "Affero General Public License v1.0 or later",
48073         false,
48074         false
48075     ],
48076     "AGPL-3.0": [
48077         "GNU Affero General Public License v3.0",
48078         true,
48079         true
48080     ],
48081     "AGPL-3.0-only": [
48082         "GNU Affero General Public License v3.0 only",
48083         true,
48084         false
48085     ],
48086     "AGPL-3.0-or-later": [
48087         "GNU Affero General Public License v3.0 or later",
48088         true,
48089         false
48090     ],
48091     "Aladdin": [
48092         "Aladdin Free Public License",
48093         false,
48094         false
48095     ],
48096     "AMDPLPA": [
48097         "AMD's plpa_map.c License",
48098         false,
48099         false
48100     ],
48101     "AML": [
48102         "Apple MIT License",
48103         false,
48104         false
48105     ],
48106     "AMPAS": [
48107         "Academy of Motion Picture Arts and Sciences BSD",
48108         false,
48109         false
48110     ],
48111     "ANTLR-PD": [
48112         "ANTLR Software Rights Notice",
48113         false,
48114         false
48115     ],
48116     "Apache-1.0": [
48117         "Apache License 1.0",
48118         false,
48119         false
48120     ],
48121     "Apache-1.1": [
48122         "Apache License 1.1",
48123         true,
48124         false
48125     ],
48126     "Apache-2.0": [
48127         "Apache License 2.0",
48128         true,
48129         false
48130     ],
48131     "APAFML": [
48132         "Adobe Postscript AFM License",
48133         false,
48134         false
48135     ],
48136     "APL-1.0": [
48137         "Adaptive Public License 1.0",
48138         true,
48139         false
48140     ],
48141     "APSL-1.0": [
48142         "Apple Public Source License 1.0",
48143         true,
48144         false
48145     ],
48146     "APSL-1.1": [
48147         "Apple Public Source License 1.1",
48148         true,
48149         false
48150     ],
48151     "APSL-1.2": [
48152         "Apple Public Source License 1.2",
48153         true,
48154         false
48155     ],
48156     "APSL-2.0": [
48157         "Apple Public Source License 2.0",
48158         true,
48159         false
48160     ],
48161     "Artistic-1.0": [
48162         "Artistic License 1.0",
48163         true,
48164         false
48165     ],
48166     "Artistic-1.0-cl8": [
48167         "Artistic License 1.0 w/clause 8",
48168         true,
48169         false
48170     ],
48171     "Artistic-1.0-Perl": [
48172         "Artistic License 1.0 (Perl)",
48173         true,
48174         false
48175     ],
48176     "Artistic-2.0": [
48177         "Artistic License 2.0",
48178         true,
48179         false
48180     ],
48181     "Bahyph": [
48182         "Bahyph License",
48183         false,
48184         false
48185     ],
48186     "Barr": [
48187         "Barr License",
48188         false,
48189         false
48190     ],
48191     "Beerware": [
48192         "Beerware License",
48193         false,
48194         false
48195     ],
48196     "BitTorrent-1.0": [
48197         "BitTorrent Open Source License v1.0",
48198         false,
48199         false
48200     ],
48201     "BitTorrent-1.1": [
48202         "BitTorrent Open Source License v1.1",
48203         false,
48204         false
48205     ],
48206     "blessing": [
48207         "SQLite Blessing",
48208         false,
48209         false
48210     ],
48211     "BlueOak-1.0.0": [
48212         "Blue Oak Model License 1.0.0",
48213         false,
48214         false
48215     ],
48216     "Borceux": [
48217         "Borceux license",
48218         false,
48219         false
48220     ],
48221     "BSD-1-Clause": [
48222         "BSD 1-Clause License",
48223         false,
48224         false
48225     ],
48226     "BSD-2-Clause": [
48227         "BSD 2-Clause \"Simplified\" License",
48228         true,
48229         false
48230     ],
48231     "BSD-2-Clause-FreeBSD": [
48232         "BSD 2-Clause FreeBSD License",
48233         false,
48234         false
48235     ],
48236     "BSD-2-Clause-NetBSD": [
48237         "BSD 2-Clause NetBSD License",
48238         false,
48239         false
48240     ],
48241     "BSD-2-Clause-Patent": [
48242         "BSD-2-Clause Plus Patent License",
48243         true,
48244         false
48245     ],
48246     "BSD-3-Clause": [
48247         "BSD 3-Clause \"New\" or \"Revised\" License",
48248         true,
48249         false
48250     ],
48251     "BSD-3-Clause-Attribution": [
48252         "BSD with attribution",
48253         false,
48254         false
48255     ],
48256     "BSD-3-Clause-Clear": [
48257         "BSD 3-Clause Clear License",
48258         false,
48259         false
48260     ],
48261     "BSD-3-Clause-LBNL": [
48262         "Lawrence Berkeley National Labs BSD variant license",
48263         true,
48264         false
48265     ],
48266     "BSD-3-Clause-No-Nuclear-License": [
48267         "BSD 3-Clause No Nuclear License",
48268         false,
48269         false
48270     ],
48271     "BSD-3-Clause-No-Nuclear-License-2014": [
48272         "BSD 3-Clause No Nuclear License 2014",
48273         false,
48274         false
48275     ],
48276     "BSD-3-Clause-No-Nuclear-Warranty": [
48277         "BSD 3-Clause No Nuclear Warranty",
48278         false,
48279         false
48280     ],
48281     "BSD-3-Clause-Open-MPI": [
48282         "BSD 3-Clause Open MPI variant",
48283         false,
48284         false
48285     ],
48286     "BSD-4-Clause": [
48287         "BSD 4-Clause \"Original\" or \"Old\" License",
48288         false,
48289         false
48290     ],
48291     "BSD-4-Clause-UC": [
48292         "BSD-4-Clause (University of California-Specific)",
48293         false,
48294         false
48295     ],
48296     "BSD-Protection": [
48297         "BSD Protection License",
48298         false,
48299         false
48300     ],
48301     "BSD-Source-Code": [
48302         "BSD Source Code Attribution",
48303         false,
48304         false
48305     ],
48306     "BSL-1.0": [
48307         "Boost Software License 1.0",
48308         true,
48309         false
48310     ],
48311     "bzip2-1.0.5": [
48312         "bzip2 and libbzip2 License v1.0.5",
48313         false,
48314         false
48315     ],
48316     "bzip2-1.0.6": [
48317         "bzip2 and libbzip2 License v1.0.6",
48318         false,
48319         false
48320     ],
48321     "Caldera": [
48322         "Caldera License",
48323         false,
48324         false
48325     ],
48326     "CATOSL-1.1": [
48327         "Computer Associates Trusted Open Source License 1.1",
48328         true,
48329         false
48330     ],
48331     "CC-BY-1.0": [
48332         "Creative Commons Attribution 1.0 Generic",
48333         false,
48334         false
48335     ],
48336     "CC-BY-2.0": [
48337         "Creative Commons Attribution 2.0 Generic",
48338         false,
48339         false
48340     ],
48341     "CC-BY-2.5": [
48342         "Creative Commons Attribution 2.5 Generic",
48343         false,
48344         false
48345     ],
48346     "CC-BY-3.0": [
48347         "Creative Commons Attribution 3.0 Unported",
48348         false,
48349         false
48350     ],
48351     "CC-BY-4.0": [
48352         "Creative Commons Attribution 4.0 International",
48353         false,
48354         false
48355     ],
48356     "CC-BY-NC-1.0": [
48357         "Creative Commons Attribution Non Commercial 1.0 Generic",
48358         false,
48359         false
48360     ],
48361     "CC-BY-NC-2.0": [
48362         "Creative Commons Attribution Non Commercial 2.0 Generic",
48363         false,
48364         false
48365     ],
48366     "CC-BY-NC-2.5": [
48367         "Creative Commons Attribution Non Commercial 2.5 Generic",
48368         false,
48369         false
48370     ],
48371     "CC-BY-NC-3.0": [
48372         "Creative Commons Attribution Non Commercial 3.0 Unported",
48373         false,
48374         false
48375     ],
48376     "CC-BY-NC-4.0": [
48377         "Creative Commons Attribution Non Commercial 4.0 International",
48378         false,
48379         false
48380     ],
48381     "CC-BY-NC-ND-1.0": [
48382         "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",
48383         false,
48384         false
48385     ],
48386     "CC-BY-NC-ND-2.0": [
48387         "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",
48388         false,
48389         false
48390     ],
48391     "CC-BY-NC-ND-2.5": [
48392         "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",
48393         false,
48394         false
48395     ],
48396     "CC-BY-NC-ND-3.0": [
48397         "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",
48398         false,
48399         false
48400     ],
48401     "CC-BY-NC-ND-4.0": [
48402         "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",
48403         false,
48404         false
48405     ],
48406     "CC-BY-NC-SA-1.0": [
48407         "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",
48408         false,
48409         false
48410     ],
48411     "CC-BY-NC-SA-2.0": [
48412         "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",
48413         false,
48414         false
48415     ],
48416     "CC-BY-NC-SA-2.5": [
48417         "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",
48418         false,
48419         false
48420     ],
48421     "CC-BY-NC-SA-3.0": [
48422         "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",
48423         false,
48424         false
48425     ],
48426     "CC-BY-NC-SA-4.0": [
48427         "Creative Commons Attribution Non Commercial Share Alike 4.0 International",
48428         false,
48429         false
48430     ],
48431     "CC-BY-ND-1.0": [
48432         "Creative Commons Attribution No Derivatives 1.0 Generic",
48433         false,
48434         false
48435     ],
48436     "CC-BY-ND-2.0": [
48437         "Creative Commons Attribution No Derivatives 2.0 Generic",
48438         false,
48439         false
48440     ],
48441     "CC-BY-ND-2.5": [
48442         "Creative Commons Attribution No Derivatives 2.5 Generic",
48443         false,
48444         false
48445     ],
48446     "CC-BY-ND-3.0": [
48447         "Creative Commons Attribution No Derivatives 3.0 Unported",
48448         false,
48449         false
48450     ],
48451     "CC-BY-ND-4.0": [
48452         "Creative Commons Attribution No Derivatives 4.0 International",
48453         false,
48454         false
48455     ],
48456     "CC-BY-SA-1.0": [
48457         "Creative Commons Attribution Share Alike 1.0 Generic",
48458         false,
48459         false
48460     ],
48461     "CC-BY-SA-2.0": [
48462         "Creative Commons Attribution Share Alike 2.0 Generic",
48463         false,
48464         false
48465     ],
48466     "CC-BY-SA-2.5": [
48467         "Creative Commons Attribution Share Alike 2.5 Generic",
48468         false,
48469         false
48470     ],
48471     "CC-BY-SA-3.0": [
48472         "Creative Commons Attribution Share Alike 3.0 Unported",
48473         false,
48474         false
48475     ],
48476     "CC-BY-SA-4.0": [
48477         "Creative Commons Attribution Share Alike 4.0 International",
48478         false,
48479         false
48480     ],
48481     "CC-PDDC": [
48482         "Creative Commons Public Domain Dedication and Certification",
48483         false,
48484         false
48485     ],
48486     "CC0-1.0": [
48487         "Creative Commons Zero v1.0 Universal",
48488         false,
48489         false
48490     ],
48491     "CDDL-1.0": [
48492         "Common Development and Distribution License 1.0",
48493         true,
48494         false
48495     ],
48496     "CDDL-1.1": [
48497         "Common Development and Distribution License 1.1",
48498         false,
48499         false
48500     ],
48501     "CDLA-Permissive-1.0": [
48502         "Community Data License Agreement Permissive 1.0",
48503         false,
48504         false
48505     ],
48506     "CDLA-Sharing-1.0": [
48507         "Community Data License Agreement Sharing 1.0",
48508         false,
48509         false
48510     ],
48511     "CECILL-1.0": [
48512         "CeCILL Free Software License Agreement v1.0",
48513         false,
48514         false
48515     ],
48516     "CECILL-1.1": [
48517         "CeCILL Free Software License Agreement v1.1",
48518         false,
48519         false
48520     ],
48521     "CECILL-2.0": [
48522         "CeCILL Free Software License Agreement v2.0",
48523         false,
48524         false
48525     ],
48526     "CECILL-2.1": [
48527         "CeCILL Free Software License Agreement v2.1",
48528         true,
48529         false
48530     ],
48531     "CECILL-B": [
48532         "CeCILL-B Free Software License Agreement",
48533         false,
48534         false
48535     ],
48536     "CECILL-C": [
48537         "CeCILL-C Free Software License Agreement",
48538         false,
48539         false
48540     ],
48541     "CERN-OHL-1.1": [
48542         "CERN Open Hardware License v1.1",
48543         false,
48544         false
48545     ],
48546     "CERN-OHL-1.2": [
48547         "CERN Open Hardware Licence v1.2",
48548         false,
48549         false
48550     ],
48551     "ClArtistic": [
48552         "Clarified Artistic License",
48553         false,
48554         false
48555     ],
48556     "CNRI-Jython": [
48557         "CNRI Jython License",
48558         false,
48559         false
48560     ],
48561     "CNRI-Python": [
48562         "CNRI Python License",
48563         true,
48564         false
48565     ],
48566     "CNRI-Python-GPL-Compatible": [
48567         "CNRI Python Open Source GPL Compatible License Agreement",
48568         false,
48569         false
48570     ],
48571     "Condor-1.1": [
48572         "Condor Public License v1.1",
48573         false,
48574         false
48575     ],
48576     "copyleft-next-0.3.0": [
48577         "copyleft-next 0.3.0",
48578         false,
48579         false
48580     ],
48581     "copyleft-next-0.3.1": [
48582         "copyleft-next 0.3.1",
48583         false,
48584         false
48585     ],
48586     "CPAL-1.0": [
48587         "Common Public Attribution License 1.0",
48588         true,
48589         false
48590     ],
48591     "CPL-1.0": [
48592         "Common Public License 1.0",
48593         true,
48594         false
48595     ],
48596     "CPOL-1.02": [
48597         "Code Project Open License 1.02",
48598         false,
48599         false
48600     ],
48601     "Crossword": [
48602         "Crossword License",
48603         false,
48604         false
48605     ],
48606     "CrystalStacker": [
48607         "CrystalStacker License",
48608         false,
48609         false
48610     ],
48611     "CUA-OPL-1.0": [
48612         "CUA Office Public License v1.0",
48613         true,
48614         false
48615     ],
48616     "Cube": [
48617         "Cube License",
48618         false,
48619         false
48620     ],
48621     "curl": [
48622         "curl License",
48623         false,
48624         false
48625     ],
48626     "D-FSL-1.0": [
48627         "Deutsche Freie Software Lizenz",
48628         false,
48629         false
48630     ],
48631     "diffmark": [
48632         "diffmark license",
48633         false,
48634         false
48635     ],
48636     "DOC": [
48637         "DOC License",
48638         false,
48639         false
48640     ],
48641     "Dotseqn": [
48642         "Dotseqn License",
48643         false,
48644         false
48645     ],
48646     "DSDP": [
48647         "DSDP License",
48648         false,
48649         false
48650     ],
48651     "dvipdfm": [
48652         "dvipdfm License",
48653         false,
48654         false
48655     ],
48656     "ECL-1.0": [
48657         "Educational Community License v1.0",
48658         true,
48659         false
48660     ],
48661     "ECL-2.0": [
48662         "Educational Community License v2.0",
48663         true,
48664         false
48665     ],
48666     "eCos-2.0": [
48667         "eCos license version 2.0",
48668         false,
48669         true
48670     ],
48671     "EFL-1.0": [
48672         "Eiffel Forum License v1.0",
48673         true,
48674         false
48675     ],
48676     "EFL-2.0": [
48677         "Eiffel Forum License v2.0",
48678         true,
48679         false
48680     ],
48681     "eGenix": [
48682         "eGenix.com Public License 1.1.0",
48683         false,
48684         false
48685     ],
48686     "Entessa": [
48687         "Entessa Public License v1.0",
48688         true,
48689         false
48690     ],
48691     "EPL-1.0": [
48692         "Eclipse Public License 1.0",
48693         true,
48694         false
48695     ],
48696     "EPL-2.0": [
48697         "Eclipse Public License 2.0",
48698         true,
48699         false
48700     ],
48701     "ErlPL-1.1": [
48702         "Erlang Public License v1.1",
48703         false,
48704         false
48705     ],
48706     "EUDatagrid": [
48707         "EU DataGrid Software License",
48708         true,
48709         false
48710     ],
48711     "EUPL-1.0": [
48712         "European Union Public License 1.0",
48713         false,
48714         false
48715     ],
48716     "EUPL-1.1": [
48717         "European Union Public License 1.1",
48718         true,
48719         false
48720     ],
48721     "EUPL-1.2": [
48722         "European Union Public License 1.2",
48723         true,
48724         false
48725     ],
48726     "Eurosym": [
48727         "Eurosym License",
48728         false,
48729         false
48730     ],
48731     "Fair": [
48732         "Fair License",
48733         true,
48734         false
48735     ],
48736     "Frameworx-1.0": [
48737         "Frameworx Open License 1.0",
48738         true,
48739         false
48740     ],
48741     "FreeImage": [
48742         "FreeImage Public License v1.0",
48743         false,
48744         false
48745     ],
48746     "FSFAP": [
48747         "FSF All Permissive License",
48748         false,
48749         false
48750     ],
48751     "FSFUL": [
48752         "FSF Unlimited License",
48753         false,
48754         false
48755     ],
48756     "FSFULLR": [
48757         "FSF Unlimited License (with License Retention)",
48758         false,
48759         false
48760     ],
48761     "FTL": [
48762         "Freetype Project License",
48763         false,
48764         false
48765     ],
48766     "GFDL-1.1": [
48767         "GNU Free Documentation License v1.1",
48768         false,
48769         true
48770     ],
48771     "GFDL-1.1-only": [
48772         "GNU Free Documentation License v1.1 only",
48773         false,
48774         false
48775     ],
48776     "GFDL-1.1-or-later": [
48777         "GNU Free Documentation License v1.1 or later",
48778         false,
48779         false
48780     ],
48781     "GFDL-1.2": [
48782         "GNU Free Documentation License v1.2",
48783         false,
48784         true
48785     ],
48786     "GFDL-1.2-only": [
48787         "GNU Free Documentation License v1.2 only",
48788         false,
48789         false
48790     ],
48791     "GFDL-1.2-or-later": [
48792         "GNU Free Documentation License v1.2 or later",
48793         false,
48794         false
48795     ],
48796     "GFDL-1.3": [
48797         "GNU Free Documentation License v1.3",
48798         false,
48799         true
48800     ],
48801     "GFDL-1.3-only": [
48802         "GNU Free Documentation License v1.3 only",
48803         false,
48804         false
48805     ],
48806     "GFDL-1.3-or-later": [
48807         "GNU Free Documentation License v1.3 or later",
48808         false,
48809         false
48810     ],
48811     "Giftware": [
48812         "Giftware License",
48813         false,
48814         false
48815     ],
48816     "GL2PS": [
48817         "GL2PS License",
48818         false,
48819         false
48820     ],
48821     "Glide": [
48822         "3dfx Glide License",
48823         false,
48824         false
48825     ],
48826     "Glulxe": [
48827         "Glulxe License",
48828         false,
48829         false
48830     ],
48831     "gnuplot": [
48832         "gnuplot License",
48833         false,
48834         false
48835     ],
48836     "GPL-1.0": [
48837         "GNU General Public License v1.0 only",
48838         false,
48839         true
48840     ],
48841     "GPL-1.0+": [
48842         "GNU General Public License v1.0 or later",
48843         false,
48844         true
48845     ],
48846     "GPL-1.0-only": [
48847         "GNU General Public License v1.0 only",
48848         false,
48849         false
48850     ],
48851     "GPL-1.0-or-later": [
48852         "GNU General Public License v1.0 or later",
48853         false,
48854         false
48855     ],
48856     "GPL-2.0": [
48857         "GNU General Public License v2.0 only",
48858         true,
48859         true
48860     ],
48861     "GPL-2.0+": [
48862         "GNU General Public License v2.0 or later",
48863         true,
48864         true
48865     ],
48866     "GPL-2.0-only": [
48867         "GNU General Public License v2.0 only",
48868         true,
48869         false
48870     ],
48871     "GPL-2.0-or-later": [
48872         "GNU General Public License v2.0 or later",
48873         true,
48874         false
48875     ],
48876     "GPL-2.0-with-autoconf-exception": [
48877         "GNU General Public License v2.0 w/Autoconf exception",
48878         false,
48879         true
48880     ],
48881     "GPL-2.0-with-bison-exception": [
48882         "GNU General Public License v2.0 w/Bison exception",
48883         false,
48884         true
48885     ],
48886     "GPL-2.0-with-classpath-exception": [
48887         "GNU General Public License v2.0 w/Classpath exception",
48888         false,
48889         true
48890     ],
48891     "GPL-2.0-with-font-exception": [
48892         "GNU General Public License v2.0 w/Font exception",
48893         false,
48894         true
48895     ],
48896     "GPL-2.0-with-GCC-exception": [
48897         "GNU General Public License v2.0 w/GCC Runtime Library exception",
48898         false,
48899         true
48900     ],
48901     "GPL-3.0": [
48902         "GNU General Public License v3.0 only",
48903         true,
48904         true
48905     ],
48906     "GPL-3.0+": [
48907         "GNU General Public License v3.0 or later",
48908         true,
48909         true
48910     ],
48911     "GPL-3.0-only": [
48912         "GNU General Public License v3.0 only",
48913         true,
48914         false
48915     ],
48916     "GPL-3.0-or-later": [
48917         "GNU General Public License v3.0 or later",
48918         true,
48919         false
48920     ],
48921     "GPL-3.0-with-autoconf-exception": [
48922         "GNU General Public License v3.0 w/Autoconf exception",
48923         false,
48924         true
48925     ],
48926     "GPL-3.0-with-GCC-exception": [
48927         "GNU General Public License v3.0 w/GCC Runtime Library exception",
48928         true,
48929         true
48930     ],
48931     "gSOAP-1.3b": [
48932         "gSOAP Public License v1.3b",
48933         false,
48934         false
48935     ],
48936     "HaskellReport": [
48937         "Haskell Language Report License",
48938         false,
48939         false
48940     ],
48941     "HPND": [
48942         "Historical Permission Notice and Disclaimer",
48943         true,
48944         false
48945     ],
48946     "HPND-sell-variant": [
48947         "Historical Permission Notice and Disclaimer - sell variant",
48948         false,
48949         false
48950     ],
48951     "IBM-pibs": [
48952         "IBM PowerPC Initialization and Boot Software",
48953         false,
48954         false
48955     ],
48956     "ICU": [
48957         "ICU License",
48958         false,
48959         false
48960     ],
48961     "IJG": [
48962         "Independent JPEG Group License",
48963         false,
48964         false
48965     ],
48966     "ImageMagick": [
48967         "ImageMagick License",
48968         false,
48969         false
48970     ],
48971     "iMatix": [
48972         "iMatix Standard Function Library Agreement",
48973         false,
48974         false
48975     ],
48976     "Imlib2": [
48977         "Imlib2 License",
48978         false,
48979         false
48980     ],
48981     "Info-ZIP": [
48982         "Info-ZIP License",
48983         false,
48984         false
48985     ],
48986     "Intel": [
48987         "Intel Open Source License",
48988         true,
48989         false
48990     ],
48991     "Intel-ACPI": [
48992         "Intel ACPI Software License Agreement",
48993         false,
48994         false
48995     ],
48996     "Interbase-1.0": [
48997         "Interbase Public License v1.0",
48998         false,
48999         false
49000     ],
49001     "IPA": [
49002         "IPA Font License",
49003         true,
49004         false
49005     ],
49006     "IPL-1.0": [
49007         "IBM Public License v1.0",
49008         true,
49009         false
49010     ],
49011     "ISC": [
49012         "ISC License",
49013         true,
49014         false
49015     ],
49016     "JasPer-2.0": [
49017         "JasPer License",
49018         false,
49019         false
49020     ],
49021     "JPNIC": [
49022         "Japan Network Information Center License",
49023         false,
49024         false
49025     ],
49026     "JSON": [
49027         "JSON License",
49028         false,
49029         false
49030     ],
49031     "LAL-1.2": [
49032         "Licence Art Libre 1.2",
49033         false,
49034         false
49035     ],
49036     "LAL-1.3": [
49037         "Licence Art Libre 1.3",
49038         false,
49039         false
49040     ],
49041     "Latex2e": [
49042         "Latex2e License",
49043         false,
49044         false
49045     ],
49046     "Leptonica": [
49047         "Leptonica License",
49048         false,
49049         false
49050     ],
49051     "LGPL-2.0": [
49052         "GNU Library General Public License v2 only",
49053         true,
49054         true
49055     ],
49056     "LGPL-2.0+": [
49057         "GNU Library General Public License v2 or later",
49058         true,
49059         true
49060     ],
49061     "LGPL-2.0-only": [
49062         "GNU Library General Public License v2 only",
49063         true,
49064         false
49065     ],
49066     "LGPL-2.0-or-later": [
49067         "GNU Library General Public License v2 or later",
49068         true,
49069         false
49070     ],
49071     "LGPL-2.1": [
49072         "GNU Lesser General Public License v2.1 only",
49073         true,
49074         true
49075     ],
49076     "LGPL-2.1+": [
49077         "GNU Library General Public License v2.1 or later",
49078         true,
49079         true
49080     ],
49081     "LGPL-2.1-only": [
49082         "GNU Lesser General Public License v2.1 only",
49083         true,
49084         false
49085     ],
49086     "LGPL-2.1-or-later": [
49087         "GNU Lesser General Public License v2.1 or later",
49088         true,
49089         false
49090     ],
49091     "LGPL-3.0": [
49092         "GNU Lesser General Public License v3.0 only",
49093         true,
49094         true
49095     ],
49096     "LGPL-3.0+": [
49097         "GNU Lesser General Public License v3.0 or later",
49098         true,
49099         true
49100     ],
49101     "LGPL-3.0-only": [
49102         "GNU Lesser General Public License v3.0 only",
49103         true,
49104         false
49105     ],
49106     "LGPL-3.0-or-later": [
49107         "GNU Lesser General Public License v3.0 or later",
49108         true,
49109         false
49110     ],
49111     "LGPLLR": [
49112         "Lesser General Public License For Linguistic Resources",
49113         false,
49114         false
49115     ],
49116     "Libpng": [
49117         "libpng License",
49118         false,
49119         false
49120     ],
49121     "libpng-2.0": [
49122         "PNG Reference Library version 2",
49123         false,
49124         false
49125     ],
49126     "libtiff": [
49127         "libtiff License",
49128         false,
49129         false
49130     ],
49131     "LiLiQ-P-1.1": [
49132         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
49133         true,
49134         false
49135     ],
49136     "LiLiQ-R-1.1": [
49137         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
49138         true,
49139         false
49140     ],
49141     "LiLiQ-Rplus-1.1": [
49142         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
49143         true,
49144         false
49145     ],
49146     "Linux-OpenIB": [
49147         "Linux Kernel Variant of OpenIB.org license",
49148         false,
49149         false
49150     ],
49151     "LPL-1.0": [
49152         "Lucent Public License Version 1.0",
49153         true,
49154         false
49155     ],
49156     "LPL-1.02": [
49157         "Lucent Public License v1.02",
49158         true,
49159         false
49160     ],
49161     "LPPL-1.0": [
49162         "LaTeX Project Public License v1.0",
49163         false,
49164         false
49165     ],
49166     "LPPL-1.1": [
49167         "LaTeX Project Public License v1.1",
49168         false,
49169         false
49170     ],
49171     "LPPL-1.2": [
49172         "LaTeX Project Public License v1.2",
49173         false,
49174         false
49175     ],
49176     "LPPL-1.3a": [
49177         "LaTeX Project Public License v1.3a",
49178         false,
49179         false
49180     ],
49181     "LPPL-1.3c": [
49182         "LaTeX Project Public License v1.3c",
49183         true,
49184         false
49185     ],
49186     "MakeIndex": [
49187         "MakeIndex License",
49188         false,
49189         false
49190     ],
49191     "MirOS": [
49192         "MirOS License",
49193         true,
49194         false
49195     ],
49196     "MIT": [
49197         "MIT License",
49198         true,
49199         false
49200     ],
49201     "MIT-0": [
49202         "MIT No Attribution",
49203         true,
49204         false
49205     ],
49206     "MIT-advertising": [
49207         "Enlightenment License (e16)",
49208         false,
49209         false
49210     ],
49211     "MIT-CMU": [
49212         "CMU License",
49213         false,
49214         false
49215     ],
49216     "MIT-enna": [
49217         "enna License",
49218         false,
49219         false
49220     ],
49221     "MIT-feh": [
49222         "feh License",
49223         false,
49224         false
49225     ],
49226     "MITNFA": [
49227         "MIT +no-false-attribs license",
49228         false,
49229         false
49230     ],
49231     "Motosoto": [
49232         "Motosoto License",
49233         true,
49234         false
49235     ],
49236     "mpich2": [
49237         "mpich2 License",
49238         false,
49239         false
49240     ],
49241     "MPL-1.0": [
49242         "Mozilla Public License 1.0",
49243         true,
49244         false
49245     ],
49246     "MPL-1.1": [
49247         "Mozilla Public License 1.1",
49248         true,
49249         false
49250     ],
49251     "MPL-2.0": [
49252         "Mozilla Public License 2.0",
49253         true,
49254         false
49255     ],
49256     "MPL-2.0-no-copyleft-exception": [
49257         "Mozilla Public License 2.0 (no copyleft exception)",
49258         true,
49259         false
49260     ],
49261     "MS-PL": [
49262         "Microsoft Public License",
49263         true,
49264         false
49265     ],
49266     "MS-RL": [
49267         "Microsoft Reciprocal License",
49268         true,
49269         false
49270     ],
49271     "MTLL": [
49272         "Matrix Template Library License",
49273         false,
49274         false
49275     ],
49276     "Multics": [
49277         "Multics License",
49278         true,
49279         false
49280     ],
49281     "Mup": [
49282         "Mup License",
49283         false,
49284         false
49285     ],
49286     "NASA-1.3": [
49287         "NASA Open Source Agreement 1.3",
49288         true,
49289         false
49290     ],
49291     "Naumen": [
49292         "Naumen Public License",
49293         true,
49294         false
49295     ],
49296     "NBPL-1.0": [
49297         "Net Boolean Public License v1",
49298         false,
49299         false
49300     ],
49301     "NCSA": [
49302         "University of Illinois/NCSA Open Source License",
49303         true,
49304         false
49305     ],
49306     "Net-SNMP": [
49307         "Net-SNMP License",
49308         false,
49309         false
49310     ],
49311     "NetCDF": [
49312         "NetCDF license",
49313         false,
49314         false
49315     ],
49316     "Newsletr": [
49317         "Newsletr License",
49318         false,
49319         false
49320     ],
49321     "NGPL": [
49322         "Nethack General Public License",
49323         true,
49324         false
49325     ],
49326     "NLOD-1.0": [
49327         "Norwegian Licence for Open Government Data",
49328         false,
49329         false
49330     ],
49331     "NLPL": [
49332         "No Limit Public License",
49333         false,
49334         false
49335     ],
49336     "Nokia": [
49337         "Nokia Open Source License",
49338         true,
49339         false
49340     ],
49341     "NOSL": [
49342         "Netizen Open Source License",
49343         false,
49344         false
49345     ],
49346     "Noweb": [
49347         "Noweb License",
49348         false,
49349         false
49350     ],
49351     "NPL-1.0": [
49352         "Netscape Public License v1.0",
49353         false,
49354         false
49355     ],
49356     "NPL-1.1": [
49357         "Netscape Public License v1.1",
49358         false,
49359         false
49360     ],
49361     "NPOSL-3.0": [
49362         "Non-Profit Open Software License 3.0",
49363         true,
49364         false
49365     ],
49366     "NRL": [
49367         "NRL License",
49368         false,
49369         false
49370     ],
49371     "NTP": [
49372         "NTP License",
49373         true,
49374         false
49375     ],
49376     "Nunit": [
49377         "Nunit License",
49378         false,
49379         true
49380     ],
49381     "OCCT-PL": [
49382         "Open CASCADE Technology Public License",
49383         false,
49384         false
49385     ],
49386     "OCLC-2.0": [
49387         "OCLC Research Public License 2.0",
49388         true,
49389         false
49390     ],
49391     "ODbL-1.0": [
49392         "ODC Open Database License v1.0",
49393         false,
49394         false
49395     ],
49396     "ODC-By-1.0": [
49397         "Open Data Commons Attribution License v1.0",
49398         false,
49399         false
49400     ],
49401     "OFL-1.0": [
49402         "SIL Open Font License 1.0",
49403         false,
49404         false
49405     ],
49406     "OFL-1.1": [
49407         "SIL Open Font License 1.1",
49408         true,
49409         false
49410     ],
49411     "OGL-UK-1.0": [
49412         "Open Government Licence v1.0",
49413         false,
49414         false
49415     ],
49416     "OGL-UK-2.0": [
49417         "Open Government Licence v2.0",
49418         false,
49419         false
49420     ],
49421     "OGL-UK-3.0": [
49422         "Open Government Licence v3.0",
49423         false,
49424         false
49425     ],
49426     "OGTSL": [
49427         "Open Group Test Suite License",
49428         true,
49429         false
49430     ],
49431     "OLDAP-1.1": [
49432         "Open LDAP Public License v1.1",
49433         false,
49434         false
49435     ],
49436     "OLDAP-1.2": [
49437         "Open LDAP Public License v1.2",
49438         false,
49439         false
49440     ],
49441     "OLDAP-1.3": [
49442         "Open LDAP Public License v1.3",
49443         false,
49444         false
49445     ],
49446     "OLDAP-1.4": [
49447         "Open LDAP Public License v1.4",
49448         false,
49449         false
49450     ],
49451     "OLDAP-2.0": [
49452         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
49453         false,
49454         false
49455     ],
49456     "OLDAP-2.0.1": [
49457         "Open LDAP Public License v2.0.1",
49458         false,
49459         false
49460     ],
49461     "OLDAP-2.1": [
49462         "Open LDAP Public License v2.1",
49463         false,
49464         false
49465     ],
49466     "OLDAP-2.2": [
49467         "Open LDAP Public License v2.2",
49468         false,
49469         false
49470     ],
49471     "OLDAP-2.2.1": [
49472         "Open LDAP Public License v2.2.1",
49473         false,
49474         false
49475     ],
49476     "OLDAP-2.2.2": [
49477         "Open LDAP Public License 2.2.2",
49478         false,
49479         false
49480     ],
49481     "OLDAP-2.3": [
49482         "Open LDAP Public License v2.3",
49483         false,
49484         false
49485     ],
49486     "OLDAP-2.4": [
49487         "Open LDAP Public License v2.4",
49488         false,
49489         false
49490     ],
49491     "OLDAP-2.5": [
49492         "Open LDAP Public License v2.5",
49493         false,
49494         false
49495     ],
49496     "OLDAP-2.6": [
49497         "Open LDAP Public License v2.6",
49498         false,
49499         false
49500     ],
49501     "OLDAP-2.7": [
49502         "Open LDAP Public License v2.7",
49503         false,
49504         false
49505     ],
49506     "OLDAP-2.8": [
49507         "Open LDAP Public License v2.8",
49508         false,
49509         false
49510     ],
49511     "OML": [
49512         "Open Market License",
49513         false,
49514         false
49515     ],
49516     "OpenSSL": [
49517         "OpenSSL License",
49518         false,
49519         false
49520     ],
49521     "OPL-1.0": [
49522         "Open Public License v1.0",
49523         false,
49524         false
49525     ],
49526     "OSET-PL-2.1": [
49527         "OSET Public License version 2.1",
49528         true,
49529         false
49530     ],
49531     "OSL-1.0": [
49532         "Open Software License 1.0",
49533         true,
49534         false
49535     ],
49536     "OSL-1.1": [
49537         "Open Software License 1.1",
49538         false,
49539         false
49540     ],
49541     "OSL-2.0": [
49542         "Open Software License 2.0",
49543         true,
49544         false
49545     ],
49546     "OSL-2.1": [
49547         "Open Software License 2.1",
49548         true,
49549         false
49550     ],
49551     "OSL-3.0": [
49552         "Open Software License 3.0",
49553         true,
49554         false
49555     ],
49556     "Parity-6.0.0": [
49557         "The Parity Public License 6.0.0",
49558         false,
49559         false
49560     ],
49561     "PDDL-1.0": [
49562         "ODC Public Domain Dedication & License 1.0",
49563         false,
49564         false
49565     ],
49566     "PHP-3.0": [
49567         "PHP License v3.0",
49568         true,
49569         false
49570     ],
49571     "PHP-3.01": [
49572         "PHP License v3.01",
49573         false,
49574         false
49575     ],
49576     "Plexus": [
49577         "Plexus Classworlds License",
49578         false,
49579         false
49580     ],
49581     "PostgreSQL": [
49582         "PostgreSQL License",
49583         true,
49584         false
49585     ],
49586     "psfrag": [
49587         "psfrag License",
49588         false,
49589         false
49590     ],
49591     "psutils": [
49592         "psutils License",
49593         false,
49594         false
49595     ],
49596     "Python-2.0": [
49597         "Python License 2.0",
49598         true,
49599         false
49600     ],
49601     "Qhull": [
49602         "Qhull License",
49603         false,
49604         false
49605     ],
49606     "QPL-1.0": [
49607         "Q Public License 1.0",
49608         true,
49609         false
49610     ],
49611     "Rdisc": [
49612         "Rdisc License",
49613         false,
49614         false
49615     ],
49616     "RHeCos-1.1": [
49617         "Red Hat eCos Public License v1.1",
49618         false,
49619         false
49620     ],
49621     "RPL-1.1": [
49622         "Reciprocal Public License 1.1",
49623         true,
49624         false
49625     ],
49626     "RPL-1.5": [
49627         "Reciprocal Public License 1.5",
49628         true,
49629         false
49630     ],
49631     "RPSL-1.0": [
49632         "RealNetworks Public Source License v1.0",
49633         true,
49634         false
49635     ],
49636     "RSA-MD": [
49637         "RSA Message-Digest License",
49638         false,
49639         false
49640     ],
49641     "RSCPL": [
49642         "Ricoh Source Code Public License",
49643         true,
49644         false
49645     ],
49646     "Ruby": [
49647         "Ruby License",
49648         false,
49649         false
49650     ],
49651     "SAX-PD": [
49652         "Sax Public Domain Notice",
49653         false,
49654         false
49655     ],
49656     "Saxpath": [
49657         "Saxpath License",
49658         false,
49659         false
49660     ],
49661     "SCEA": [
49662         "SCEA Shared Source License",
49663         false,
49664         false
49665     ],
49666     "Sendmail": [
49667         "Sendmail License",
49668         false,
49669         false
49670     ],
49671     "Sendmail-8.23": [
49672         "Sendmail License 8.23",
49673         false,
49674         false
49675     ],
49676     "SGI-B-1.0": [
49677         "SGI Free Software License B v1.0",
49678         false,
49679         false
49680     ],
49681     "SGI-B-1.1": [
49682         "SGI Free Software License B v1.1",
49683         false,
49684         false
49685     ],
49686     "SGI-B-2.0": [
49687         "SGI Free Software License B v2.0",
49688         false,
49689         false
49690     ],
49691     "SHL-0.5": [
49692         "Solderpad Hardware License v0.5",
49693         false,
49694         false
49695     ],
49696     "SHL-0.51": [
49697         "Solderpad Hardware License, Version 0.51",
49698         false,
49699         false
49700     ],
49701     "SimPL-2.0": [
49702         "Simple Public License 2.0",
49703         true,
49704         false
49705     ],
49706     "SISSL": [
49707         "Sun Industry Standards Source License v1.1",
49708         true,
49709         false
49710     ],
49711     "SISSL-1.2": [
49712         "Sun Industry Standards Source License v1.2",
49713         false,
49714         false
49715     ],
49716     "Sleepycat": [
49717         "Sleepycat License",
49718         true,
49719         false
49720     ],
49721     "SMLNJ": [
49722         "Standard ML of New Jersey License",
49723         false,
49724         false
49725     ],
49726     "SMPPL": [
49727         "Secure Messaging Protocol Public License",
49728         false,
49729         false
49730     ],
49731     "SNIA": [
49732         "SNIA Public License 1.1",
49733         false,
49734         false
49735     ],
49736     "Spencer-86": [
49737         "Spencer License 86",
49738         false,
49739         false
49740     ],
49741     "Spencer-94": [
49742         "Spencer License 94",
49743         false,
49744         false
49745     ],
49746     "Spencer-99": [
49747         "Spencer License 99",
49748         false,
49749         false
49750     ],
49751     "SPL-1.0": [
49752         "Sun Public License v1.0",
49753         true,
49754         false
49755     ],
49756     "SSPL-1.0": [
49757         "Server Side Public License, v 1",
49758         false,
49759         false
49760     ],
49761     "StandardML-NJ": [
49762         "Standard ML of New Jersey License",
49763         false,
49764         true
49765     ],
49766     "SugarCRM-1.1.3": [
49767         "SugarCRM Public License v1.1.3",
49768         false,
49769         false
49770     ],
49771     "SWL": [
49772         "Scheme Widget Library (SWL) Software License Agreement",
49773         false,
49774         false
49775     ],
49776     "TAPR-OHL-1.0": [
49777         "TAPR Open Hardware License v1.0",
49778         false,
49779         false
49780     ],
49781     "TCL": [
49782         "TCL/TK License",
49783         false,
49784         false
49785     ],
49786     "TCP-wrappers": [
49787         "TCP Wrappers License",
49788         false,
49789         false
49790     ],
49791     "TMate": [
49792         "TMate Open Source License",
49793         false,
49794         false
49795     ],
49796     "TORQUE-1.1": [
49797         "TORQUE v2.5+ Software License v1.1",
49798         false,
49799         false
49800     ],
49801     "TOSL": [
49802         "Trusster Open Source License",
49803         false,
49804         false
49805     ],
49806     "TU-Berlin-1.0": [
49807         "Technische Universitaet Berlin License 1.0",
49808         false,
49809         false
49810     ],
49811     "TU-Berlin-2.0": [
49812         "Technische Universitaet Berlin License 2.0",
49813         false,
49814         false
49815     ],
49816     "Unicode-DFS-2015": [
49817         "Unicode License Agreement - Data Files and Software (2015)",
49818         false,
49819         false
49820     ],
49821     "Unicode-DFS-2016": [
49822         "Unicode License Agreement - Data Files and Software (2016)",
49823         false,
49824         false
49825     ],
49826     "Unicode-TOU": [
49827         "Unicode Terms of Use",
49828         false,
49829         false
49830     ],
49831     "Unlicense": [
49832         "The Unlicense",
49833         false,
49834         false
49835     ],
49836     "UPL-1.0": [
49837         "Universal Permissive License v1.0",
49838         true,
49839         false
49840     ],
49841     "Vim": [
49842         "Vim License",
49843         false,
49844         false
49845     ],
49846     "VOSTROM": [
49847         "VOSTROM Public License for Open Source",
49848         false,
49849         false
49850     ],
49851     "VSL-1.0": [
49852         "Vovida Software License v1.0",
49853         true,
49854         false
49855     ],
49856     "W3C": [
49857         "W3C Software Notice and License (2002-12-31)",
49858         true,
49859         false
49860     ],
49861     "W3C-19980720": [
49862         "W3C Software Notice and License (1998-07-20)",
49863         false,
49864         false
49865     ],
49866     "W3C-20150513": [
49867         "W3C Software Notice and Document License (2015-05-13)",
49868         false,
49869         false
49870     ],
49871     "Watcom-1.0": [
49872         "Sybase Open Watcom Public License 1.0",
49873         true,
49874         false
49875     ],
49876     "Wsuipa": [
49877         "Wsuipa License",
49878         false,
49879         false
49880     ],
49881     "WTFPL": [
49882         "Do What The F*ck You Want To Public License",
49883         false,
49884         false
49885     ],
49886     "wxWindows": [
49887         "wxWindows Library License",
49888         false,
49889         true
49890     ],
49891     "X11": [
49892         "X11 License",
49893         false,
49894         false
49895     ],
49896     "Xerox": [
49897         "Xerox License",
49898         false,
49899         false
49900     ],
49901     "XFree86-1.1": [
49902         "XFree86 License 1.1",
49903         false,
49904         false
49905     ],
49906     "xinetd": [
49907         "xinetd License",
49908         false,
49909         false
49910     ],
49911     "Xnet": [
49912         "X.Net License",
49913         true,
49914         false
49915     ],
49916     "xpp": [
49917         "XPP License",
49918         false,
49919         false
49920     ],
49921     "XSkat": [
49922         "XSkat License",
49923         false,
49924         false
49925     ],
49926     "YPL-1.0": [
49927         "Yahoo! Public License v1.0",
49928         false,
49929         false
49930     ],
49931     "YPL-1.1": [
49932         "Yahoo! Public License v1.1",
49933         false,
49934         false
49935     ],
49936     "Zed": [
49937         "Zed License",
49938         false,
49939         false
49940     ],
49941     "Zend-2.0": [
49942         "Zend License v2.0",
49943         false,
49944         false
49945     ],
49946     "Zimbra-1.3": [
49947         "Zimbra Public License v1.3",
49948         false,
49949         false
49950     ],
49951     "Zimbra-1.4": [
49952         "Zimbra Public License v1.4",
49953         false,
49954         false
49955     ],
49956     "Zlib": [
49957         "zlib License",
49958         true,
49959         false
49960     ],
49961     "zlib-acknowledgement": [
49962         "zlib/libpng License with Acknowledgement",
49963         false,
49964         false
49965     ],
49966     "ZPL-1.1": [
49967         "Zope Public License 1.1",
49968         false,
49969         false
49970     ],
49971     "ZPL-2.0": [
49972         "Zope Public License 2.0",
49973         true,
49974         false
49975     ],
49976     "ZPL-2.1": [
49977         "Zope Public License 2.1",
49978         false,
49979         false
49980     ]
49981 }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
49982 $\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
49983 \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
49984 \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
49985 \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
49986 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
49987 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
49988 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
49989   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
49990     <security>\r
49991       <requestedPrivileges>\r
49992         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
49993       </requestedPrivileges>\r
49994     </security>\r
49995   </trustInfo>\r
49996   <dependency>\r
49997     <dependentAssembly>\r
49998       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
49999     </dependentAssembly>\r
50000   </dependency>\r
50001 </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
50002
50003
50004
50005
50006
50007
50008
50009
50010
50011
50012 namespace Symfony\Component\Console;
50013
50014 use Symfony\Component\Console\Command\Command;
50015 use Symfony\Component\Console\Command\HelpCommand;
50016 use Symfony\Component\Console\Command\ListCommand;
50017 use Symfony\Component\Console\Descriptor\TextDescriptor;
50018 use Symfony\Component\Console\Descriptor\XmlDescriptor;
50019 use Symfony\Component\Console\Event\ConsoleCommandEvent;
50020 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
50021 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
50022 use Symfony\Component\Console\Exception\CommandNotFoundException;
50023 use Symfony\Component\Console\Exception\ExceptionInterface;
50024 use Symfony\Component\Console\Exception\LogicException;
50025 use Symfony\Component\Console\Formatter\OutputFormatter;
50026 use Symfony\Component\Console\Helper\DebugFormatterHelper;
50027 use Symfony\Component\Console\Helper\DialogHelper;
50028 use Symfony\Component\Console\Helper\FormatterHelper;
50029 use Symfony\Component\Console\Helper\Helper;
50030 use Symfony\Component\Console\Helper\HelperSet;
50031 use Symfony\Component\Console\Helper\ProcessHelper;
50032 use Symfony\Component\Console\Helper\ProgressHelper;
50033 use Symfony\Component\Console\Helper\QuestionHelper;
50034 use Symfony\Component\Console\Helper\TableHelper;
50035 use Symfony\Component\Console\Input\ArgvInput;
50036 use Symfony\Component\Console\Input\ArrayInput;
50037 use Symfony\Component\Console\Input\InputArgument;
50038 use Symfony\Component\Console\Input\InputAwareInterface;
50039 use Symfony\Component\Console\Input\InputDefinition;
50040 use Symfony\Component\Console\Input\InputInterface;
50041 use Symfony\Component\Console\Input\InputOption;
50042 use Symfony\Component\Console\Output\BufferedOutput;
50043 use Symfony\Component\Console\Output\ConsoleOutput;
50044 use Symfony\Component\Console\Output\ConsoleOutputInterface;
50045 use Symfony\Component\Console\Output\OutputInterface;
50046 use Symfony\Component\Debug\Exception\FatalThrowableError;
50047 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
50048
50049
50050
50051
50052
50053
50054
50055
50056
50057
50058
50059
50060
50061
50062
50063
50064 class Application
50065 {
50066 private $commands = array();
50067 private $wantHelps = false;
50068 private $runningCommand;
50069 private $name;
50070 private $version;
50071 private $catchExceptions = true;
50072 private $autoExit = true;
50073 private $definition;
50074 private $helperSet;
50075 private $dispatcher;
50076 private $terminalDimensions;
50077 private $defaultCommand;
50078 private $initialized;
50079
50080
50081
50082
50083
50084 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
50085 {
50086 $this->name = $name;
50087 $this->version = $version;
50088 $this->defaultCommand = 'list';
50089 }
50090
50091 public function setDispatcher(EventDispatcherInterface $dispatcher)
50092 {
50093 $this->dispatcher = $dispatcher;
50094 }
50095
50096
50097
50098
50099
50100
50101
50102
50103 public function run(InputInterface $input = null, OutputInterface $output = null)
50104 {
50105 if (null === $input) {
50106 $input = new ArgvInput();
50107 }
50108
50109 if (null === $output) {
50110 $output = new ConsoleOutput();
50111 }
50112
50113 $this->configureIO($input, $output);
50114
50115 try {
50116 $e = null;
50117 $exitCode = $this->doRun($input, $output);
50118 } catch (\Exception $e) {
50119 }
50120
50121 if (null !== $e) {
50122 if (!$this->catchExceptions) {
50123 throw $e;
50124 }
50125
50126 if ($output instanceof ConsoleOutputInterface) {
50127 $this->renderException($e, $output->getErrorOutput());
50128 } else {
50129 $this->renderException($e, $output);
50130 }
50131
50132 $exitCode = $this->getExitCodeForThrowable($e);
50133 }
50134
50135 if ($this->autoExit) {
50136 if ($exitCode > 255) {
50137 $exitCode = 255;
50138 }
50139
50140 exit($exitCode);
50141 }
50142
50143 return $exitCode;
50144 }
50145
50146
50147
50148
50149
50150
50151 public function doRun(InputInterface $input, OutputInterface $output)
50152 {
50153 if (true === $input->hasParameterOption(array('--version', '-V'))) {
50154 $output->writeln($this->getLongVersion());
50155
50156 return 0;
50157 }
50158
50159 $name = $this->getCommandName($input);
50160 if (true === $input->hasParameterOption(array('--help', '-h'))) {
50161 if (!$name) {
50162 $name = 'help';
50163 $input = new ArrayInput(array('command' => 'help'));
50164 } else {
50165 $this->wantHelps = true;
50166 }
50167 }
50168
50169 if (!$name) {
50170 $name = $this->defaultCommand;
50171 $definition = $this->getDefinition();
50172 $definition->setArguments(array_merge(
50173 $definition->getArguments(),
50174 array(
50175 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
50176 )
50177 ));
50178 }
50179
50180 $this->runningCommand = null;
50181
50182  $command = $this->find($name);
50183
50184 $this->runningCommand = $command;
50185 $exitCode = $this->doRunCommand($command, $input, $output);
50186 $this->runningCommand = null;
50187
50188 return $exitCode;
50189 }
50190
50191 public function setHelperSet(HelperSet $helperSet)
50192 {
50193 $this->helperSet = $helperSet;
50194 }
50195
50196
50197
50198
50199
50200
50201 public function getHelperSet()
50202 {
50203 if (!$this->helperSet) {
50204 $this->helperSet = $this->getDefaultHelperSet();
50205 }
50206
50207 return $this->helperSet;
50208 }
50209
50210 public function setDefinition(InputDefinition $definition)
50211 {
50212 $this->definition = $definition;
50213 }
50214
50215
50216
50217
50218
50219
50220 public function getDefinition()
50221 {
50222 if (!$this->definition) {
50223 $this->definition = $this->getDefaultInputDefinition();
50224 }
50225
50226 return $this->definition;
50227 }
50228
50229
50230
50231
50232
50233
50234 public function getHelp()
50235 {
50236 return $this->getLongVersion();
50237 }
50238
50239
50240
50241
50242
50243
50244 public function setCatchExceptions($boolean)
50245 {
50246 $this->catchExceptions = (bool) $boolean;
50247 }
50248
50249
50250
50251
50252
50253
50254 public function setAutoExit($boolean)
50255 {
50256 $this->autoExit = (bool) $boolean;
50257 }
50258
50259
50260
50261
50262
50263
50264 public function getName()
50265 {
50266 return $this->name;
50267 }
50268
50269
50270
50271
50272
50273
50274 public function setName($name)
50275 {
50276 $this->name = $name;
50277 }
50278
50279
50280
50281
50282
50283
50284 public function getVersion()
50285 {
50286 return $this->version;
50287 }
50288
50289
50290
50291
50292
50293
50294 public function setVersion($version)
50295 {
50296 $this->version = $version;
50297 }
50298
50299
50300
50301
50302
50303
50304 public function getLongVersion()
50305 {
50306 if ('UNKNOWN' !== $this->getName()) {
50307 if ('UNKNOWN' !== $this->getVersion()) {
50308 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
50309 }
50310
50311 return sprintf('<info>%s</info>', $this->getName());
50312 }
50313
50314 return '<info>Console Tool</info>';
50315 }
50316
50317
50318
50319
50320
50321
50322
50323
50324 public function register($name)
50325 {
50326 return $this->add(new Command($name));
50327 }
50328
50329
50330
50331
50332
50333
50334
50335
50336 public function addCommands(array $commands)
50337 {
50338 foreach ($commands as $command) {
50339 $this->add($command);
50340 }
50341 }
50342
50343
50344
50345
50346
50347
50348
50349
50350
50351 public function add(Command $command)
50352 {
50353 $this->init();
50354
50355 $command->setApplication($this);
50356
50357 if (!$command->isEnabled()) {
50358 $command->setApplication(null);
50359
50360 return;
50361 }
50362
50363 if (null === $command->getDefinition()) {
50364 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($command)));
50365 }
50366
50367 $this->commands[$command->getName()] = $command;
50368
50369 foreach ($command->getAliases() as $alias) {
50370 $this->commands[$alias] = $command;
50371 }
50372
50373 return $command;
50374 }
50375
50376
50377
50378
50379
50380
50381
50382
50383
50384
50385 public function get($name)
50386 {
50387 $this->init();
50388
50389 if (!isset($this->commands[$name])) {
50390 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
50391 }
50392
50393 $command = $this->commands[$name];
50394
50395 if ($this->wantHelps) {
50396 $this->wantHelps = false;
50397
50398 $helpCommand = $this->get('help');
50399 $helpCommand->setCommand($command);
50400
50401 return $helpCommand;
50402 }
50403
50404 return $command;
50405 }
50406
50407
50408
50409
50410
50411
50412
50413
50414 public function has($name)
50415 {
50416 $this->init();
50417
50418 return isset($this->commands[$name]);
50419 }
50420
50421
50422
50423
50424
50425
50426
50427
50428 public function getNamespaces()
50429 {
50430 $namespaces = array();
50431 foreach ($this->all() as $command) {
50432 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
50433
50434 foreach ($command->getAliases() as $alias) {
50435 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
50436 }
50437 }
50438
50439 return array_values(array_unique(array_filter($namespaces)));
50440 }
50441
50442
50443
50444
50445
50446
50447
50448
50449
50450
50451 public function findNamespace($namespace)
50452 {
50453 $allNamespaces = $this->getNamespaces();
50454 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
50455 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
50456
50457 if (empty($namespaces)) {
50458 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
50459
50460 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
50461 if (1 == \count($alternatives)) {
50462 $message .= "\n\nDid you mean this?\n    ";
50463 } else {
50464 $message .= "\n\nDid you mean one of these?\n    ";
50465 }
50466
50467 $message .= implode("\n    ", $alternatives);
50468 }
50469
50470 throw new CommandNotFoundException($message, $alternatives);
50471 }
50472
50473 $exact = \in_array($namespace, $namespaces, true);
50474 if (\count($namespaces) > 1 && !$exact) {
50475 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
50476 }
50477
50478 return $exact ? $namespace : reset($namespaces);
50479 }
50480
50481
50482
50483
50484
50485
50486
50487
50488
50489
50490
50491
50492
50493 public function find($name)
50494 {
50495 $this->init();
50496 $aliases = array();
50497 $allCommands = array_keys($this->commands);
50498 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
50499 $commands = preg_grep('{^'.$expr.'}', $allCommands);
50500
50501 if (empty($commands) || \count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
50502 if (false !== $pos = strrpos($name, ':')) {
50503
50504  $this->findNamespace(substr($name, 0, $pos));
50505 }
50506
50507 $message = sprintf('Command "%s" is not defined.', $name);
50508
50509 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
50510 if (1 == \count($alternatives)) {
50511 $message .= "\n\nDid you mean this?\n    ";
50512 } else {
50513 $message .= "\n\nDid you mean one of these?\n    ";
50514 }
50515 $message .= implode("\n    ", $alternatives);
50516 }
50517
50518 throw new CommandNotFoundException($message, $alternatives);
50519 }
50520
50521
50522  if (\count($commands) > 1) {
50523 $commandList = $this->commands;
50524 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
50525 $commandName = $commandList[$nameOrAlias]->getName();
50526 $aliases[$nameOrAlias] = $commandName;
50527
50528 return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
50529 });
50530 }
50531
50532 $exact = \in_array($name, $commands, true) || isset($aliases[$name]);
50533 if (!$exact && \count($commands) > 1) {
50534 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
50535
50536 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
50537 }
50538
50539 return $this->get($exact ? $name : reset($commands));
50540 }
50541
50542
50543
50544
50545
50546
50547
50548
50549
50550
50551 public function all($namespace = null)
50552 {
50553 $this->init();
50554
50555 if (null === $namespace) {
50556 return $this->commands;
50557 }
50558
50559 $commands = array();
50560 foreach ($this->commands as $name => $command) {
50561 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
50562 $commands[$name] = $command;
50563 }
50564 }
50565
50566 return $commands;
50567 }
50568
50569
50570
50571
50572
50573
50574
50575
50576 public static function getAbbreviations($names)
50577 {
50578 $abbrevs = array();
50579 foreach ($names as $name) {
50580 for ($len = \strlen($name); $len > 0; --$len) {
50581 $abbrev = substr($name, 0, $len);
50582 $abbrevs[$abbrev][] = $name;
50583 }
50584 }
50585
50586 return $abbrevs;
50587 }
50588
50589
50590
50591
50592
50593
50594
50595
50596
50597
50598
50599 public function asText($namespace = null, $raw = false)
50600 {
50601 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
50602
50603 $descriptor = new TextDescriptor();
50604 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
50605 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
50606
50607 return $output->fetch();
50608 }
50609
50610
50611
50612
50613
50614
50615
50616
50617
50618
50619
50620 public function asXml($namespace = null, $asDom = false)
50621 {
50622 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
50623
50624 $descriptor = new XmlDescriptor();
50625
50626 if ($asDom) {
50627 return $descriptor->getApplicationDocument($this, $namespace);
50628 }
50629
50630 $output = new BufferedOutput();
50631 $descriptor->describe($output, $this, array('namespace' => $namespace));
50632
50633 return $output->fetch();
50634 }
50635
50636
50637
50638
50639 public function renderException($e, $output)
50640 {
50641 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
50642
50643 do {
50644 $title = sprintf('  [%s]  ', \get_class($e));
50645
50646 $len = Helper::strlen($title);
50647
50648 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
50649
50650  if (\defined('HHVM_VERSION') && $width > 1 << 31) {
50651 $width = 1 << 31;
50652 }
50653 $lines = array();
50654 foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) {
50655 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
50656
50657  $lineLength = Helper::strlen($line) + 4;
50658 $lines[] = array($line, $lineLength);
50659
50660 $len = max($lineLength, $len);
50661 }
50662 }
50663
50664 $messages = array();
50665 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
50666 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
50667 foreach ($lines as $line) {
50668 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
50669 }
50670 $messages[] = $emptyLine;
50671 $messages[] = '';
50672
50673 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
50674
50675 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
50676 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
50677
50678
50679  $trace = $e->getTrace();
50680 array_unshift($trace, array(
50681 'function' => '',
50682 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a',
50683 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a',
50684 'args' => array(),
50685 ));
50686
50687 for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
50688 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
50689 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
50690 $function = $trace[$i]['function'];
50691 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
50692 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
50693
50694 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
50695 }
50696
50697 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
50698 }
50699 } while ($e = $e->getPrevious());
50700
50701 if (null !== $this->runningCommand) {
50702 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
50703 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
50704 }
50705 }
50706
50707
50708
50709
50710
50711
50712 protected function getTerminalWidth()
50713 {
50714 $dimensions = $this->getTerminalDimensions();
50715
50716 return $dimensions[0];
50717 }
50718
50719
50720
50721
50722
50723
50724 protected function getTerminalHeight()
50725 {
50726 $dimensions = $this->getTerminalDimensions();
50727
50728 return $dimensions[1];
50729 }
50730
50731
50732
50733
50734
50735
50736 public function getTerminalDimensions()
50737 {
50738 if ($this->terminalDimensions) {
50739 return $this->terminalDimensions;
50740 }
50741
50742 if ('\\' === \DIRECTORY_SEPARATOR) {
50743
50744  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
50745 return array((int) $matches[1], (int) $matches[2]);
50746 }
50747
50748  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
50749 return array((int) $matches[1], (int) $matches[2]);
50750 }
50751 }
50752
50753 if ($sttyString = $this->getSttyColumns()) {
50754
50755  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
50756 return array((int) $matches[2], (int) $matches[1]);
50757 }
50758
50759  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
50760 return array((int) $matches[2], (int) $matches[1]);
50761 }
50762 }
50763
50764 return array(null, null);
50765 }
50766
50767
50768
50769
50770
50771
50772
50773
50774
50775
50776
50777 public function setTerminalDimensions($width, $height)
50778 {
50779 $this->terminalDimensions = array($width, $height);
50780
50781 return $this;
50782 }
50783
50784
50785
50786
50787 protected function configureIO(InputInterface $input, OutputInterface $output)
50788 {
50789 if (true === $input->hasParameterOption(array('--ansi'))) {
50790 $output->setDecorated(true);
50791 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
50792 $output->setDecorated(false);
50793 }
50794
50795 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
50796 $input->setInteractive(false);
50797 } elseif (\function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
50798 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
50799 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
50800 $input->setInteractive(false);
50801 }
50802 }
50803
50804 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
50805 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
50806 $input->setInteractive(false);
50807 } else {
50808 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) {
50809 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
50810 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) {
50811 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
50812 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
50813 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
50814 }
50815 }
50816 }
50817
50818
50819
50820
50821
50822
50823
50824
50825
50826 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
50827 {
50828 foreach ($command->getHelperSet() as $helper) {
50829 if ($helper instanceof InputAwareInterface) {
50830 $helper->setInput($input);
50831 }
50832 }
50833
50834 if (null === $this->dispatcher) {
50835 return $command->run($input, $output);
50836 }
50837
50838
50839  try {
50840 $command->mergeApplicationDefinition();
50841 $input->bind($command->getDefinition());
50842 } catch (ExceptionInterface $e) {
50843
50844  }
50845
50846 $event = new ConsoleCommandEvent($command, $input, $output);
50847 $e = null;
50848
50849 try {
50850 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
50851
50852 if ($event->commandShouldRun()) {
50853 $exitCode = $command->run($input, $output);
50854 } else {
50855 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
50856 }
50857 } catch (\Exception $e) {
50858 } catch (\Throwable $e) {
50859 }
50860 if (null !== $e) {
50861 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
50862 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
50863 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
50864
50865 if ($x !== $event->getException()) {
50866 $e = $event->getException();
50867 }
50868
50869 $exitCode = $this->getExitCodeForThrowable($e);
50870 }
50871
50872 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
50873 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
50874
50875 if (null !== $e) {
50876 throw $e;
50877 }
50878
50879 return $event->getExitCode();
50880 }
50881
50882
50883
50884
50885
50886
50887 protected function getCommandName(InputInterface $input)
50888 {
50889 return $input->getFirstArgument();
50890 }
50891
50892
50893
50894
50895
50896
50897 protected function getDefaultInputDefinition()
50898 {
50899 return new InputDefinition(array(
50900 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
50901
50902 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
50903 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
50904 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'),
50905 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
50906 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
50907 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
50908 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
50909 ));
50910 }
50911
50912
50913
50914
50915
50916
50917 protected function getDefaultCommands()
50918 {
50919 return array(new HelpCommand(), new ListCommand());
50920 }
50921
50922
50923
50924
50925
50926
50927 protected function getDefaultHelperSet()
50928 {
50929 return new HelperSet(array(
50930 new FormatterHelper(),
50931 new DialogHelper(false),
50932 new ProgressHelper(false),
50933 new TableHelper(false),
50934 new DebugFormatterHelper(),
50935 new ProcessHelper(),
50936 new QuestionHelper(),
50937 ));
50938 }
50939
50940
50941
50942
50943
50944
50945 private function getSttyColumns()
50946 {
50947 if (!\function_exists('proc_open')) {
50948 return;
50949 }
50950
50951 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
50952 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
50953 if (\is_resource($process)) {
50954 $info = stream_get_contents($pipes[1]);
50955 fclose($pipes[1]);
50956 fclose($pipes[2]);
50957 proc_close($process);
50958
50959 return $info;
50960 }
50961 }
50962
50963
50964
50965
50966
50967
50968 private function getConsoleMode()
50969 {
50970 if (!\function_exists('proc_open')) {
50971 return;
50972 }
50973
50974 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
50975 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
50976 if (\is_resource($process)) {
50977 $info = stream_get_contents($pipes[1]);
50978 fclose($pipes[1]);
50979 fclose($pipes[2]);
50980 proc_close($process);
50981
50982 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
50983 return $matches[2].'x'.$matches[1];
50984 }
50985 }
50986 }
50987
50988
50989
50990
50991
50992
50993
50994
50995 private function getAbbreviationSuggestions($abbrevs)
50996 {
50997 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], \count($abbrevs) > 2 ? sprintf(' and %d more', \count($abbrevs) - 2) : '');
50998 }
50999
51000
51001
51002
51003
51004
51005
51006
51007
51008
51009
51010 public function extractNamespace($name, $limit = null)
51011 {
51012 $parts = explode(':', $name);
51013 array_pop($parts);
51014
51015 return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
51016 }
51017
51018
51019
51020
51021
51022
51023
51024
51025
51026
51027 private function findAlternatives($name, $collection)
51028 {
51029 $threshold = 1e3;
51030 $alternatives = array();
51031
51032 $collectionParts = array();
51033 foreach ($collection as $item) {
51034 $collectionParts[$item] = explode(':', $item);
51035 }
51036
51037 foreach (explode(':', $name) as $i => $subname) {
51038 foreach ($collectionParts as $collectionName => $parts) {
51039 $exists = isset($alternatives[$collectionName]);
51040 if (!isset($parts[$i]) && $exists) {
51041 $alternatives[$collectionName] += $threshold;
51042 continue;
51043 } elseif (!isset($parts[$i])) {
51044 continue;
51045 }
51046
51047 $lev = levenshtein($subname, $parts[$i]);
51048 if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
51049 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
51050 } elseif ($exists) {
51051 $alternatives[$collectionName] += $threshold;
51052 }
51053 }
51054 }
51055
51056 foreach ($collection as $item) {
51057 $lev = levenshtein($name, $item);
51058 if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) {
51059 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
51060 }
51061 }
51062
51063 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
51064 asort($alternatives);
51065
51066 return array_keys($alternatives);
51067 }
51068
51069
51070
51071
51072
51073
51074 public function setDefaultCommand($commandName)
51075 {
51076 $this->defaultCommand = $commandName;
51077 }
51078
51079 private function splitStringByWidth($string, $width)
51080 {
51081
51082  
51083  
51084  if (false === $encoding = mb_detect_encoding($string, null, true)) {
51085 return str_split($string, $width);
51086 }
51087
51088 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
51089 $lines = array();
51090 $line = '';
51091 foreach (preg_split('//u', $utf8String) as $char) {
51092
51093  if (mb_strwidth($line.$char, 'utf8') <= $width) {
51094 $line .= $char;
51095 continue;
51096 }
51097
51098  $lines[] = str_pad($line, $width);
51099 $line = $char;
51100 }
51101
51102 $lines[] = \count($lines) ? str_pad($line, $width) : $line;
51103
51104 mb_convert_variables($encoding, 'utf8', $lines);
51105
51106 return $lines;
51107 }
51108
51109
51110
51111
51112
51113
51114
51115
51116 private function extractAllNamespaces($name)
51117 {
51118
51119  $parts = explode(':', $name, -1);
51120 $namespaces = array();
51121
51122 foreach ($parts as $part) {
51123 if (\count($namespaces)) {
51124 $namespaces[] = end($namespaces).':'.$part;
51125 } else {
51126 $namespaces[] = $part;
51127 }
51128 }
51129
51130 return $namespaces;
51131 }
51132
51133 private function init()
51134 {
51135 if ($this->initialized) {
51136 return;
51137 }
51138 $this->initialized = true;
51139
51140 foreach ($this->getDefaultCommands() as $command) {
51141 $this->add($command);
51142 }
51143 }
51144
51145
51146
51147
51148
51149
51150 private function getExitCodeForThrowable($throwable)
51151 {
51152 $exitCode = $throwable->getCode();
51153 if (is_numeric($exitCode)) {
51154 $exitCode = (int) $exitCode;
51155 if (0 === $exitCode) {
51156 $exitCode = 1;
51157 }
51158 } else {
51159 $exitCode = 1;
51160 }
51161
51162 return $exitCode;
51163 }
51164 }
51165 <?php
51166
51167
51168
51169
51170
51171
51172
51173
51174
51175
51176 namespace Symfony\Component\Console\Command;
51177
51178 use Symfony\Component\Console\Application;
51179 use Symfony\Component\Console\Descriptor\TextDescriptor;
51180 use Symfony\Component\Console\Descriptor\XmlDescriptor;
51181 use Symfony\Component\Console\Exception\ExceptionInterface;
51182 use Symfony\Component\Console\Exception\InvalidArgumentException;
51183 use Symfony\Component\Console\Exception\LogicException;
51184 use Symfony\Component\Console\Helper\HelperSet;
51185 use Symfony\Component\Console\Input\InputArgument;
51186 use Symfony\Component\Console\Input\InputDefinition;
51187 use Symfony\Component\Console\Input\InputInterface;
51188 use Symfony\Component\Console\Input\InputOption;
51189 use Symfony\Component\Console\Output\BufferedOutput;
51190 use Symfony\Component\Console\Output\OutputInterface;
51191
51192
51193
51194
51195
51196
51197 class Command
51198 {
51199 private $application;
51200 private $name;
51201 private $processTitle;
51202 private $aliases = array();
51203 private $definition;
51204 private $help;
51205 private $description;
51206 private $ignoreValidationErrors = false;
51207 private $applicationDefinitionMerged = false;
51208 private $applicationDefinitionMergedWithArgs = false;
51209 private $code;
51210 private $synopsis = array();
51211 private $usages = array();
51212 private $helperSet;
51213
51214
51215
51216
51217
51218
51219 public function __construct($name = null)
51220 {
51221 $this->definition = new InputDefinition();
51222
51223 if (null !== $name) {
51224 $this->setName($name);
51225 }
51226
51227 $this->configure();
51228
51229 if (!$this->name) {
51230 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($this)));
51231 }
51232 }
51233
51234
51235
51236
51237
51238
51239 public function ignoreValidationErrors()
51240 {
51241 $this->ignoreValidationErrors = true;
51242 }
51243
51244 public function setApplication(Application $application = null)
51245 {
51246 $this->application = $application;
51247 if ($application) {
51248 $this->setHelperSet($application->getHelperSet());
51249 } else {
51250 $this->helperSet = null;
51251 }
51252 }
51253
51254 public function setHelperSet(HelperSet $helperSet)
51255 {
51256 $this->helperSet = $helperSet;
51257 }
51258
51259
51260
51261
51262
51263
51264 public function getHelperSet()
51265 {
51266 return $this->helperSet;
51267 }
51268
51269
51270
51271
51272
51273
51274 public function getApplication()
51275 {
51276 return $this->application;
51277 }
51278
51279
51280
51281
51282
51283
51284
51285
51286
51287 public function isEnabled()
51288 {
51289 return true;
51290 }
51291
51292
51293
51294
51295 protected function configure()
51296 {
51297 }
51298
51299
51300
51301
51302
51303
51304
51305
51306
51307
51308
51309
51310
51311
51312
51313 protected function execute(InputInterface $input, OutputInterface $output)
51314 {
51315 throw new LogicException('You must override the execute() method in the concrete command class.');
51316 }
51317
51318
51319
51320
51321
51322
51323
51324
51325 protected function interact(InputInterface $input, OutputInterface $output)
51326 {
51327 }
51328
51329
51330
51331
51332
51333
51334
51335
51336
51337
51338
51339 protected function initialize(InputInterface $input, OutputInterface $output)
51340 {
51341 }
51342
51343
51344
51345
51346
51347
51348
51349
51350
51351
51352
51353
51354
51355
51356
51357 public function run(InputInterface $input, OutputInterface $output)
51358 {
51359
51360  $this->getSynopsis(true);
51361 $this->getSynopsis(false);
51362
51363
51364  $this->mergeApplicationDefinition();
51365
51366
51367  try {
51368 $input->bind($this->definition);
51369 } catch (ExceptionInterface $e) {
51370 if (!$this->ignoreValidationErrors) {
51371 throw $e;
51372 }
51373 }
51374
51375 $this->initialize($input, $output);
51376
51377 if (null !== $this->processTitle) {
51378 if (\function_exists('cli_set_process_title')) {
51379 if (!@cli_set_process_title($this->processTitle)) {
51380 if ('Darwin' === PHP_OS) {
51381 $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
51382 } else {
51383 cli_set_process_title($this->processTitle);
51384 }
51385 }
51386 } elseif (\function_exists('setproctitle')) {
51387 setproctitle($this->processTitle);
51388 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
51389 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
51390 }
51391 }
51392
51393 if ($input->isInteractive()) {
51394 $this->interact($input, $output);
51395 }
51396
51397
51398  
51399  
51400  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
51401 $input->setArgument('command', $this->getName());
51402 }
51403
51404 $input->validate();
51405
51406 if ($this->code) {
51407 $statusCode = \call_user_func($this->code, $input, $output);
51408 } else {
51409 $statusCode = $this->execute($input, $output);
51410 }
51411
51412 return is_numeric($statusCode) ? (int) $statusCode : 0;
51413 }
51414
51415
51416
51417
51418
51419
51420
51421
51422
51423
51424
51425
51426
51427
51428
51429 public function setCode($code)
51430 {
51431 if (!\is_callable($code)) {
51432 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
51433 }
51434
51435 if (\PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
51436 $r = new \ReflectionFunction($code);
51437 if (null === $r->getClosureThis()) {
51438 if (\PHP_VERSION_ID < 70000) {
51439
51440  
51441  
51442  
51443  $code = @\Closure::bind($code, $this);
51444 } else {
51445 $code = \Closure::bind($code, $this);
51446 }
51447 }
51448 }
51449
51450 $this->code = $code;
51451
51452 return $this;
51453 }
51454
51455
51456
51457
51458
51459
51460
51461
51462 public function mergeApplicationDefinition($mergeArgs = true)
51463 {
51464 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
51465 return;
51466 }
51467
51468 $this->definition->addOptions($this->application->getDefinition()->getOptions());
51469
51470 $this->applicationDefinitionMerged = true;
51471
51472 if ($mergeArgs) {
51473 $currentArguments = $this->definition->getArguments();
51474 $this->definition->setArguments($this->application->getDefinition()->getArguments());
51475 $this->definition->addArguments($currentArguments);
51476
51477 $this->applicationDefinitionMergedWithArgs = true;
51478 }
51479 }
51480
51481
51482
51483
51484
51485
51486
51487
51488 public function setDefinition($definition)
51489 {
51490 if ($definition instanceof InputDefinition) {
51491 $this->definition = $definition;
51492 } else {
51493 $this->definition->setDefinition($definition);
51494 }
51495
51496 $this->applicationDefinitionMerged = false;
51497
51498 return $this;
51499 }
51500
51501
51502
51503
51504
51505
51506 public function getDefinition()
51507 {
51508 return $this->definition;
51509 }
51510
51511
51512
51513
51514
51515
51516
51517
51518
51519
51520
51521 public function getNativeDefinition()
51522 {
51523 return $this->getDefinition();
51524 }
51525
51526
51527
51528
51529
51530
51531
51532
51533
51534
51535
51536
51537
51538 public function addArgument($name, $mode = null, $description = '', $default = null)
51539 {
51540 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
51541
51542 return $this;
51543 }
51544
51545
51546
51547
51548
51549
51550
51551
51552
51553
51554
51555
51556
51557
51558 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
51559 {
51560 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
51561
51562 return $this;
51563 }
51564
51565
51566
51567
51568
51569
51570
51571
51572
51573
51574
51575
51576
51577
51578
51579 public function setName($name)
51580 {
51581 $this->validateName($name);
51582
51583 $this->name = $name;
51584
51585 return $this;
51586 }
51587
51588
51589
51590
51591
51592
51593
51594
51595
51596
51597
51598
51599
51600 public function setProcessTitle($title)
51601 {
51602 $this->processTitle = $title;
51603
51604 return $this;
51605 }
51606
51607
51608
51609
51610
51611
51612 public function getName()
51613 {
51614 return $this->name;
51615 }
51616
51617
51618
51619
51620
51621
51622
51623
51624 public function setDescription($description)
51625 {
51626 $this->description = $description;
51627
51628 return $this;
51629 }
51630
51631
51632
51633
51634
51635
51636 public function getDescription()
51637 {
51638 return $this->description;
51639 }
51640
51641
51642
51643
51644
51645
51646
51647
51648 public function setHelp($help)
51649 {
51650 $this->help = $help;
51651
51652 return $this;
51653 }
51654
51655
51656
51657
51658
51659
51660 public function getHelp()
51661 {
51662 return $this->help;
51663 }
51664
51665
51666
51667
51668
51669
51670
51671 public function getProcessedHelp()
51672 {
51673 $name = $this->name;
51674
51675 $placeholders = array(
51676 '%command.name%',
51677 '%command.full_name%',
51678 );
51679 $replacements = array(
51680 $name,
51681 $_SERVER['PHP_SELF'].' '.$name,
51682 );
51683
51684 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
51685 }
51686
51687
51688
51689
51690
51691
51692
51693
51694
51695
51696 public function setAliases($aliases)
51697 {
51698 if (!\is_array($aliases) && !$aliases instanceof \Traversable) {
51699 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
51700 }
51701
51702 foreach ($aliases as $alias) {
51703 $this->validateName($alias);
51704 }
51705
51706 $this->aliases = $aliases;
51707
51708 return $this;
51709 }
51710
51711
51712
51713
51714
51715
51716 public function getAliases()
51717 {
51718 return $this->aliases;
51719 }
51720
51721
51722
51723
51724
51725
51726
51727
51728 public function getSynopsis($short = false)
51729 {
51730 $key = $short ? 'short' : 'long';
51731
51732 if (!isset($this->synopsis[$key])) {
51733 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
51734 }
51735
51736 return $this->synopsis[$key];
51737 }
51738
51739
51740
51741
51742
51743
51744
51745
51746 public function addUsage($usage)
51747 {
51748 if (0 !== strpos($usage, $this->name)) {
51749 $usage = sprintf('%s %s', $this->name, $usage);
51750 }
51751
51752 $this->usages[] = $usage;
51753
51754 return $this;
51755 }
51756
51757
51758
51759
51760
51761
51762 public function getUsages()
51763 {
51764 return $this->usages;
51765 }
51766
51767
51768
51769
51770
51771
51772
51773
51774
51775
51776
51777 public function getHelper($name)
51778 {
51779 if (null === $this->helperSet) {
51780 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));
51781 }
51782
51783 return $this->helperSet->get($name);
51784 }
51785
51786
51787
51788
51789
51790
51791
51792
51793 public function asText()
51794 {
51795 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
51796
51797 $descriptor = new TextDescriptor();
51798 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
51799 $descriptor->describe($output, $this, array('raw_output' => true));
51800
51801 return $output->fetch();
51802 }
51803
51804
51805
51806
51807
51808
51809
51810
51811
51812
51813 public function asXml($asDom = false)
51814 {
51815 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
51816
51817 $descriptor = new XmlDescriptor();
51818
51819 if ($asDom) {
51820 return $descriptor->getCommandDocument($this);
51821 }
51822
51823 $output = new BufferedOutput();
51824 $descriptor->describe($output, $this);
51825
51826 return $output->fetch();
51827 }
51828
51829
51830
51831
51832
51833
51834
51835
51836
51837
51838 private function validateName($name)
51839 {
51840 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
51841 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
51842 }
51843 }
51844 }
51845 <?php
51846
51847
51848
51849
51850
51851
51852
51853
51854
51855
51856 namespace Symfony\Component\Console\Command;
51857
51858 use Symfony\Component\Console\Helper\DescriptorHelper;
51859 use Symfony\Component\Console\Input\InputArgument;
51860 use Symfony\Component\Console\Input\InputInterface;
51861 use Symfony\Component\Console\Input\InputOption;
51862 use Symfony\Component\Console\Output\OutputInterface;
51863
51864
51865
51866
51867
51868
51869 class HelpCommand extends Command
51870 {
51871 private $command;
51872
51873
51874
51875
51876 protected function configure()
51877 {
51878 $this->ignoreValidationErrors();
51879
51880 $this
51881 ->setName('help')
51882 ->setDefinition(array(
51883 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
51884 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
51885 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
51886 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
51887 ))
51888 ->setDescription('Displays help for a command')
51889 ->setHelp(<<<'EOF'
51890 The <info>%command.name%</info> command displays help for a given command:
51891
51892   <info>php %command.full_name% list</info>
51893
51894 You can also output the help in other formats by using the <comment>--format</comment> option:
51895
51896   <info>php %command.full_name% --format=xml list</info>
51897
51898 To display the list of available commands, please use the <info>list</info> command.
51899 EOF
51900 )
51901 ;
51902 }
51903
51904 public function setCommand(Command $command)
51905 {
51906 $this->command = $command;
51907 }
51908
51909
51910
51911
51912 protected function execute(InputInterface $input, OutputInterface $output)
51913 {
51914 if (null === $this->command) {
51915 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
51916 }
51917
51918 if ($input->getOption('xml')) {
51919 @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);
51920
51921 $input->setOption('format', 'xml');
51922 }
51923
51924 $helper = new DescriptorHelper();
51925 $helper->describe($output, $this->command, array(
51926 'format' => $input->getOption('format'),
51927 'raw_text' => $input->getOption('raw'),
51928 ));
51929
51930 $this->command = null;
51931 }
51932 }
51933 <?php
51934
51935
51936
51937
51938
51939
51940
51941
51942
51943
51944 namespace Symfony\Component\Console\Command;
51945
51946 use Symfony\Component\Console\Helper\DescriptorHelper;
51947 use Symfony\Component\Console\Input\InputArgument;
51948 use Symfony\Component\Console\Input\InputDefinition;
51949 use Symfony\Component\Console\Input\InputInterface;
51950 use Symfony\Component\Console\Input\InputOption;
51951 use Symfony\Component\Console\Output\OutputInterface;
51952
51953
51954
51955
51956
51957
51958 class ListCommand extends Command
51959 {
51960
51961
51962
51963 protected function configure()
51964 {
51965 $this
51966 ->setName('list')
51967 ->setDefinition($this->createDefinition())
51968 ->setDescription('Lists commands')
51969 ->setHelp(<<<'EOF'
51970 The <info>%command.name%</info> command lists all commands:
51971
51972   <info>php %command.full_name%</info>
51973
51974 You can also display the commands for a specific namespace:
51975
51976   <info>php %command.full_name% test</info>
51977
51978 You can also output the information in other formats by using the <comment>--format</comment> option:
51979
51980   <info>php %command.full_name% --format=xml</info>
51981
51982 It's also possible to get raw list of commands (useful for embedding command runner):
51983
51984   <info>php %command.full_name% --raw</info>
51985 EOF
51986 )
51987 ;
51988 }
51989
51990
51991
51992
51993 public function getNativeDefinition()
51994 {
51995 return $this->createDefinition();
51996 }
51997
51998
51999
52000
52001 protected function execute(InputInterface $input, OutputInterface $output)
52002 {
52003 if ($input->getOption('xml')) {
52004 @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);
52005
52006 $input->setOption('format', 'xml');
52007 }
52008
52009 $helper = new DescriptorHelper();
52010 $helper->describe($output, $this->getApplication(), array(
52011 'format' => $input->getOption('format'),
52012 'raw_text' => $input->getOption('raw'),
52013 'namespace' => $input->getArgument('namespace'),
52014 ));
52015 }
52016
52017
52018
52019
52020 private function createDefinition()
52021 {
52022 return new InputDefinition(array(
52023 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
52024 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
52025 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
52026 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
52027 ));
52028 }
52029 }
52030 <?php
52031
52032
52033
52034
52035
52036
52037
52038
52039
52040
52041 namespace Symfony\Component\Console;
52042
52043
52044
52045
52046
52047
52048 final class ConsoleEvents
52049 {
52050
52051
52052
52053
52054
52055
52056
52057
52058
52059
52060 const COMMAND = 'console.command';
52061
52062
52063
52064
52065
52066
52067
52068
52069
52070
52071 const TERMINATE = 'console.terminate';
52072
52073
52074
52075
52076
52077
52078
52079
52080
52081
52082
52083 const EXCEPTION = 'console.exception';
52084 }
52085 <?php
52086
52087
52088
52089
52090
52091
52092
52093
52094
52095
52096 namespace Symfony\Component\Console\Descriptor;
52097
52098 use Symfony\Component\Console\Application;
52099 use Symfony\Component\Console\Command\Command;
52100 use Symfony\Component\Console\Exception\CommandNotFoundException;
52101
52102
52103
52104
52105
52106
52107 class ApplicationDescription
52108 {
52109 const GLOBAL_NAMESPACE = '_global';
52110
52111 private $application;
52112 private $namespace;
52113
52114
52115
52116
52117 private $namespaces;
52118
52119
52120
52121
52122 private $commands;
52123
52124
52125
52126
52127 private $aliases;
52128
52129 public function __construct(Application $application, $namespace = null)
52130 {
52131 $this->application = $application;
52132 $this->namespace = $namespace;
52133 }
52134
52135
52136
52137
52138 public function getNamespaces()
52139 {
52140 if (null === $this->namespaces) {
52141 $this->inspectApplication();
52142 }
52143
52144 return $this->namespaces;
52145 }
52146
52147
52148
52149
52150 public function getCommands()
52151 {
52152 if (null === $this->commands) {
52153 $this->inspectApplication();
52154 }
52155
52156 return $this->commands;
52157 }
52158
52159
52160
52161
52162
52163
52164
52165
52166 public function getCommand($name)
52167 {
52168 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
52169 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
52170 }
52171
52172 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
52173 }
52174
52175 private function inspectApplication()
52176 {
52177 $this->commands = array();
52178 $this->namespaces = array();
52179
52180 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
52181 foreach ($this->sortCommands($all) as $namespace => $commands) {
52182 $names = array();
52183
52184
52185 foreach ($commands as $name => $command) {
52186 if (!$command->getName()) {
52187 continue;
52188 }
52189
52190 if ($command->getName() === $name) {
52191 $this->commands[$name] = $command;
52192 } else {
52193 $this->aliases[$name] = $command;
52194 }
52195
52196 $names[] = $name;
52197 }
52198
52199 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
52200 }
52201 }
52202
52203
52204
52205
52206 private function sortCommands(array $commands)
52207 {
52208 $namespacedCommands = array();
52209 $globalCommands = array();
52210 foreach ($commands as $name => $command) {
52211 $key = $this->application->extractNamespace($name, 1);
52212 if (!$key) {
52213 $globalCommands['_global'][$name] = $command;
52214 } else {
52215 $namespacedCommands[$key][$name] = $command;
52216 }
52217 }
52218 ksort($namespacedCommands);
52219 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
52220
52221 foreach ($namespacedCommands as &$commandsSet) {
52222 ksort($commandsSet);
52223 }
52224
52225  unset($commandsSet);
52226
52227 return $namespacedCommands;
52228 }
52229 }
52230 <?php
52231
52232
52233
52234
52235
52236
52237
52238
52239
52240
52241 namespace Symfony\Component\Console\Descriptor;
52242
52243 use Symfony\Component\Console\Application;
52244 use Symfony\Component\Console\Command\Command;
52245 use Symfony\Component\Console\Exception\InvalidArgumentException;
52246 use Symfony\Component\Console\Input\InputArgument;
52247 use Symfony\Component\Console\Input\InputDefinition;
52248 use Symfony\Component\Console\Input\InputOption;
52249 use Symfony\Component\Console\Output\OutputInterface;
52250
52251
52252
52253
52254
52255
52256 abstract class Descriptor implements DescriptorInterface
52257 {
52258
52259
52260
52261 private $output;
52262
52263
52264
52265
52266 public function describe(OutputInterface $output, $object, array $options = array())
52267 {
52268 $this->output = $output;
52269
52270 switch (true) {
52271 case $object instanceof InputArgument:
52272 $this->describeInputArgument($object, $options);
52273 break;
52274 case $object instanceof InputOption:
52275 $this->describeInputOption($object, $options);
52276 break;
52277 case $object instanceof InputDefinition:
52278 $this->describeInputDefinition($object, $options);
52279 break;
52280 case $object instanceof Command:
52281 $this->describeCommand($object, $options);
52282 break;
52283 case $object instanceof Application:
52284 $this->describeApplication($object, $options);
52285 break;
52286 default:
52287 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object)));
52288 }
52289 }
52290
52291
52292
52293
52294
52295
52296
52297 protected function write($content, $decorated = false)
52298 {
52299 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
52300 }
52301
52302
52303
52304
52305
52306
52307 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
52308
52309
52310
52311
52312
52313
52314 abstract protected function describeInputOption(InputOption $option, array $options = array());
52315
52316
52317
52318
52319
52320
52321 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
52322
52323
52324
52325
52326
52327
52328 abstract protected function describeCommand(Command $command, array $options = array());
52329
52330
52331
52332
52333
52334
52335 abstract protected function describeApplication(Application $application, array $options = array());
52336 }
52337 <?php
52338
52339
52340
52341
52342
52343
52344
52345
52346
52347
52348 namespace Symfony\Component\Console\Descriptor;
52349
52350 use Symfony\Component\Console\Output\OutputInterface;
52351
52352
52353
52354
52355
52356
52357 interface DescriptorInterface
52358 {
52359
52360
52361
52362
52363
52364
52365
52366 public function describe(OutputInterface $output, $object, array $options = array());
52367 }
52368 <?php
52369
52370
52371
52372
52373
52374
52375
52376
52377
52378
52379 namespace Symfony\Component\Console\Descriptor;
52380
52381 use Symfony\Component\Console\Application;
52382 use Symfony\Component\Console\Command\Command;
52383 use Symfony\Component\Console\Input\InputArgument;
52384 use Symfony\Component\Console\Input\InputDefinition;
52385 use Symfony\Component\Console\Input\InputOption;
52386
52387
52388
52389
52390
52391
52392
52393
52394 class JsonDescriptor extends Descriptor
52395 {
52396
52397
52398
52399 protected function describeInputArgument(InputArgument $argument, array $options = array())
52400 {
52401 $this->writeData($this->getInputArgumentData($argument), $options);
52402 }
52403
52404
52405
52406
52407 protected function describeInputOption(InputOption $option, array $options = array())
52408 {
52409 $this->writeData($this->getInputOptionData($option), $options);
52410 }
52411
52412
52413
52414
52415 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
52416 {
52417 $this->writeData($this->getInputDefinitionData($definition), $options);
52418 }
52419
52420
52421
52422
52423 protected function describeCommand(Command $command, array $options = array())
52424 {
52425 $this->writeData($this->getCommandData($command), $options);
52426 }
52427
52428
52429
52430
52431 protected function describeApplication(Application $application, array $options = array())
52432 {
52433 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
52434 $description = new ApplicationDescription($application, $describedNamespace);
52435 $commands = array();
52436
52437 foreach ($description->getCommands() as $command) {
52438 $commands[] = $this->getCommandData($command);
52439 }
52440
52441 $data = $describedNamespace
52442 ? array('commands' => $commands, 'namespace' => $describedNamespace)
52443 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
52444
52445 $this->writeData($data, $options);
52446 }
52447
52448
52449
52450
52451
52452
52453 private function writeData(array $data, array $options)
52454 {
52455 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
52456 }
52457
52458
52459
52460
52461 private function getInputArgumentData(InputArgument $argument)
52462 {
52463 return array(
52464 'name' => $argument->getName(),
52465 'is_required' => $argument->isRequired(),
52466 'is_array' => $argument->isArray(),
52467 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
52468 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
52469 );
52470 }
52471
52472
52473
52474
52475 private function getInputOptionData(InputOption $option)
52476 {
52477 return array(
52478 'name' => '--'.$option->getName(),
52479 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
52480 'accept_value' => $option->acceptValue(),
52481 'is_value_required' => $option->isValueRequired(),
52482 'is_multiple' => $option->isArray(),
52483 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
52484 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
52485 );
52486 }
52487
52488
52489
52490
52491 private function getInputDefinitionData(InputDefinition $definition)
52492 {
52493 $inputArguments = array();
52494 foreach ($definition->getArguments() as $name => $argument) {
52495 $inputArguments[$name] = $this->getInputArgumentData($argument);
52496 }
52497
52498 $inputOptions = array();
52499 foreach ($definition->getOptions() as $name => $option) {
52500 $inputOptions[$name] = $this->getInputOptionData($option);
52501 }
52502
52503 return array('arguments' => $inputArguments, 'options' => $inputOptions);
52504 }
52505
52506
52507
52508
52509 private function getCommandData(Command $command)
52510 {
52511 $command->getSynopsis();
52512 $command->mergeApplicationDefinition(false);
52513
52514 return array(
52515 'name' => $command->getName(),
52516 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
52517 'description' => $command->getDescription(),
52518 'help' => $command->getProcessedHelp(),
52519 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
52520 );
52521 }
52522 }
52523 <?php
52524
52525
52526
52527
52528
52529
52530
52531
52532
52533
52534 namespace Symfony\Component\Console\Descriptor;
52535
52536 use Symfony\Component\Console\Application;
52537 use Symfony\Component\Console\Command\Command;
52538 use Symfony\Component\Console\Helper\Helper;
52539 use Symfony\Component\Console\Input\InputArgument;
52540 use Symfony\Component\Console\Input\InputDefinition;
52541 use Symfony\Component\Console\Input\InputOption;
52542
52543
52544
52545
52546
52547
52548
52549
52550 class MarkdownDescriptor extends Descriptor
52551 {
52552
52553
52554
52555 protected function describeInputArgument(InputArgument $argument, array $options = array())
52556 {
52557 $this->write(
52558 '**'.$argument->getName().':**'."\n\n"
52559 .'* Name: '.($argument->getName() ?: '<none>')."\n"
52560 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
52561 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
52562 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
52563 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
52564 );
52565 }
52566
52567
52568
52569
52570 protected function describeInputOption(InputOption $option, array $options = array())
52571 {
52572 $this->write(
52573 '**'.$option->getName().':**'."\n\n"
52574 .'* Name: `--'.$option->getName().'`'."\n"
52575 .'* Shortcut: '.($option->getShortcut() ? '`-'.str_replace('|', '|-', $option->getShortcut()).'`' : '<none>')."\n"
52576 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
52577 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
52578 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
52579 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
52580 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
52581 );
52582 }
52583
52584
52585
52586
52587 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
52588 {
52589 if ($showArguments = \count($definition->getArguments()) > 0) {
52590 $this->write('### Arguments:');
52591 foreach ($definition->getArguments() as $argument) {
52592 $this->write("\n\n");
52593 $this->write($this->describeInputArgument($argument));
52594 }
52595 }
52596
52597 if (\count($definition->getOptions()) > 0) {
52598 if ($showArguments) {
52599 $this->write("\n\n");
52600 }
52601
52602 $this->write('### Options:');
52603 foreach ($definition->getOptions() as $option) {
52604 $this->write("\n\n");
52605 $this->write($this->describeInputOption($option));
52606 }
52607 }
52608 }
52609
52610
52611
52612
52613 protected function describeCommand(Command $command, array $options = array())
52614 {
52615 $command->getSynopsis();
52616 $command->mergeApplicationDefinition(false);
52617
52618 $this->write(
52619 $command->getName()."\n"
52620 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
52621 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
52622 .'* Usage:'."\n\n"
52623 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
52624 return $carry.'  * `'.$usage.'`'."\n";
52625 })
52626 );
52627
52628 if ($help = $command->getProcessedHelp()) {
52629 $this->write("\n");
52630 $this->write($help);
52631 }
52632
52633 if ($command->getNativeDefinition()) {
52634 $this->write("\n\n");
52635 $this->describeInputDefinition($command->getNativeDefinition());
52636 }
52637 }
52638
52639
52640
52641
52642 protected function describeApplication(Application $application, array $options = array())
52643 {
52644 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
52645 $description = new ApplicationDescription($application, $describedNamespace);
52646
52647 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
52648
52649 foreach ($description->getNamespaces() as $namespace) {
52650 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
52651 $this->write("\n\n");
52652 $this->write('**'.$namespace['id'].':**');
52653 }
52654
52655 $this->write("\n\n");
52656 $this->write(implode("\n", array_map(function ($commandName) {
52657 return '* '.$commandName;
52658 }, $namespace['commands'])));
52659 }
52660
52661 foreach ($description->getCommands() as $command) {
52662 $this->write("\n\n");
52663 $this->write($this->describeCommand($command));
52664 }
52665 }
52666 }
52667 <?php
52668
52669
52670
52671
52672
52673
52674
52675
52676
52677
52678 namespace Symfony\Component\Console\Descriptor;
52679
52680 use Symfony\Component\Console\Application;
52681 use Symfony\Component\Console\Command\Command;
52682 use Symfony\Component\Console\Formatter\OutputFormatter;
52683 use Symfony\Component\Console\Helper\Helper;
52684 use Symfony\Component\Console\Input\InputArgument;
52685 use Symfony\Component\Console\Input\InputDefinition;
52686 use Symfony\Component\Console\Input\InputOption;
52687
52688
52689
52690
52691
52692
52693
52694
52695 class TextDescriptor extends Descriptor
52696 {
52697
52698
52699
52700 protected function describeInputArgument(InputArgument $argument, array $options = array())
52701 {
52702 if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
52703 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
52704 } else {
52705 $default = '';
52706 }
52707
52708 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
52709 $spacingWidth = $totalWidth - \strlen($argument->getName());
52710
52711 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
52712 $argument->getName(),
52713 str_repeat(' ', $spacingWidth),
52714
52715  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
52716 $default
52717 ), $options);
52718 }
52719
52720
52721
52722
52723 protected function describeInputOption(InputOption $option, array $options = array())
52724 {
52725 if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
52726 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
52727 } else {
52728 $default = '';
52729 }
52730
52731 $value = '';
52732 if ($option->acceptValue()) {
52733 $value = '='.strtoupper($option->getName());
52734
52735 if ($option->isValueOptional()) {
52736 $value = '['.$value.']';
52737 }
52738 }
52739
52740 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
52741 $synopsis = sprintf('%s%s',
52742 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
52743 sprintf('--%s%s', $option->getName(), $value)
52744 );
52745
52746 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
52747
52748 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
52749 $synopsis,
52750 str_repeat(' ', $spacingWidth),
52751
52752  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
52753 $default,
52754 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
52755 ), $options);
52756 }
52757
52758
52759
52760
52761 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
52762 {
52763 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
52764 foreach ($definition->getArguments() as $argument) {
52765 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
52766 }
52767
52768 if ($definition->getArguments()) {
52769 $this->writeText('<comment>Arguments:</comment>', $options);
52770 $this->writeText("\n");
52771 foreach ($definition->getArguments() as $argument) {
52772 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
52773 $this->writeText("\n");
52774 }
52775 }
52776
52777 if ($definition->getArguments() && $definition->getOptions()) {
52778 $this->writeText("\n");
52779 }
52780
52781 if ($definition->getOptions()) {
52782 $laterOptions = array();
52783
52784 $this->writeText('<comment>Options:</comment>', $options);
52785 foreach ($definition->getOptions() as $option) {
52786 if (\strlen($option->getShortcut()) > 1) {
52787 $laterOptions[] = $option;
52788 continue;
52789 }
52790 $this->writeText("\n");
52791 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
52792 }
52793 foreach ($laterOptions as $option) {
52794 $this->writeText("\n");
52795 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
52796 }
52797 }
52798 }
52799
52800
52801
52802
52803 protected function describeCommand(Command $command, array $options = array())
52804 {
52805 $command->getSynopsis(true);
52806 $command->getSynopsis(false);
52807 $command->mergeApplicationDefinition(false);
52808
52809 $this->writeText('<comment>Usage:</comment>', $options);
52810 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
52811 $this->writeText("\n");
52812 $this->writeText('  '.OutputFormatter::escape($usage), $options);
52813 }
52814 $this->writeText("\n");
52815
52816 $definition = $command->getNativeDefinition();
52817 if ($definition->getOptions() || $definition->getArguments()) {
52818 $this->writeText("\n");
52819 $this->describeInputDefinition($definition, $options);
52820 $this->writeText("\n");
52821 }
52822
52823 if ($help = $command->getProcessedHelp()) {
52824 $this->writeText("\n");
52825 $this->writeText('<comment>Help:</comment>', $options);
52826 $this->writeText("\n");
52827 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
52828 $this->writeText("\n");
52829 }
52830 }
52831
52832
52833
52834
52835 protected function describeApplication(Application $application, array $options = array())
52836 {
52837 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
52838 $description = new ApplicationDescription($application, $describedNamespace);
52839
52840 if (isset($options['raw_text']) && $options['raw_text']) {
52841 $width = $this->getColumnWidth($description->getCommands());
52842
52843 foreach ($description->getCommands() as $command) {
52844 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
52845 $this->writeText("\n");
52846 }
52847 } else {
52848 if ('' != $help = $application->getHelp()) {
52849 $this->writeText("$help\n\n", $options);
52850 }
52851
52852 $this->writeText("<comment>Usage:</comment>\n", $options);
52853 $this->writeText("  command [options] [arguments]\n\n", $options);
52854
52855 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
52856
52857 $this->writeText("\n");
52858 $this->writeText("\n");
52859
52860 $width = $this->getColumnWidth($description->getCommands());
52861
52862 if ($describedNamespace) {
52863 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
52864 } else {
52865 $this->writeText('<comment>Available commands:</comment>', $options);
52866 }
52867
52868
52869  foreach ($description->getNamespaces() as $namespace) {
52870 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
52871 $this->writeText("\n");
52872 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
52873 }
52874
52875 foreach ($namespace['commands'] as $name) {
52876 $this->writeText("\n");
52877 $spacingWidth = $width - Helper::strlen($name);
52878 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
52879 }
52880 }
52881
52882 $this->writeText("\n");
52883 }
52884 }
52885
52886
52887
52888
52889 private function writeText($content, array $options = array())
52890 {
52891 $this->write(
52892 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
52893 isset($options['raw_output']) ? !$options['raw_output'] : true
52894 );
52895 }
52896
52897
52898
52899
52900
52901
52902
52903
52904 private function formatDefaultValue($default)
52905 {
52906 if (INF === $default) {
52907 return 'INF';
52908 }
52909
52910 if (\is_string($default)) {
52911 $default = OutputFormatter::escape($default);
52912 } elseif (\is_array($default)) {
52913 foreach ($default as $key => $value) {
52914 if (\is_string($value)) {
52915 $default[$key] = OutputFormatter::escape($value);
52916 }
52917 }
52918 }
52919
52920 if (\PHP_VERSION_ID < 50400) {
52921 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
52922 }
52923
52924 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
52925 }
52926
52927
52928
52929
52930
52931
52932 private function getColumnWidth(array $commands)
52933 {
52934 $widths = array();
52935
52936 foreach ($commands as $command) {
52937 $widths[] = Helper::strlen($command->getName());
52938 foreach ($command->getAliases() as $alias) {
52939 $widths[] = Helper::strlen($alias);
52940 }
52941 }
52942
52943 return max($widths) + 2;
52944 }
52945
52946
52947
52948
52949
52950
52951 private function calculateTotalWidthForOptions(array $options)
52952 {
52953 $totalWidth = 0;
52954 foreach ($options as $option) {
52955
52956  $nameLength = 1 + max(\strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
52957
52958 if ($option->acceptValue()) {
52959 $valueLength = 1 + Helper::strlen($option->getName()); 
52960  $valueLength += $option->isValueOptional() ? 2 : 0; 
52961
52962 $nameLength += $valueLength;
52963 }
52964 $totalWidth = max($totalWidth, $nameLength);
52965 }
52966
52967 return $totalWidth;
52968 }
52969 }
52970 <?php
52971
52972
52973
52974
52975
52976
52977
52978
52979
52980
52981 namespace Symfony\Component\Console\Descriptor;
52982
52983 use Symfony\Component\Console\Application;
52984 use Symfony\Component\Console\Command\Command;
52985 use Symfony\Component\Console\Input\InputArgument;
52986 use Symfony\Component\Console\Input\InputDefinition;
52987 use Symfony\Component\Console\Input\InputOption;
52988
52989
52990
52991
52992
52993
52994
52995
52996 class XmlDescriptor extends Descriptor
52997 {
52998
52999
53000
53001 public function getInputDefinitionDocument(InputDefinition $definition)
53002 {
53003 $dom = new \DOMDocument('1.0', 'UTF-8');
53004 $dom->appendChild($definitionXML = $dom->createElement('definition'));
53005
53006 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
53007 foreach ($definition->getArguments() as $argument) {
53008 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
53009 }
53010
53011 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
53012 foreach ($definition->getOptions() as $option) {
53013 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
53014 }
53015
53016 return $dom;
53017 }
53018
53019
53020
53021
53022 public function getCommandDocument(Command $command)
53023 {
53024 $dom = new \DOMDocument('1.0', 'UTF-8');
53025 $dom->appendChild($commandXML = $dom->createElement('command'));
53026
53027 $command->getSynopsis();
53028 $command->mergeApplicationDefinition(false);
53029
53030 $commandXML->setAttribute('id', $command->getName());
53031 $commandXML->setAttribute('name', $command->getName());
53032
53033 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
53034
53035 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
53036 $usagesXML->appendChild($dom->createElement('usage', $usage));
53037 }
53038
53039 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
53040 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
53041
53042 $commandXML->appendChild($helpXML = $dom->createElement('help'));
53043 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
53044
53045 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
53046 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
53047
53048 return $dom;
53049 }
53050
53051
53052
53053
53054
53055
53056
53057 public function getApplicationDocument(Application $application, $namespace = null)
53058 {
53059 $dom = new \DOMDocument('1.0', 'UTF-8');
53060 $dom->appendChild($rootXml = $dom->createElement('symfony'));
53061
53062 if ('UNKNOWN' !== $application->getName()) {
53063 $rootXml->setAttribute('name', $application->getName());
53064 if ('UNKNOWN' !== $application->getVersion()) {
53065 $rootXml->setAttribute('version', $application->getVersion());
53066 }
53067 }
53068
53069 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
53070
53071 $description = new ApplicationDescription($application, $namespace);
53072
53073 if ($namespace) {
53074 $commandsXML->setAttribute('namespace', $namespace);
53075 }
53076
53077 foreach ($description->getCommands() as $command) {
53078 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
53079 }
53080
53081 if (!$namespace) {
53082 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
53083
53084 foreach ($description->getNamespaces() as $namespaceDescription) {
53085 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
53086 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
53087
53088 foreach ($namespaceDescription['commands'] as $name) {
53089 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
53090 $commandXML->appendChild($dom->createTextNode($name));
53091 }
53092 }
53093 }
53094
53095 return $dom;
53096 }
53097
53098
53099
53100
53101 protected function describeInputArgument(InputArgument $argument, array $options = array())
53102 {
53103 $this->writeDocument($this->getInputArgumentDocument($argument));
53104 }
53105
53106
53107
53108
53109 protected function describeInputOption(InputOption $option, array $options = array())
53110 {
53111 $this->writeDocument($this->getInputOptionDocument($option));
53112 }
53113
53114
53115
53116
53117 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
53118 {
53119 $this->writeDocument($this->getInputDefinitionDocument($definition));
53120 }
53121
53122
53123
53124
53125 protected function describeCommand(Command $command, array $options = array())
53126 {
53127 $this->writeDocument($this->getCommandDocument($command));
53128 }
53129
53130
53131
53132
53133 protected function describeApplication(Application $application, array $options = array())
53134 {
53135 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
53136 }
53137
53138
53139
53140
53141 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
53142 {
53143 foreach ($importedParent->childNodes as $childNode) {
53144 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
53145 }
53146 }
53147
53148
53149
53150
53151
53152
53153 private function writeDocument(\DOMDocument $dom)
53154 {
53155 $dom->formatOutput = true;
53156 $this->write($dom->saveXML());
53157 }
53158
53159
53160
53161
53162 private function getInputArgumentDocument(InputArgument $argument)
53163 {
53164 $dom = new \DOMDocument('1.0', 'UTF-8');
53165
53166 $dom->appendChild($objectXML = $dom->createElement('argument'));
53167 $objectXML->setAttribute('name', $argument->getName());
53168 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
53169 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
53170 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
53171 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
53172
53173 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
53174 $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
53175 foreach ($defaults as $default) {
53176 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
53177 $defaultXML->appendChild($dom->createTextNode($default));
53178 }
53179
53180 return $dom;
53181 }
53182
53183
53184
53185
53186 private function getInputOptionDocument(InputOption $option)
53187 {
53188 $dom = new \DOMDocument('1.0', 'UTF-8');
53189
53190 $dom->appendChild($objectXML = $dom->createElement('option'));
53191 $objectXML->setAttribute('name', '--'.$option->getName());
53192 $pos = strpos($option->getShortcut(), '|');
53193 if (false !== $pos) {
53194 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
53195 $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
53196 } else {
53197 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
53198 }
53199 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
53200 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
53201 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
53202 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
53203 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
53204
53205 if ($option->acceptValue()) {
53206 $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
53207 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
53208
53209 if (!empty($defaults)) {
53210 foreach ($defaults as $default) {
53211 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
53212 $defaultXML->appendChild($dom->createTextNode($default));
53213 }
53214 }
53215 }
53216
53217 return $dom;
53218 }
53219 }
53220 <?php
53221
53222
53223
53224
53225
53226
53227
53228
53229
53230
53231 namespace Symfony\Component\Console\Event;
53232
53233
53234
53235
53236
53237
53238 class ConsoleCommandEvent extends ConsoleEvent
53239 {
53240
53241
53242
53243 const RETURN_CODE_DISABLED = 113;
53244
53245
53246
53247
53248 private $commandShouldRun = true;
53249
53250
53251
53252
53253
53254
53255 public function disableCommand()
53256 {
53257 return $this->commandShouldRun = false;
53258 }
53259
53260
53261
53262
53263
53264
53265 public function enableCommand()
53266 {
53267 return $this->commandShouldRun = true;
53268 }
53269
53270
53271
53272
53273
53274
53275 public function commandShouldRun()
53276 {
53277 return $this->commandShouldRun;
53278 }
53279 }
53280 <?php
53281
53282
53283
53284
53285
53286
53287
53288
53289
53290
53291 namespace Symfony\Component\Console\Event;
53292
53293 use Symfony\Component\Console\Command\Command;
53294 use Symfony\Component\Console\Input\InputInterface;
53295 use Symfony\Component\Console\Output\OutputInterface;
53296 use Symfony\Component\EventDispatcher\Event;
53297
53298
53299
53300
53301
53302
53303 class ConsoleEvent extends Event
53304 {
53305 protected $command;
53306
53307 private $input;
53308 private $output;
53309
53310 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
53311 {
53312 $this->command = $command;
53313 $this->input = $input;
53314 $this->output = $output;
53315 }
53316
53317
53318
53319
53320
53321
53322 public function getCommand()
53323 {
53324 return $this->command;
53325 }
53326
53327
53328
53329
53330
53331
53332 public function getInput()
53333 {
53334 return $this->input;
53335 }
53336
53337
53338
53339
53340
53341
53342 public function getOutput()
53343 {
53344 return $this->output;
53345 }
53346 }
53347 <?php
53348
53349
53350
53351
53352
53353
53354
53355
53356
53357
53358 namespace Symfony\Component\Console\Event;
53359
53360 use Symfony\Component\Console\Command\Command;
53361 use Symfony\Component\Console\Input\InputInterface;
53362 use Symfony\Component\Console\Output\OutputInterface;
53363
53364
53365
53366
53367
53368
53369 class ConsoleExceptionEvent extends ConsoleEvent
53370 {
53371 private $exception;
53372 private $exitCode;
53373
53374 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
53375 {
53376 parent::__construct($command, $input, $output);
53377
53378 $this->setException($exception);
53379 $this->exitCode = (int) $exitCode;
53380 }
53381
53382
53383
53384
53385
53386
53387 public function getException()
53388 {
53389 return $this->exception;
53390 }
53391
53392
53393
53394
53395
53396
53397
53398
53399 public function setException(\Exception $exception)
53400 {
53401 $this->exception = $exception;
53402 }
53403
53404
53405
53406
53407
53408
53409 public function getExitCode()
53410 {
53411 return $this->exitCode;
53412 }
53413 }
53414 <?php
53415
53416
53417
53418
53419
53420
53421
53422
53423
53424
53425 namespace Symfony\Component\Console\Event;
53426
53427 use Symfony\Component\Console\Command\Command;
53428 use Symfony\Component\Console\Input\InputInterface;
53429 use Symfony\Component\Console\Output\OutputInterface;
53430
53431
53432
53433
53434
53435
53436 class ConsoleTerminateEvent extends ConsoleEvent
53437 {
53438
53439
53440
53441
53442
53443 private $exitCode;
53444
53445 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
53446 {
53447 parent::__construct($command, $input, $output);
53448
53449 $this->setExitCode($exitCode);
53450 }
53451
53452
53453
53454
53455
53456
53457 public function setExitCode($exitCode)
53458 {
53459 $this->exitCode = (int) $exitCode;
53460 }
53461
53462
53463
53464
53465
53466
53467 public function getExitCode()
53468 {
53469 return $this->exitCode;
53470 }
53471 }
53472 <?php
53473
53474
53475
53476
53477
53478
53479
53480
53481
53482
53483 namespace Symfony\Component\Console\Exception;
53484
53485
53486
53487
53488
53489
53490 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
53491 {
53492 private $alternatives;
53493
53494
53495
53496
53497
53498
53499
53500 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
53501 {
53502 parent::__construct($message, $code, $previous);
53503
53504 $this->alternatives = $alternatives;
53505 }
53506
53507
53508
53509
53510 public function getAlternatives()
53511 {
53512 return $this->alternatives;
53513 }
53514 }
53515 <?php
53516
53517
53518
53519
53520
53521
53522
53523
53524
53525
53526 namespace Symfony\Component\Console\Exception;
53527
53528
53529
53530
53531
53532
53533 interface ExceptionInterface
53534 {
53535 }
53536 <?php
53537
53538
53539
53540
53541
53542
53543
53544
53545
53546
53547 namespace Symfony\Component\Console\Exception;
53548
53549
53550
53551
53552 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
53553 {
53554 }
53555 <?php
53556
53557
53558
53559
53560
53561
53562
53563
53564
53565
53566 namespace Symfony\Component\Console\Exception;
53567
53568
53569
53570
53571
53572
53573 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
53574 {
53575 }
53576 <?php
53577
53578
53579
53580
53581
53582
53583
53584
53585
53586
53587 namespace Symfony\Component\Console\Exception;
53588
53589
53590
53591
53592 class LogicException extends \LogicException implements ExceptionInterface
53593 {
53594 }
53595 <?php
53596
53597
53598
53599
53600
53601
53602
53603
53604
53605
53606 namespace Symfony\Component\Console\Exception;
53607
53608
53609
53610
53611 class RuntimeException extends \RuntimeException implements ExceptionInterface
53612 {
53613 }
53614 <?php
53615
53616
53617
53618
53619
53620
53621
53622
53623
53624
53625 namespace Symfony\Component\Console\Formatter;
53626
53627 use Symfony\Component\Console\Exception\InvalidArgumentException;
53628
53629
53630
53631
53632
53633
53634 class OutputFormatter implements OutputFormatterInterface
53635 {
53636 private $decorated;
53637 private $styles = array();
53638 private $styleStack;
53639
53640
53641
53642
53643
53644
53645
53646
53647 public static function escape($text)
53648 {
53649 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
53650
53651 return self::escapeTrailingBackslash($text);
53652 }
53653
53654
53655
53656
53657
53658
53659
53660
53661
53662
53663 public static function escapeTrailingBackslash($text)
53664 {
53665 if ('\\' === substr($text, -1)) {
53666 $len = \strlen($text);
53667 $text = rtrim($text, '\\');
53668 $text = str_replace("\0", '', $text);
53669 $text .= str_repeat("\0", $len - \strlen($text));
53670 }
53671
53672 return $text;
53673 }
53674
53675
53676
53677
53678
53679
53680
53681 public function __construct($decorated = false, array $styles = array())
53682 {
53683 $this->decorated = (bool) $decorated;
53684
53685 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
53686 $this->setStyle('info', new OutputFormatterStyle('green'));
53687 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
53688 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
53689
53690 foreach ($styles as $name => $style) {
53691 $this->setStyle($name, $style);
53692 }
53693
53694 $this->styleStack = new OutputFormatterStyleStack();
53695 }
53696
53697
53698
53699
53700 public function setDecorated($decorated)
53701 {
53702 $this->decorated = (bool) $decorated;
53703 }
53704
53705
53706
53707
53708 public function isDecorated()
53709 {
53710 return $this->decorated;
53711 }
53712
53713
53714
53715
53716 public function setStyle($name, OutputFormatterStyleInterface $style)
53717 {
53718 $this->styles[strtolower($name)] = $style;
53719 }
53720
53721
53722
53723
53724 public function hasStyle($name)
53725 {
53726 return isset($this->styles[strtolower($name)]);
53727 }
53728
53729
53730
53731
53732 public function getStyle($name)
53733 {
53734 if (!$this->hasStyle($name)) {
53735 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
53736 }
53737
53738 return $this->styles[strtolower($name)];
53739 }
53740
53741
53742
53743
53744 public function format($message)
53745 {
53746 $message = (string) $message;
53747 $offset = 0;
53748 $output = '';
53749 $tagRegex = '[a-z][a-z0-9_=;-]*+';
53750 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
53751 foreach ($matches[0] as $i => $match) {
53752 $pos = $match[1];
53753 $text = $match[0];
53754
53755 if (0 != $pos && '\\' == $message[$pos - 1]) {
53756 continue;
53757 }
53758
53759
53760  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
53761 $offset = $pos + \strlen($text);
53762
53763
53764  if ($open = '/' != $text[1]) {
53765 $tag = $matches[1][$i][0];
53766 } else {
53767 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
53768 }
53769
53770 if (!$open && !$tag) {
53771
53772  $this->styleStack->pop();
53773 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
53774 $output .= $this->applyCurrentStyle($text);
53775 } elseif ($open) {
53776 $this->styleStack->push($style);
53777 } else {
53778 $this->styleStack->pop($style);
53779 }
53780 }
53781
53782 $output .= $this->applyCurrentStyle(substr($message, $offset));
53783
53784 if (false !== strpos($output, "\0")) {
53785 return strtr($output, array("\0" => '\\', '\\<' => '<'));
53786 }
53787
53788 return str_replace('\\<', '<', $output);
53789 }
53790
53791
53792
53793
53794 public function getStyleStack()
53795 {
53796 return $this->styleStack;
53797 }
53798
53799
53800
53801
53802
53803
53804
53805
53806 private function createStyleFromString($string)
53807 {
53808 if (isset($this->styles[$string])) {
53809 return $this->styles[$string];
53810 }
53811
53812 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
53813 return false;
53814 }
53815
53816 $style = new OutputFormatterStyle();
53817 foreach ($matches as $match) {
53818 array_shift($match);
53819
53820 if ('fg' == $match[0]) {
53821 $style->setForeground($match[1]);
53822 } elseif ('bg' == $match[0]) {
53823 $style->setBackground($match[1]);
53824 } else {
53825 try {
53826 $style->setOption($match[1]);
53827 } catch (\InvalidArgumentException $e) {
53828 return false;
53829 }
53830 }
53831 }
53832
53833 return $style;
53834 }
53835
53836
53837
53838
53839
53840
53841
53842
53843 private function applyCurrentStyle($text)
53844 {
53845 return $this->isDecorated() && \strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
53846 }
53847 }
53848 <?php
53849
53850
53851
53852
53853
53854
53855
53856
53857
53858
53859 namespace Symfony\Component\Console\Formatter;
53860
53861
53862
53863
53864
53865
53866 interface OutputFormatterInterface
53867 {
53868
53869
53870
53871
53872
53873 public function setDecorated($decorated);
53874
53875
53876
53877
53878
53879
53880 public function isDecorated();
53881
53882
53883
53884
53885
53886
53887
53888 public function setStyle($name, OutputFormatterStyleInterface $style);
53889
53890
53891
53892
53893
53894
53895
53896
53897 public function hasStyle($name);
53898
53899
53900
53901
53902
53903
53904
53905
53906
53907
53908 public function getStyle($name);
53909
53910
53911
53912
53913
53914
53915
53916
53917 public function format($message);
53918 }
53919 <?php
53920
53921
53922
53923
53924
53925
53926
53927
53928
53929
53930 namespace Symfony\Component\Console\Formatter;
53931
53932 use Symfony\Component\Console\Exception\InvalidArgumentException;
53933
53934
53935
53936
53937
53938
53939 class OutputFormatterStyle implements OutputFormatterStyleInterface
53940 {
53941 private static $availableForegroundColors = array(
53942 'black' => array('set' => 30, 'unset' => 39),
53943 'red' => array('set' => 31, 'unset' => 39),
53944 'green' => array('set' => 32, 'unset' => 39),
53945 'yellow' => array('set' => 33, 'unset' => 39),
53946 'blue' => array('set' => 34, 'unset' => 39),
53947 'magenta' => array('set' => 35, 'unset' => 39),
53948 'cyan' => array('set' => 36, 'unset' => 39),
53949 'white' => array('set' => 37, 'unset' => 39),
53950 'default' => array('set' => 39, 'unset' => 39),
53951 );
53952 private static $availableBackgroundColors = array(
53953 'black' => array('set' => 40, 'unset' => 49),
53954 'red' => array('set' => 41, 'unset' => 49),
53955 'green' => array('set' => 42, 'unset' => 49),
53956 'yellow' => array('set' => 43, 'unset' => 49),
53957 'blue' => array('set' => 44, 'unset' => 49),
53958 'magenta' => array('set' => 45, 'unset' => 49),
53959 'cyan' => array('set' => 46, 'unset' => 49),
53960 'white' => array('set' => 47, 'unset' => 49),
53961 'default' => array('set' => 49, 'unset' => 49),
53962 );
53963 private static $availableOptions = array(
53964 'bold' => array('set' => 1, 'unset' => 22),
53965 'underscore' => array('set' => 4, 'unset' => 24),
53966 'blink' => array('set' => 5, 'unset' => 25),
53967 'reverse' => array('set' => 7, 'unset' => 27),
53968 'conceal' => array('set' => 8, 'unset' => 28),
53969 );
53970
53971 private $foreground;
53972 private $background;
53973 private $options = array();
53974
53975
53976
53977
53978
53979
53980
53981
53982 public function __construct($foreground = null, $background = null, array $options = array())
53983 {
53984 if (null !== $foreground) {
53985 $this->setForeground($foreground);
53986 }
53987 if (null !== $background) {
53988 $this->setBackground($background);
53989 }
53990 if (\count($options)) {
53991 $this->setOptions($options);
53992 }
53993 }
53994
53995
53996
53997
53998
53999
54000
54001
54002 public function setForeground($color = null)
54003 {
54004 if (null === $color) {
54005 $this->foreground = null;
54006
54007 return;
54008 }
54009
54010 if (!isset(static::$availableForegroundColors[$color])) {
54011 throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors))));
54012 }
54013
54014 $this->foreground = static::$availableForegroundColors[$color];
54015 }
54016
54017
54018
54019
54020
54021
54022
54023
54024 public function setBackground($color = null)
54025 {
54026 if (null === $color) {
54027 $this->background = null;
54028
54029 return;
54030 }
54031
54032 if (!isset(static::$availableBackgroundColors[$color])) {
54033 throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors))));
54034 }
54035
54036 $this->background = static::$availableBackgroundColors[$color];
54037 }
54038
54039
54040
54041
54042
54043
54044
54045
54046 public function setOption($option)
54047 {
54048 if (!isset(static::$availableOptions[$option])) {
54049 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
54050 }
54051
54052 if (!\in_array(static::$availableOptions[$option], $this->options)) {
54053 $this->options[] = static::$availableOptions[$option];
54054 }
54055 }
54056
54057
54058
54059
54060
54061
54062
54063
54064 public function unsetOption($option)
54065 {
54066 if (!isset(static::$availableOptions[$option])) {
54067 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
54068 }
54069
54070 $pos = array_search(static::$availableOptions[$option], $this->options);
54071 if (false !== $pos) {
54072 unset($this->options[$pos]);
54073 }
54074 }
54075
54076
54077
54078
54079 public function setOptions(array $options)
54080 {
54081 $this->options = array();
54082
54083 foreach ($options as $option) {
54084 $this->setOption($option);
54085 }
54086 }
54087
54088
54089
54090
54091
54092
54093
54094
54095 public function apply($text)
54096 {
54097 $setCodes = array();
54098 $unsetCodes = array();
54099
54100 if (null !== $this->foreground) {
54101 $setCodes[] = $this->foreground['set'];
54102 $unsetCodes[] = $this->foreground['unset'];
54103 }
54104 if (null !== $this->background) {
54105 $setCodes[] = $this->background['set'];
54106 $unsetCodes[] = $this->background['unset'];
54107 }
54108 if (\count($this->options)) {
54109 foreach ($this->options as $option) {
54110 $setCodes[] = $option['set'];
54111 $unsetCodes[] = $option['unset'];
54112 }
54113 }
54114
54115 if (0 === \count($setCodes)) {
54116 return $text;
54117 }
54118
54119 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
54120 }
54121 }
54122 <?php
54123
54124
54125
54126
54127
54128
54129
54130
54131
54132
54133 namespace Symfony\Component\Console\Formatter;
54134
54135
54136
54137
54138
54139
54140 interface OutputFormatterStyleInterface
54141 {
54142
54143
54144
54145
54146
54147 public function setForeground($color = null);
54148
54149
54150
54151
54152
54153
54154 public function setBackground($color = null);
54155
54156
54157
54158
54159
54160
54161 public function setOption($option);
54162
54163
54164
54165
54166
54167
54168 public function unsetOption($option);
54169
54170
54171
54172
54173 public function setOptions(array $options);
54174
54175
54176
54177
54178
54179
54180
54181
54182 public function apply($text);
54183 }
54184 <?php
54185
54186
54187
54188
54189
54190
54191
54192
54193
54194
54195 namespace Symfony\Component\Console\Formatter;
54196
54197 use Symfony\Component\Console\Exception\InvalidArgumentException;
54198
54199
54200
54201
54202 class OutputFormatterStyleStack
54203 {
54204
54205
54206
54207 private $styles;
54208
54209 private $emptyStyle;
54210
54211 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
54212 {
54213 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
54214 $this->reset();
54215 }
54216
54217
54218
54219
54220 public function reset()
54221 {
54222 $this->styles = array();
54223 }
54224
54225
54226
54227
54228 public function push(OutputFormatterStyleInterface $style)
54229 {
54230 $this->styles[] = $style;
54231 }
54232
54233
54234
54235
54236
54237
54238
54239
54240 public function pop(OutputFormatterStyleInterface $style = null)
54241 {
54242 if (empty($this->styles)) {
54243 return $this->emptyStyle;
54244 }
54245
54246 if (null === $style) {
54247 return array_pop($this->styles);
54248 }
54249
54250 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
54251 if ($style->apply('') === $stackedStyle->apply('')) {
54252 $this->styles = \array_slice($this->styles, 0, $index);
54253
54254 return $stackedStyle;
54255 }
54256 }
54257
54258 throw new InvalidArgumentException('Incorrectly nested style tag found.');
54259 }
54260
54261
54262
54263
54264
54265
54266 public function getCurrent()
54267 {
54268 if (empty($this->styles)) {
54269 return $this->emptyStyle;
54270 }
54271
54272 return $this->styles[\count($this->styles) - 1];
54273 }
54274
54275
54276
54277
54278 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
54279 {
54280 $this->emptyStyle = $emptyStyle;
54281
54282 return $this;
54283 }
54284
54285
54286
54287
54288 public function getEmptyStyle()
54289 {
54290 return $this->emptyStyle;
54291 }
54292 }
54293 <?php
54294
54295
54296
54297
54298
54299
54300
54301
54302
54303
54304 namespace Symfony\Component\Console\Helper;
54305
54306
54307
54308
54309
54310
54311
54312
54313 class DebugFormatterHelper extends Helper
54314 {
54315 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
54316 private $started = array();
54317 private $count = -1;
54318
54319
54320
54321
54322
54323
54324
54325
54326
54327
54328 public function start($id, $message, $prefix = 'RUN')
54329 {
54330 $this->started[$id] = array('border' => ++$this->count % \count($this->colors));
54331
54332 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
54333 }
54334
54335
54336
54337
54338
54339
54340
54341
54342
54343
54344
54345
54346 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
54347 {
54348 $message = '';
54349
54350 if ($error) {
54351 if (isset($this->started[$id]['out'])) {
54352 $message .= "\n";
54353 unset($this->started[$id]['out']);
54354 }
54355 if (!isset($this->started[$id]['err'])) {
54356 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
54357 $this->started[$id]['err'] = true;
54358 }
54359
54360 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
54361 } else {
54362 if (isset($this->started[$id]['err'])) {
54363 $message .= "\n";
54364 unset($this->started[$id]['err']);
54365 }
54366 if (!isset($this->started[$id]['out'])) {
54367 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
54368 $this->started[$id]['out'] = true;
54369 }
54370
54371 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
54372 }
54373
54374 return $message;
54375 }
54376
54377
54378
54379
54380
54381
54382
54383
54384
54385
54386
54387 public function stop($id, $message, $successful, $prefix = 'RES')
54388 {
54389 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
54390
54391 if ($successful) {
54392 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
54393 }
54394
54395 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
54396
54397 unset($this->started[$id]['out'], $this->started[$id]['err']);
54398
54399 return $message;
54400 }
54401
54402
54403
54404
54405
54406
54407 private function getBorder($id)
54408 {
54409 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
54410 }
54411
54412
54413
54414
54415 public function getName()
54416 {
54417 return 'debug_formatter';
54418 }
54419 }
54420 <?php
54421
54422
54423
54424
54425
54426
54427
54428
54429
54430
54431 namespace Symfony\Component\Console\Helper;
54432
54433 use Symfony\Component\Console\Descriptor\DescriptorInterface;
54434 use Symfony\Component\Console\Descriptor\JsonDescriptor;
54435 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
54436 use Symfony\Component\Console\Descriptor\TextDescriptor;
54437 use Symfony\Component\Console\Descriptor\XmlDescriptor;
54438 use Symfony\Component\Console\Exception\InvalidArgumentException;
54439 use Symfony\Component\Console\Output\OutputInterface;
54440
54441
54442
54443
54444
54445
54446 class DescriptorHelper extends Helper
54447 {
54448
54449
54450
54451 private $descriptors = array();
54452
54453 public function __construct()
54454 {
54455 $this
54456 ->register('txt', new TextDescriptor())
54457 ->register('xml', new XmlDescriptor())
54458 ->register('json', new JsonDescriptor())
54459 ->register('md', new MarkdownDescriptor())
54460 ;
54461 }
54462
54463
54464
54465
54466
54467
54468
54469
54470
54471
54472
54473
54474
54475
54476 public function describe(OutputInterface $output, $object, array $options = array())
54477 {
54478 $options = array_merge(array(
54479 'raw_text' => false,
54480 'format' => 'txt',
54481 ), $options);
54482
54483 if (!isset($this->descriptors[$options['format']])) {
54484 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
54485 }
54486
54487 $descriptor = $this->descriptors[$options['format']];
54488 $descriptor->describe($output, $object, $options);
54489 }
54490
54491
54492
54493
54494
54495
54496
54497
54498
54499 public function register($format, DescriptorInterface $descriptor)
54500 {
54501 $this->descriptors[$format] = $descriptor;
54502
54503 return $this;
54504 }
54505
54506
54507
54508
54509 public function getName()
54510 {
54511 return 'descriptor';
54512 }
54513 }
54514 <?php
54515
54516
54517
54518
54519
54520
54521
54522
54523
54524
54525 namespace Symfony\Component\Console\Helper;
54526
54527 use Symfony\Component\Console\Exception\InvalidArgumentException;
54528 use Symfony\Component\Console\Exception\RuntimeException;
54529 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
54530 use Symfony\Component\Console\Output\ConsoleOutputInterface;
54531 use Symfony\Component\Console\Output\OutputInterface;
54532
54533
54534
54535
54536
54537
54538
54539
54540
54541 class DialogHelper extends InputAwareHelper
54542 {
54543 private $inputStream;
54544 private static $shell;
54545 private static $stty;
54546
54547 public function __construct($triggerDeprecationError = true)
54548 {
54549 if ($triggerDeprecationError) {
54550 @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);
54551 }
54552 }
54553
54554
54555
54556
54557
54558
54559
54560
54561
54562
54563
54564
54565
54566
54567
54568
54569 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
54570 {
54571 if ($output instanceof ConsoleOutputInterface) {
54572 $output = $output->getErrorOutput();
54573 }
54574
54575 $width = max(array_map('strlen', array_keys($choices)));
54576
54577 $messages = (array) $question;
54578 foreach ($choices as $key => $value) {
54579 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
54580 }
54581
54582 $output->writeln($messages);
54583
54584 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
54585
54586  $selectedChoices = str_replace(' ', '', $picked);
54587
54588 if ($multiselect) {
54589
54590  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
54591 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
54592 }
54593 $selectedChoices = explode(',', $selectedChoices);
54594 } else {
54595 $selectedChoices = array($picked);
54596 }
54597
54598 $multiselectChoices = array();
54599
54600 foreach ($selectedChoices as $value) {
54601 if (empty($choices[$value])) {
54602 throw new InvalidArgumentException(sprintf($errorMessage, $value));
54603 }
54604 $multiselectChoices[] = $value;
54605 }
54606
54607 if ($multiselect) {
54608 return $multiselectChoices;
54609 }
54610
54611 return $picked;
54612 }, $attempts, $default);
54613
54614 return $result;
54615 }
54616
54617
54618
54619
54620
54621
54622
54623
54624
54625
54626
54627
54628
54629 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
54630 {
54631 if ($this->input && !$this->input->isInteractive()) {
54632 return $default;
54633 }
54634
54635 if ($output instanceof ConsoleOutputInterface) {
54636 $output = $output->getErrorOutput();
54637 }
54638
54639 $output->write($question);
54640
54641 $inputStream = $this->inputStream ?: STDIN;
54642
54643 if (null === $autocomplete || !$this->hasSttyAvailable()) {
54644 $ret = fgets($inputStream, 4096);
54645 if (false === $ret) {
54646 throw new RuntimeException('Aborted');
54647 }
54648 $ret = trim($ret);
54649 } else {
54650 $ret = '';
54651
54652 $i = 0;
54653 $ofs = -1;
54654 $matches = $autocomplete;
54655 $numMatches = \count($matches);
54656
54657 $sttyMode = shell_exec('stty -g');
54658
54659
54660  shell_exec('stty -icanon -echo');
54661
54662
54663  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
54664
54665
54666  while (!feof($inputStream)) {
54667 $c = fread($inputStream, 1);
54668
54669
54670  if ("\177" === $c) {
54671 if (0 === $numMatches && 0 !== $i) {
54672 --$i;
54673
54674  $output->write("\033[1D");
54675 }
54676
54677 if (0 === $i) {
54678 $ofs = -1;
54679 $matches = $autocomplete;
54680 $numMatches = \count($matches);
54681 } else {
54682 $numMatches = 0;
54683 }
54684
54685
54686  $ret = substr($ret, 0, $i);
54687 } elseif ("\033" === $c) {
54688
54689  $c .= fread($inputStream, 2);
54690
54691
54692  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
54693 if ('A' === $c[2] && -1 === $ofs) {
54694 $ofs = 0;
54695 }
54696
54697 if (0 === $numMatches) {
54698 continue;
54699 }
54700
54701 $ofs += ('A' === $c[2]) ? -1 : 1;
54702 $ofs = ($numMatches + $ofs) % $numMatches;
54703 }
54704 } elseif (\ord($c) < 32) {
54705 if ("\t" === $c || "\n" === $c) {
54706 if ($numMatches > 0 && -1 !== $ofs) {
54707 $ret = $matches[$ofs];
54708
54709  $output->write(substr($ret, $i));
54710 $i = \strlen($ret);
54711 }
54712
54713 if ("\n" === $c) {
54714 $output->write($c);
54715 break;
54716 }
54717
54718 $numMatches = 0;
54719 }
54720
54721 continue;
54722 } else {
54723 $output->write($c);
54724 $ret .= $c;
54725 ++$i;
54726
54727 $numMatches = 0;
54728 $ofs = 0;
54729
54730 foreach ($autocomplete as $value) {
54731
54732  if (0 === strpos($value, $ret) && $i !== \strlen($value)) {
54733 $matches[$numMatches++] = $value;
54734 }
54735 }
54736 }
54737
54738
54739  $output->write("\033[K");
54740
54741 if ($numMatches > 0 && -1 !== $ofs) {
54742
54743  $output->write("\0337");
54744
54745  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
54746
54747  $output->write("\0338");
54748 }
54749 }
54750
54751
54752  shell_exec(sprintf('stty %s', $sttyMode));
54753 }
54754
54755 return \strlen($ret) > 0 ? $ret : $default;
54756 }
54757
54758
54759
54760
54761
54762
54763
54764
54765
54766
54767
54768
54769 public function askConfirmation(OutputInterface $output, $question, $default = true)
54770 {
54771 $answer = 'z';
54772 while ($answer && !\in_array(strtolower($answer[0]), array('y', 'n'))) {
54773 $answer = $this->ask($output, $question);
54774 }
54775
54776 if (false === $default) {
54777 return $answer && 'y' == strtolower($answer[0]);
54778 }
54779
54780 return !$answer || 'y' == strtolower($answer[0]);
54781 }
54782
54783
54784
54785
54786
54787
54788
54789
54790
54791
54792
54793
54794 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
54795 {
54796 if ($output instanceof ConsoleOutputInterface) {
54797 $output = $output->getErrorOutput();
54798 }
54799
54800 if ('\\' === \DIRECTORY_SEPARATOR) {
54801 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
54802
54803
54804  if ('phar:' === substr(__FILE__, 0, 5)) {
54805 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
54806 copy($exe, $tmpExe);
54807 $exe = $tmpExe;
54808 }
54809
54810 $output->write($question);
54811 $value = rtrim(shell_exec($exe));
54812 $output->writeln('');
54813
54814 if (isset($tmpExe)) {
54815 unlink($tmpExe);
54816 }
54817
54818 return $value;
54819 }
54820
54821 if ($this->hasSttyAvailable()) {
54822 $output->write($question);
54823
54824 $sttyMode = shell_exec('stty -g');
54825
54826 shell_exec('stty -echo');
54827 $value = fgets($this->inputStream ?: STDIN, 4096);
54828 shell_exec(sprintf('stty %s', $sttyMode));
54829
54830 if (false === $value) {
54831 throw new RuntimeException('Aborted');
54832 }
54833
54834 $value = trim($value);
54835 $output->writeln('');
54836
54837 return $value;
54838 }
54839
54840 if (false !== $shell = $this->getShell()) {
54841 $output->write($question);
54842 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
54843 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
54844 $value = rtrim(shell_exec($command));
54845 $output->writeln('');
54846
54847 return $value;
54848 }
54849
54850 if ($fallback) {
54851 return $this->ask($output, $question);
54852 }
54853
54854 throw new RuntimeException('Unable to hide the response');
54855 }
54856
54857
54858
54859
54860
54861
54862
54863
54864
54865
54866
54867
54868
54869
54870
54871
54872
54873
54874
54875 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
54876 {
54877 $that = $this;
54878
54879 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
54880 return $that->ask($output, $question, $default, $autocomplete);
54881 };
54882
54883 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
54884 }
54885
54886
54887
54888
54889
54890
54891
54892
54893
54894
54895
54896
54897
54898
54899
54900
54901
54902
54903
54904 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
54905 {
54906 $that = $this;
54907
54908 $interviewer = function () use ($output, $question, $fallback, $that) {
54909 return $that->askHiddenResponse($output, $question, $fallback);
54910 };
54911
54912 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
54913 }
54914
54915
54916
54917
54918
54919
54920
54921
54922 public function setInputStream($stream)
54923 {
54924 $this->inputStream = $stream;
54925 }
54926
54927
54928
54929
54930
54931
54932 public function getInputStream()
54933 {
54934 return $this->inputStream;
54935 }
54936
54937
54938
54939
54940 public function getName()
54941 {
54942 return 'dialog';
54943 }
54944
54945
54946
54947
54948
54949
54950 private function getShell()
54951 {
54952 if (null !== self::$shell) {
54953 return self::$shell;
54954 }
54955
54956 self::$shell = false;
54957
54958 if (file_exists('/usr/bin/env')) {
54959
54960  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
54961 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
54962 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
54963 self::$shell = $sh;
54964 break;
54965 }
54966 }
54967 }
54968
54969 return self::$shell;
54970 }
54971
54972 private function hasSttyAvailable()
54973 {
54974 if (null !== self::$stty) {
54975 return self::$stty;
54976 }
54977
54978 exec('stty 2>&1', $output, $exitcode);
54979
54980 return self::$stty = 0 === $exitcode;
54981 }
54982
54983
54984
54985
54986
54987
54988
54989
54990
54991
54992
54993
54994
54995 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
54996 {
54997 if ($output instanceof ConsoleOutputInterface) {
54998 $output = $output->getErrorOutput();
54999 }
55000
55001 $e = null;
55002 while (false === $attempts || $attempts--) {
55003 if (null !== $e) {
55004 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
55005 }
55006
55007 try {
55008 return \call_user_func($validator, $interviewer());
55009 } catch (\Exception $e) {
55010 }
55011 }
55012
55013 throw $e;
55014 }
55015 }
55016 <?php
55017
55018
55019
55020
55021
55022
55023
55024
55025
55026
55027 namespace Symfony\Component\Console\Helper;
55028
55029 use Symfony\Component\Console\Formatter\OutputFormatter;
55030
55031
55032
55033
55034
55035
55036 class FormatterHelper extends Helper
55037 {
55038
55039
55040
55041
55042
55043
55044
55045
55046
55047 public function formatSection($section, $message, $style = 'info')
55048 {
55049 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
55050 }
55051
55052
55053
55054
55055
55056
55057
55058
55059
55060
55061 public function formatBlock($messages, $style, $large = false)
55062 {
55063 if (!\is_array($messages)) {
55064 $messages = array($messages);
55065 }
55066
55067 $len = 0;
55068 $lines = array();
55069 foreach ($messages as $message) {
55070 $message = OutputFormatter::escape($message);
55071 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
55072 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
55073 }
55074
55075 $messages = $large ? array(str_repeat(' ', $len)) : array();
55076 for ($i = 0; isset($lines[$i]); ++$i) {
55077 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
55078 }
55079 if ($large) {
55080 $messages[] = str_repeat(' ', $len);
55081 }
55082
55083 for ($i = 0; isset($messages[$i]); ++$i) {
55084 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
55085 }
55086
55087 return implode("\n", $messages);
55088 }
55089
55090
55091
55092
55093 public function getName()
55094 {
55095 return 'formatter';
55096 }
55097 }
55098 <?php
55099
55100
55101
55102
55103
55104
55105
55106
55107
55108
55109 namespace Symfony\Component\Console\Helper;
55110
55111 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
55112
55113
55114
55115
55116
55117
55118 abstract class Helper implements HelperInterface
55119 {
55120 protected $helperSet = null;
55121
55122
55123
55124
55125 public function setHelperSet(HelperSet $helperSet = null)
55126 {
55127 $this->helperSet = $helperSet;
55128 }
55129
55130
55131
55132
55133 public function getHelperSet()
55134 {
55135 return $this->helperSet;
55136 }
55137
55138
55139
55140
55141
55142
55143
55144
55145 public static function strlen($string)
55146 {
55147 if (false === $encoding = mb_detect_encoding($string, null, true)) {
55148 return \strlen($string);
55149 }
55150
55151 return mb_strwidth($string, $encoding);
55152 }
55153
55154 public static function formatTime($secs)
55155 {
55156 static $timeFormats = array(
55157 array(0, '< 1 sec'),
55158 array(1, '1 sec'),
55159 array(2, 'secs', 1),
55160 array(60, '1 min'),
55161 array(120, 'mins', 60),
55162 array(3600, '1 hr'),
55163 array(7200, 'hrs', 3600),
55164 array(86400, '1 day'),
55165 array(172800, 'days', 86400),
55166 );
55167
55168 foreach ($timeFormats as $index => $format) {
55169 if ($secs >= $format[0]) {
55170 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
55171 || $index == \count($timeFormats) - 1
55172 ) {
55173 if (2 == \count($format)) {
55174 return $format[1];
55175 }
55176
55177 return floor($secs / $format[2]).' '.$format[1];
55178 }
55179 }
55180 }
55181 }
55182
55183 public static function formatMemory($memory)
55184 {
55185 if ($memory >= 1024 * 1024 * 1024) {
55186 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
55187 }
55188
55189 if ($memory >= 1024 * 1024) {
55190 return sprintf('%.1f MiB', $memory / 1024 / 1024);
55191 }
55192
55193 if ($memory >= 1024) {
55194 return sprintf('%d KiB', $memory / 1024);
55195 }
55196
55197 return sprintf('%d B', $memory);
55198 }
55199
55200 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
55201 {
55202 return self::strlen(self::removeDecoration($formatter, $string));
55203 }
55204
55205 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
55206 {
55207 $isDecorated = $formatter->isDecorated();
55208 $formatter->setDecorated(false);
55209
55210  $string = $formatter->format($string);
55211
55212  $string = preg_replace("/\033\[[^m]*m/", '', $string);
55213 $formatter->setDecorated($isDecorated);
55214
55215 return $string;
55216 }
55217 }
55218 <?php
55219
55220
55221
55222
55223
55224
55225
55226
55227
55228
55229 namespace Symfony\Component\Console\Helper;
55230
55231
55232
55233
55234
55235
55236 interface HelperInterface
55237 {
55238
55239
55240
55241 public function setHelperSet(HelperSet $helperSet = null);
55242
55243
55244
55245
55246
55247
55248 public function getHelperSet();
55249
55250
55251
55252
55253
55254
55255 public function getName();
55256 }
55257 <?php
55258
55259
55260
55261
55262
55263
55264
55265
55266
55267
55268 namespace Symfony\Component\Console\Helper;
55269
55270 use Symfony\Component\Console\Command\Command;
55271 use Symfony\Component\Console\Exception\InvalidArgumentException;
55272
55273
55274
55275
55276
55277
55278 class HelperSet implements \IteratorAggregate
55279 {
55280
55281
55282
55283 private $helpers = array();
55284 private $command;
55285
55286
55287
55288
55289 public function __construct(array $helpers = array())
55290 {
55291 foreach ($helpers as $alias => $helper) {
55292 $this->set($helper, \is_int($alias) ? null : $alias);
55293 }
55294 }
55295
55296
55297
55298
55299
55300
55301
55302 public function set(HelperInterface $helper, $alias = null)
55303 {
55304 $this->helpers[$helper->getName()] = $helper;
55305 if (null !== $alias) {
55306 $this->helpers[$alias] = $helper;
55307 }
55308
55309 $helper->setHelperSet($this);
55310 }
55311
55312
55313
55314
55315
55316
55317
55318
55319 public function has($name)
55320 {
55321 return isset($this->helpers[$name]);
55322 }
55323
55324
55325
55326
55327
55328
55329
55330
55331
55332
55333 public function get($name)
55334 {
55335 if (!$this->has($name)) {
55336 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
55337 }
55338
55339 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
55340 @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);
55341 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
55342 @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);
55343 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
55344 @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);
55345 }
55346
55347 return $this->helpers[$name];
55348 }
55349
55350 public function setCommand(Command $command = null)
55351 {
55352 $this->command = $command;
55353 }
55354
55355
55356
55357
55358
55359
55360 public function getCommand()
55361 {
55362 return $this->command;
55363 }
55364
55365
55366
55367
55368 public function getIterator()
55369 {
55370 return new \ArrayIterator($this->helpers);
55371 }
55372 }
55373 <?php
55374
55375
55376
55377
55378
55379
55380
55381
55382
55383
55384 namespace Symfony\Component\Console\Helper;
55385
55386 use Symfony\Component\Console\Input\InputAwareInterface;
55387 use Symfony\Component\Console\Input\InputInterface;
55388
55389
55390
55391
55392
55393
55394 abstract class InputAwareHelper extends Helper implements InputAwareInterface
55395 {
55396 protected $input;
55397
55398
55399
55400
55401 public function setInput(InputInterface $input)
55402 {
55403 $this->input = $input;
55404 }
55405 }
55406 <?php
55407
55408
55409
55410
55411
55412
55413
55414
55415
55416
55417 namespace Symfony\Component\Console\Helper;
55418
55419 use Symfony\Component\Console\Output\ConsoleOutputInterface;
55420 use Symfony\Component\Console\Output\OutputInterface;
55421 use Symfony\Component\Process\Exception\ProcessFailedException;
55422 use Symfony\Component\Process\Process;
55423 use Symfony\Component\Process\ProcessBuilder;
55424
55425
55426
55427
55428
55429
55430 class ProcessHelper extends Helper
55431 {
55432
55433
55434
55435
55436
55437
55438
55439
55440
55441
55442
55443
55444 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
55445 {
55446 if ($output instanceof ConsoleOutputInterface) {
55447 $output = $output->getErrorOutput();
55448 }
55449
55450 $formatter = $this->getHelperSet()->get('debug_formatter');
55451
55452 if (\is_array($cmd)) {
55453 $process = ProcessBuilder::create($cmd)->getProcess();
55454 } elseif ($cmd instanceof Process) {
55455 $process = $cmd;
55456 } else {
55457 $process = new Process($cmd);
55458 }
55459
55460 if ($verbosity <= $output->getVerbosity()) {
55461 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
55462 }
55463
55464 if ($output->isDebug()) {
55465 $callback = $this->wrapCallback($output, $process, $callback);
55466 }
55467
55468 $process->run($callback);
55469
55470 if ($verbosity <= $output->getVerbosity()) {
55471 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
55472 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
55473 }
55474
55475 if (!$process->isSuccessful() && null !== $error) {
55476 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
55477 }
55478
55479 return $process;
55480 }
55481
55482
55483
55484
55485
55486
55487
55488
55489
55490
55491
55492
55493
55494
55495
55496
55497
55498
55499
55500 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
55501 {
55502 $process = $this->run($output, $cmd, $error, $callback);
55503
55504 if (!$process->isSuccessful()) {
55505 throw new ProcessFailedException($process);
55506 }
55507
55508 return $process;
55509 }
55510
55511
55512
55513
55514
55515
55516
55517
55518
55519
55520 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
55521 {
55522 if ($output instanceof ConsoleOutputInterface) {
55523 $output = $output->getErrorOutput();
55524 }
55525
55526 $formatter = $this->getHelperSet()->get('debug_formatter');
55527
55528 $that = $this;
55529
55530 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
55531 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
55532
55533 if (null !== $callback) {
55534 \call_user_func($callback, $type, $buffer);
55535 }
55536 };
55537 }
55538
55539
55540
55541
55542
55543
55544 public function escapeString($str)
55545 {
55546 return str_replace('<', '\\<', $str);
55547 }
55548
55549
55550
55551
55552 public function getName()
55553 {
55554 return 'process';
55555 }
55556 }
55557 <?php
55558
55559
55560
55561
55562
55563
55564
55565
55566
55567
55568 namespace Symfony\Component\Console\Helper;
55569
55570 use Symfony\Component\Console\Exception\LogicException;
55571 use Symfony\Component\Console\Output\ConsoleOutputInterface;
55572 use Symfony\Component\Console\Output\OutputInterface;
55573
55574
55575
55576
55577
55578
55579
55580 class ProgressBar
55581 {
55582 private $barWidth = 28;
55583 private $barChar;
55584 private $emptyBarChar = '-';
55585 private $progressChar = '>';
55586 private $format;
55587 private $internalFormat;
55588 private $redrawFreq = 1;
55589 private $output;
55590 private $step = 0;
55591 private $max;
55592 private $startTime;
55593 private $stepWidth;
55594 private $percent = 0.0;
55595 private $formatLineCount;
55596 private $messages = array();
55597 private $overwrite = true;
55598 private $firstRun = true;
55599
55600 private static $formatters;
55601 private static $formats;
55602
55603
55604
55605
55606
55607 public function __construct(OutputInterface $output, $max = 0)
55608 {
55609 if ($output instanceof ConsoleOutputInterface) {
55610 $output = $output->getErrorOutput();
55611 }
55612
55613 $this->output = $output;
55614 $this->setMaxSteps($max);
55615
55616 if (!$this->output->isDecorated()) {
55617
55618  $this->overwrite = false;
55619
55620
55621  $this->setRedrawFrequency($max / 10);
55622 }
55623
55624 $this->startTime = time();
55625 }
55626
55627
55628
55629
55630
55631
55632
55633
55634
55635 public static function setPlaceholderFormatterDefinition($name, $callable)
55636 {
55637 if (!self::$formatters) {
55638 self::$formatters = self::initPlaceholderFormatters();
55639 }
55640
55641 self::$formatters[$name] = $callable;
55642 }
55643
55644
55645
55646
55647
55648
55649
55650
55651 public static function getPlaceholderFormatterDefinition($name)
55652 {
55653 if (!self::$formatters) {
55654 self::$formatters = self::initPlaceholderFormatters();
55655 }
55656
55657 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
55658 }
55659
55660
55661
55662
55663
55664
55665
55666
55667
55668 public static function setFormatDefinition($name, $format)
55669 {
55670 if (!self::$formats) {
55671 self::$formats = self::initFormats();
55672 }
55673
55674 self::$formats[$name] = $format;
55675 }
55676
55677
55678
55679
55680
55681
55682
55683
55684 public static function getFormatDefinition($name)
55685 {
55686 if (!self::$formats) {
55687 self::$formats = self::initFormats();
55688 }
55689
55690 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
55691 }
55692
55693
55694
55695
55696
55697
55698
55699
55700
55701
55702
55703 public function setMessage($message, $name = 'message')
55704 {
55705 $this->messages[$name] = $message;
55706 }
55707
55708 public function getMessage($name = 'message')
55709 {
55710 return $this->messages[$name];
55711 }
55712
55713
55714
55715
55716
55717
55718 public function getStartTime()
55719 {
55720 return $this->startTime;
55721 }
55722
55723
55724
55725
55726
55727
55728 public function getMaxSteps()
55729 {
55730 return $this->max;
55731 }
55732
55733
55734
55735
55736
55737
55738
55739
55740 public function getStep()
55741 {
55742 @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);
55743
55744 return $this->getProgress();
55745 }
55746
55747
55748
55749
55750
55751
55752 public function getProgress()
55753 {
55754 return $this->step;
55755 }
55756
55757
55758
55759
55760
55761
55762
55763
55764 public function getStepWidth()
55765 {
55766 return $this->stepWidth;
55767 }
55768
55769
55770
55771
55772
55773
55774 public function getProgressPercent()
55775 {
55776 return $this->percent;
55777 }
55778
55779
55780
55781
55782
55783
55784 public function setBarWidth($size)
55785 {
55786 $this->barWidth = (int) $size;
55787 }
55788
55789
55790
55791
55792
55793
55794 public function getBarWidth()
55795 {
55796 return $this->barWidth;
55797 }
55798
55799
55800
55801
55802
55803
55804 public function setBarCharacter($char)
55805 {
55806 $this->barChar = $char;
55807 }
55808
55809
55810
55811
55812
55813
55814 public function getBarCharacter()
55815 {
55816 if (null === $this->barChar) {
55817 return $this->max ? '=' : $this->emptyBarChar;
55818 }
55819
55820 return $this->barChar;
55821 }
55822
55823
55824
55825
55826
55827
55828 public function setEmptyBarCharacter($char)
55829 {
55830 $this->emptyBarChar = $char;
55831 }
55832
55833
55834
55835
55836
55837
55838 public function getEmptyBarCharacter()
55839 {
55840 return $this->emptyBarChar;
55841 }
55842
55843
55844
55845
55846
55847
55848 public function setProgressCharacter($char)
55849 {
55850 $this->progressChar = $char;
55851 }
55852
55853
55854
55855
55856
55857
55858 public function getProgressCharacter()
55859 {
55860 return $this->progressChar;
55861 }
55862
55863
55864
55865
55866
55867
55868 public function setFormat($format)
55869 {
55870 $this->format = null;
55871 $this->internalFormat = $format;
55872 }
55873
55874
55875
55876
55877
55878
55879 public function setRedrawFrequency($freq)
55880 {
55881 $this->redrawFreq = max((int) $freq, 1);
55882 }
55883
55884
55885
55886
55887
55888
55889 public function start($max = null)
55890 {
55891 $this->startTime = time();
55892 $this->step = 0;
55893 $this->percent = 0.0;
55894
55895 if (null !== $max) {
55896 $this->setMaxSteps($max);
55897 }
55898
55899 $this->display();
55900 }
55901
55902
55903
55904
55905
55906
55907
55908
55909 public function advance($step = 1)
55910 {
55911 $this->setProgress($this->step + $step);
55912 }
55913
55914
55915
55916
55917
55918
55919
55920
55921
55922
55923 public function setCurrent($step)
55924 {
55925 @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);
55926
55927 $this->setProgress($step);
55928 }
55929
55930
55931
55932
55933
55934
55935 public function setOverwrite($overwrite)
55936 {
55937 $this->overwrite = (bool) $overwrite;
55938 }
55939
55940
55941
55942
55943
55944
55945
55946
55947 public function setProgress($step)
55948 {
55949 $step = (int) $step;
55950 if ($step < $this->step) {
55951 throw new LogicException('You can\'t regress the progress bar.');
55952 }
55953
55954 if ($this->max && $step > $this->max) {
55955 $this->max = $step;
55956 }
55957
55958 $prevPeriod = (int) ($this->step / $this->redrawFreq);
55959 $currPeriod = (int) ($step / $this->redrawFreq);
55960 $this->step = $step;
55961 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
55962 if ($prevPeriod !== $currPeriod || $this->max === $step) {
55963 $this->display();
55964 }
55965 }
55966
55967
55968
55969
55970 public function finish()
55971 {
55972 if (!$this->max) {
55973 $this->max = $this->step;
55974 }
55975
55976 if ($this->step === $this->max && !$this->overwrite) {
55977
55978  return;
55979 }
55980
55981 $this->setProgress($this->max);
55982 }
55983
55984
55985
55986
55987 public function display()
55988 {
55989 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
55990 return;
55991 }
55992
55993 if (null === $this->format) {
55994 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
55995 }
55996
55997
55998  $self = $this;
55999 $output = $this->output;
56000 $messages = $this->messages;
56001 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
56002 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
56003 $text = \call_user_func($formatter, $self, $output);
56004 } elseif (isset($messages[$matches[1]])) {
56005 $text = $messages[$matches[1]];
56006 } else {
56007 return $matches[0];
56008 }
56009
56010 if (isset($matches[2])) {
56011 $text = sprintf('%'.$matches[2], $text);
56012 }
56013
56014 return $text;
56015 }, $this->format));
56016 }
56017
56018
56019
56020
56021
56022
56023
56024
56025 public function clear()
56026 {
56027 if (!$this->overwrite) {
56028 return;
56029 }
56030
56031 if (null === $this->format) {
56032 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
56033 }
56034
56035 $this->overwrite('');
56036 }
56037
56038
56039
56040
56041
56042
56043 private function setRealFormat($format)
56044 {
56045
56046  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
56047 $this->format = self::getFormatDefinition($format.'_nomax');
56048 } elseif (null !== self::getFormatDefinition($format)) {
56049 $this->format = self::getFormatDefinition($format);
56050 } else {
56051 $this->format = $format;
56052 }
56053
56054 $this->formatLineCount = substr_count($this->format, "\n");
56055 }
56056
56057
56058
56059
56060
56061
56062 private function setMaxSteps($max)
56063 {
56064 $this->max = max(0, (int) $max);
56065 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
56066 }
56067
56068
56069
56070
56071
56072
56073 private function overwrite($message)
56074 {
56075 if ($this->overwrite) {
56076 if (!$this->firstRun) {
56077
56078  $this->output->write("\x0D");
56079
56080
56081  $this->output->write("\x1B[2K");
56082
56083
56084  if ($this->formatLineCount > 0) {
56085 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
56086 }
56087 }
56088 } elseif ($this->step > 0) {
56089 $this->output->writeln('');
56090 }
56091
56092 $this->firstRun = false;
56093
56094 $this->output->write($message);
56095 }
56096
56097 private function determineBestFormat()
56098 {
56099 switch ($this->output->getVerbosity()) {
56100
56101  case OutputInterface::VERBOSITY_VERBOSE:
56102 return $this->max ? 'verbose' : 'verbose_nomax';
56103 case OutputInterface::VERBOSITY_VERY_VERBOSE:
56104 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
56105 case OutputInterface::VERBOSITY_DEBUG:
56106 return $this->max ? 'debug' : 'debug_nomax';
56107 default:
56108 return $this->max ? 'normal' : 'normal_nomax';
56109 }
56110 }
56111
56112 private static function initPlaceholderFormatters()
56113 {
56114 return array(
56115 'bar' => function (ProgressBar $bar, OutputInterface $output) {
56116 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
56117 $display = str_repeat($bar->getBarCharacter(), $completeBars);
56118 if ($completeBars < $bar->getBarWidth()) {
56119 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
56120 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
56121 }
56122
56123 return $display;
56124 },
56125 'elapsed' => function (ProgressBar $bar) {
56126 return Helper::formatTime(time() - $bar->getStartTime());
56127 },
56128 'remaining' => function (ProgressBar $bar) {
56129 if (!$bar->getMaxSteps()) {
56130 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
56131 }
56132
56133 if (!$bar->getProgress()) {
56134 $remaining = 0;
56135 } else {
56136 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
56137 }
56138
56139 return Helper::formatTime($remaining);
56140 },
56141 'estimated' => function (ProgressBar $bar) {
56142 if (!$bar->getMaxSteps()) {
56143 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
56144 }
56145
56146 if (!$bar->getProgress()) {
56147 $estimated = 0;
56148 } else {
56149 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
56150 }
56151
56152 return Helper::formatTime($estimated);
56153 },
56154 'memory' => function (ProgressBar $bar) {
56155 return Helper::formatMemory(memory_get_usage(true));
56156 },
56157 'current' => function (ProgressBar $bar) {
56158 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
56159 },
56160 'max' => function (ProgressBar $bar) {
56161 return $bar->getMaxSteps();
56162 },
56163 'percent' => function (ProgressBar $bar) {
56164 return floor($bar->getProgressPercent() * 100);
56165 },
56166 );
56167 }
56168
56169 private static function initFormats()
56170 {
56171 return array(
56172 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
56173 'normal_nomax' => ' %current% [%bar%]',
56174
56175 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
56176 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
56177
56178 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
56179 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
56180
56181 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
56182 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
56183 );
56184 }
56185 }
56186 <?php
56187
56188
56189
56190
56191
56192
56193
56194
56195
56196
56197 namespace Symfony\Component\Console\Helper;
56198
56199 use Symfony\Component\Console\Exception\LogicException;
56200 use Symfony\Component\Console\Output\ConsoleOutputInterface;
56201 use Symfony\Component\Console\Output\NullOutput;
56202 use Symfony\Component\Console\Output\OutputInterface;
56203
56204
56205
56206
56207
56208
56209
56210
56211
56212
56213 class ProgressHelper extends Helper
56214 {
56215 const FORMAT_QUIET = ' %percent%%';
56216 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
56217 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
56218 const FORMAT_QUIET_NOMAX = ' %current%';
56219 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
56220 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
56221
56222
56223  private $barWidth = 28;
56224 private $barChar = '=';
56225 private $emptyBarChar = '-';
56226 private $progressChar = '>';
56227 private $format = null;
56228 private $redrawFreq = 1;
56229
56230 private $lastMessagesLength;
56231 private $barCharOriginal;
56232
56233
56234
56235
56236 private $output;
56237
56238
56239
56240
56241
56242
56243 private $current;
56244
56245
56246
56247
56248
56249
56250 private $max;
56251
56252
56253
56254
56255
56256
56257 private $startTime;
56258
56259
56260
56261
56262
56263
56264 private $defaultFormatVars = array(
56265 'current',
56266 'max',
56267 'bar',
56268 'percent',
56269 'elapsed',
56270 );
56271
56272
56273
56274
56275
56276
56277 private $formatVars;
56278
56279
56280
56281
56282
56283
56284 private $widths = array(
56285 'current' => 4,
56286 'max' => 4,
56287 'percent' => 3,
56288 'elapsed' => 6,
56289 );
56290
56291
56292
56293
56294
56295
56296 private $timeFormats = array(
56297 array(0, '???'),
56298 array(2, '1 sec'),
56299 array(59, 'secs', 1),
56300 array(60, '1 min'),
56301 array(3600, 'mins', 60),
56302 array(5400, '1 hr'),
56303 array(86400, 'hrs', 3600),
56304 array(129600, '1 day'),
56305 array(604800, 'days', 86400),
56306 );
56307
56308 public function __construct($triggerDeprecationError = true)
56309 {
56310 if ($triggerDeprecationError) {
56311 @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);
56312 }
56313 }
56314
56315
56316
56317
56318
56319
56320 public function setBarWidth($size)
56321 {
56322 $this->barWidth = (int) $size;
56323 }
56324
56325
56326
56327
56328
56329
56330 public function setBarCharacter($char)
56331 {
56332 $this->barChar = $char;
56333 }
56334
56335
56336
56337
56338
56339
56340 public function setEmptyBarCharacter($char)
56341 {
56342 $this->emptyBarChar = $char;
56343 }
56344
56345
56346
56347
56348
56349
56350 public function setProgressCharacter($char)
56351 {
56352 $this->progressChar = $char;
56353 }
56354
56355
56356
56357
56358
56359
56360 public function setFormat($format)
56361 {
56362 $this->format = $format;
56363 }
56364
56365
56366
56367
56368
56369
56370 public function setRedrawFrequency($freq)
56371 {
56372 $this->redrawFreq = (int) $freq;
56373 }
56374
56375
56376
56377
56378
56379
56380
56381 public function start(OutputInterface $output, $max = null)
56382 {
56383 if ($output instanceof ConsoleOutputInterface) {
56384 $output = $output->getErrorOutput();
56385 }
56386
56387 $this->startTime = time();
56388 $this->current = 0;
56389 $this->max = (int) $max;
56390
56391
56392  $this->output = $output->isDecorated() ? $output : new NullOutput();
56393 $this->lastMessagesLength = 0;
56394 $this->barCharOriginal = '';
56395
56396 if (null === $this->format) {
56397 switch ($output->getVerbosity()) {
56398 case OutputInterface::VERBOSITY_QUIET:
56399 $this->format = self::FORMAT_QUIET_NOMAX;
56400 if ($this->max > 0) {
56401 $this->format = self::FORMAT_QUIET;
56402 }
56403 break;
56404 case OutputInterface::VERBOSITY_VERBOSE:
56405 case OutputInterface::VERBOSITY_VERY_VERBOSE:
56406 case OutputInterface::VERBOSITY_DEBUG:
56407 $this->format = self::FORMAT_VERBOSE_NOMAX;
56408 if ($this->max > 0) {
56409 $this->format = self::FORMAT_VERBOSE;
56410 }
56411 break;
56412 default:
56413 $this->format = self::FORMAT_NORMAL_NOMAX;
56414 if ($this->max > 0) {
56415 $this->format = self::FORMAT_NORMAL;
56416 }
56417 break;
56418 }
56419 }
56420
56421 $this->initialize();
56422 }
56423
56424
56425
56426
56427
56428
56429
56430
56431
56432 public function advance($step = 1, $redraw = false)
56433 {
56434 $this->setCurrent($this->current + $step, $redraw);
56435 }
56436
56437
56438
56439
56440
56441
56442
56443
56444
56445 public function setCurrent($current, $redraw = false)
56446 {
56447 if (null === $this->startTime) {
56448 throw new LogicException('You must start the progress bar before calling setCurrent().');
56449 }
56450
56451 $current = (int) $current;
56452
56453 if ($current < $this->current) {
56454 throw new LogicException('You can\'t regress the progress bar');
56455 }
56456
56457 if (0 === $this->current) {
56458 $redraw = true;
56459 }
56460
56461 $prevPeriod = (int) ($this->current / $this->redrawFreq);
56462
56463 $this->current = $current;
56464
56465 $currPeriod = (int) ($this->current / $this->redrawFreq);
56466 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
56467 $this->display();
56468 }
56469 }
56470
56471
56472
56473
56474
56475
56476
56477
56478 public function display($finish = false)
56479 {
56480 if (null === $this->startTime) {
56481 throw new LogicException('You must start the progress bar before calling display().');
56482 }
56483
56484 $message = $this->format;
56485 foreach ($this->generate($finish) as $name => $value) {
56486 $message = str_replace("%{$name}%", $value, $message);
56487 }
56488 $this->overwrite($this->output, $message);
56489 }
56490
56491
56492
56493
56494
56495
56496
56497
56498 public function clear()
56499 {
56500 $this->overwrite($this->output, '');
56501 }
56502
56503
56504
56505
56506 public function finish()
56507 {
56508 if (null === $this->startTime) {
56509 throw new LogicException('You must start the progress bar before calling finish().');
56510 }
56511
56512 if (null !== $this->startTime) {
56513 if (!$this->max) {
56514 $this->barChar = $this->barCharOriginal;
56515 $this->display(true);
56516 }
56517 $this->startTime = null;
56518 $this->output->writeln('');
56519 $this->output = null;
56520 }
56521 }
56522
56523
56524
56525
56526 private function initialize()
56527 {
56528 $this->formatVars = array();
56529 foreach ($this->defaultFormatVars as $var) {
56530 if (false !== strpos($this->format, "%{$var}%")) {
56531 $this->formatVars[$var] = true;
56532 }
56533 }
56534
56535 if ($this->max > 0) {
56536 $this->widths['max'] = $this->strlen($this->max);
56537 $this->widths['current'] = $this->widths['max'];
56538 } else {
56539 $this->barCharOriginal = $this->barChar;
56540 $this->barChar = $this->emptyBarChar;
56541 }
56542 }
56543
56544
56545
56546
56547
56548
56549
56550
56551 private function generate($finish = false)
56552 {
56553 $vars = array();
56554 $percent = 0;
56555 if ($this->max > 0) {
56556 $percent = (float) $this->current / $this->max;
56557 }
56558
56559 if (isset($this->formatVars['bar'])) {
56560 if ($this->max > 0) {
56561 $completeBars = floor($percent * $this->barWidth);
56562 } else {
56563 if (!$finish) {
56564 $completeBars = floor($this->current % $this->barWidth);
56565 } else {
56566 $completeBars = $this->barWidth;
56567 }
56568 }
56569
56570 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
56571 $bar = str_repeat($this->barChar, $completeBars);
56572 if ($completeBars < $this->barWidth) {
56573 $bar .= $this->progressChar;
56574 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
56575 }
56576
56577 $vars['bar'] = $bar;
56578 }
56579
56580 if (isset($this->formatVars['elapsed'])) {
56581 $elapsed = time() - $this->startTime;
56582 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
56583 }
56584
56585 if (isset($this->formatVars['current'])) {
56586 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
56587 }
56588
56589 if (isset($this->formatVars['max'])) {
56590 $vars['max'] = $this->max;
56591 }
56592
56593 if (isset($this->formatVars['percent'])) {
56594 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
56595 }
56596
56597 return $vars;
56598 }
56599
56600
56601
56602
56603
56604
56605
56606
56607 private function humaneTime($secs)
56608 {
56609 $text = '';
56610 foreach ($this->timeFormats as $format) {
56611 if ($secs < $format[0]) {
56612 if (2 == \count($format)) {
56613 $text = $format[1];
56614 break;
56615 } else {
56616 $text = ceil($secs / $format[2]).' '.$format[1];
56617 break;
56618 }
56619 }
56620 }
56621
56622 return $text;
56623 }
56624
56625
56626
56627
56628
56629
56630
56631 private function overwrite(OutputInterface $output, $message)
56632 {
56633 $length = $this->strlen($message);
56634
56635
56636  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
56637 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
56638 }
56639
56640
56641  $output->write("\x0D");
56642 $output->write($message);
56643
56644 $this->lastMessagesLength = $this->strlen($message);
56645 }
56646
56647
56648
56649
56650 public function getName()
56651 {
56652 return 'progress';
56653 }
56654 }
56655 <?php
56656
56657
56658
56659
56660
56661
56662
56663
56664
56665
56666 namespace Symfony\Component\Console\Helper;
56667
56668 use Symfony\Component\Console\Exception\InvalidArgumentException;
56669 use Symfony\Component\Console\Exception\LogicException;
56670 use Symfony\Component\Console\Output\OutputInterface;
56671
56672
56673
56674
56675 class ProgressIndicator
56676 {
56677 private $output;
56678 private $startTime;
56679 private $format;
56680 private $message;
56681 private $indicatorValues;
56682 private $indicatorCurrent;
56683 private $indicatorChangeInterval;
56684 private $indicatorUpdateTime;
56685 private $started = false;
56686
56687 private static $formatters;
56688 private static $formats;
56689
56690
56691
56692
56693
56694
56695
56696 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
56697 {
56698 $this->output = $output;
56699
56700 if (null === $format) {
56701 $format = $this->determineBestFormat();
56702 }
56703
56704 if (null === $indicatorValues) {
56705 $indicatorValues = array('-', '\\', '|', '/');
56706 }
56707
56708 $indicatorValues = array_values($indicatorValues);
56709
56710 if (2 > \count($indicatorValues)) {
56711 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
56712 }
56713
56714 $this->format = self::getFormatDefinition($format);
56715 $this->indicatorChangeInterval = $indicatorChangeInterval;
56716 $this->indicatorValues = $indicatorValues;
56717 $this->startTime = time();
56718 }
56719
56720
56721
56722
56723
56724
56725 public function setMessage($message)
56726 {
56727 $this->message = $message;
56728
56729 $this->display();
56730 }
56731
56732
56733
56734
56735
56736
56737
56738
56739 public function getMessage()
56740 {
56741 return $this->message;
56742 }
56743
56744
56745
56746
56747
56748
56749
56750
56751 public function getStartTime()
56752 {
56753 return $this->startTime;
56754 }
56755
56756
56757
56758
56759
56760
56761
56762
56763 public function getCurrentValue()
56764 {
56765 return $this->indicatorValues[$this->indicatorCurrent % \count($this->indicatorValues)];
56766 }
56767
56768
56769
56770
56771
56772
56773 public function start($message)
56774 {
56775 if ($this->started) {
56776 throw new LogicException('Progress indicator already started.');
56777 }
56778
56779 $this->message = $message;
56780 $this->started = true;
56781 $this->startTime = time();
56782 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
56783 $this->indicatorCurrent = 0;
56784
56785 $this->display();
56786 }
56787
56788
56789
56790
56791 public function advance()
56792 {
56793 if (!$this->started) {
56794 throw new LogicException('Progress indicator has not yet been started.');
56795 }
56796
56797 if (!$this->output->isDecorated()) {
56798 return;
56799 }
56800
56801 $currentTime = $this->getCurrentTimeInMilliseconds();
56802
56803 if ($currentTime < $this->indicatorUpdateTime) {
56804 return;
56805 }
56806
56807 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
56808 ++$this->indicatorCurrent;
56809
56810 $this->display();
56811 }
56812
56813
56814
56815
56816
56817
56818 public function finish($message)
56819 {
56820 if (!$this->started) {
56821 throw new LogicException('Progress indicator has not yet been started.');
56822 }
56823
56824 $this->message = $message;
56825 $this->display();
56826 $this->output->writeln('');
56827 $this->started = false;
56828 }
56829
56830
56831
56832
56833
56834
56835
56836
56837 public static function getFormatDefinition($name)
56838 {
56839 if (!self::$formats) {
56840 self::$formats = self::initFormats();
56841 }
56842
56843 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
56844 }
56845
56846
56847
56848
56849
56850
56851
56852
56853
56854 public static function setPlaceholderFormatterDefinition($name, $callable)
56855 {
56856 if (!self::$formatters) {
56857 self::$formatters = self::initPlaceholderFormatters();
56858 }
56859
56860 self::$formatters[$name] = $callable;
56861 }
56862
56863
56864
56865
56866
56867
56868
56869
56870 public static function getPlaceholderFormatterDefinition($name)
56871 {
56872 if (!self::$formatters) {
56873 self::$formatters = self::initPlaceholderFormatters();
56874 }
56875
56876 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
56877 }
56878
56879 private function display()
56880 {
56881 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
56882 return;
56883 }
56884
56885 $self = $this;
56886
56887 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
56888 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
56889 return \call_user_func($formatter, $self);
56890 }
56891
56892 return $matches[0];
56893 }, $this->format));
56894 }
56895
56896 private function determineBestFormat()
56897 {
56898 switch ($this->output->getVerbosity()) {
56899
56900  case OutputInterface::VERBOSITY_VERBOSE:
56901 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
56902 case OutputInterface::VERBOSITY_VERY_VERBOSE:
56903 case OutputInterface::VERBOSITY_DEBUG:
56904 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
56905 default:
56906 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
56907 }
56908 }
56909
56910
56911
56912
56913
56914
56915 private function overwrite($message)
56916 {
56917 if ($this->output->isDecorated()) {
56918 $this->output->write("\x0D\x1B[2K");
56919 $this->output->write($message);
56920 } else {
56921 $this->output->writeln($message);
56922 }
56923 }
56924
56925 private function getCurrentTimeInMilliseconds()
56926 {
56927 return round(microtime(true) * 1000);
56928 }
56929
56930 private static function initPlaceholderFormatters()
56931 {
56932 return array(
56933 'indicator' => function (ProgressIndicator $indicator) {
56934 return $indicator->getCurrentValue();
56935 },
56936 'message' => function (ProgressIndicator $indicator) {
56937 return $indicator->getMessage();
56938 },
56939 'elapsed' => function (ProgressIndicator $indicator) {
56940 return Helper::formatTime(time() - $indicator->getStartTime());
56941 },
56942 'memory' => function () {
56943 return Helper::formatMemory(memory_get_usage(true));
56944 },
56945 );
56946 }
56947
56948 private static function initFormats()
56949 {
56950 return array(
56951 'normal' => ' %indicator% %message%',
56952 'normal_no_ansi' => ' %message%',
56953
56954 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
56955 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
56956
56957 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
56958 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
56959 );
56960 }
56961 }
56962 <?php
56963
56964
56965
56966
56967
56968
56969
56970
56971
56972
56973 namespace Symfony\Component\Console\Helper;
56974
56975 use Symfony\Component\Console\Exception\InvalidArgumentException;
56976 use Symfony\Component\Console\Exception\RuntimeException;
56977 use Symfony\Component\Console\Formatter\OutputFormatter;
56978 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
56979 use Symfony\Component\Console\Input\InputInterface;
56980 use Symfony\Component\Console\Output\ConsoleOutputInterface;
56981 use Symfony\Component\Console\Output\OutputInterface;
56982 use Symfony\Component\Console\Question\ChoiceQuestion;
56983 use Symfony\Component\Console\Question\Question;
56984
56985
56986
56987
56988
56989
56990 class QuestionHelper extends Helper
56991 {
56992 private $inputStream;
56993 private static $shell;
56994 private static $stty;
56995
56996
56997
56998
56999
57000
57001
57002
57003 public function ask(InputInterface $input, OutputInterface $output, Question $question)
57004 {
57005 if ($output instanceof ConsoleOutputInterface) {
57006 $output = $output->getErrorOutput();
57007 }
57008
57009 if (!$input->isInteractive()) {
57010 $default = $question->getDefault();
57011
57012 if (null !== $default && $question instanceof ChoiceQuestion) {
57013 $choices = $question->getChoices();
57014
57015 if (!$question->isMultiselect()) {
57016 return isset($choices[$default]) ? $choices[$default] : $default;
57017 }
57018
57019 $default = explode(',', $default);
57020 foreach ($default as $k => $v) {
57021 $v = trim($v);
57022 $default[$k] = isset($choices[$v]) ? $choices[$v] : $v;
57023 }
57024 }
57025
57026 return $default;
57027 }
57028
57029 if (!$question->getValidator()) {
57030 return $this->doAsk($output, $question);
57031 }
57032
57033 $that = $this;
57034
57035 $interviewer = function () use ($output, $question, $that) {
57036 return $that->doAsk($output, $question);
57037 };
57038
57039 return $this->validateAttempts($interviewer, $output, $question);
57040 }
57041
57042
57043
57044
57045
57046
57047
57048
57049
57050
57051 public function setInputStream($stream)
57052 {
57053 if (!\is_resource($stream)) {
57054 throw new InvalidArgumentException('Input stream must be a valid resource.');
57055 }
57056
57057 $this->inputStream = $stream;
57058 }
57059
57060
57061
57062
57063
57064
57065 public function getInputStream()
57066 {
57067 return $this->inputStream;
57068 }
57069
57070
57071
57072
57073 public function getName()
57074 {
57075 return 'question';
57076 }
57077
57078
57079
57080
57081
57082
57083
57084
57085
57086
57087 public function doAsk(OutputInterface $output, Question $question)
57088 {
57089 $this->writePrompt($output, $question);
57090
57091 $inputStream = $this->inputStream ?: STDIN;
57092 $autocomplete = $question->getAutocompleterValues();
57093
57094 if (null === $autocomplete || !$this->hasSttyAvailable()) {
57095 $ret = false;
57096 if ($question->isHidden()) {
57097 try {
57098 $ret = trim($this->getHiddenResponse($output, $inputStream));
57099 } catch (RuntimeException $e) {
57100 if (!$question->isHiddenFallback()) {
57101 throw $e;
57102 }
57103 }
57104 }
57105
57106 if (false === $ret) {
57107 $ret = fgets($inputStream, 4096);
57108 if (false === $ret) {
57109 throw new RuntimeException('Aborted');
57110 }
57111 $ret = trim($ret);
57112 }
57113 } else {
57114 $ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
57115 }
57116
57117 $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
57118
57119 if ($normalizer = $question->getNormalizer()) {
57120 return $normalizer($ret);
57121 }
57122
57123 return $ret;
57124 }
57125
57126
57127
57128
57129 protected function writePrompt(OutputInterface $output, Question $question)
57130 {
57131 $message = $question->getQuestion();
57132
57133 if ($question instanceof ChoiceQuestion) {
57134 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
57135
57136 $messages = (array) $question->getQuestion();
57137 foreach ($question->getChoices() as $key => $value) {
57138 $width = $maxWidth - $this->strlen($key);
57139 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
57140 }
57141
57142 $output->writeln($messages);
57143
57144 $message = $question->getPrompt();
57145 }
57146
57147 $output->write($message);
57148 }
57149
57150
57151
57152
57153 protected function writeError(OutputInterface $output, \Exception $error)
57154 {
57155 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
57156 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
57157 } else {
57158 $message = '<error>'.$error->getMessage().'</error>';
57159 }
57160
57161 $output->writeln($message);
57162 }
57163
57164
57165
57166
57167
57168
57169
57170
57171
57172
57173
57174 private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
57175 {
57176 $ret = '';
57177
57178 $i = 0;
57179 $ofs = -1;
57180 $matches = $autocomplete;
57181 $numMatches = \count($matches);
57182
57183 $sttyMode = shell_exec('stty -g');
57184
57185
57186  shell_exec('stty -icanon -echo');
57187
57188
57189  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
57190
57191
57192  while (!feof($inputStream)) {
57193 $c = fread($inputStream, 1);
57194
57195
57196  if ("\177" === $c) {
57197 if (0 === $numMatches && 0 !== $i) {
57198 --$i;
57199
57200  $output->write("\033[1D");
57201 }
57202
57203 if (0 === $i) {
57204 $ofs = -1;
57205 $matches = $autocomplete;
57206 $numMatches = \count($matches);
57207 } else {
57208 $numMatches = 0;
57209 }
57210
57211
57212  $ret = substr($ret, 0, $i);
57213 } elseif ("\033" === $c) {
57214
57215  $c .= fread($inputStream, 2);
57216
57217
57218  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
57219 if ('A' === $c[2] && -1 === $ofs) {
57220 $ofs = 0;
57221 }
57222
57223 if (0 === $numMatches) {
57224 continue;
57225 }
57226
57227 $ofs += ('A' === $c[2]) ? -1 : 1;
57228 $ofs = ($numMatches + $ofs) % $numMatches;
57229 }
57230 } elseif (\ord($c) < 32) {
57231 if ("\t" === $c || "\n" === $c) {
57232 if ($numMatches > 0 && -1 !== $ofs) {
57233 $ret = $matches[$ofs];
57234
57235  $output->write(substr($ret, $i));
57236 $i = \strlen($ret);
57237 }
57238
57239 if ("\n" === $c) {
57240 $output->write($c);
57241 break;
57242 }
57243
57244 $numMatches = 0;
57245 }
57246
57247 continue;
57248 } else {
57249 $output->write($c);
57250 $ret .= $c;
57251 ++$i;
57252
57253 $numMatches = 0;
57254 $ofs = 0;
57255
57256 foreach ($autocomplete as $value) {
57257
57258  if (0 === strpos($value, $ret)) {
57259 $matches[$numMatches++] = $value;
57260 }
57261 }
57262 }
57263
57264
57265  $output->write("\033[K");
57266
57267 if ($numMatches > 0 && -1 !== $ofs) {
57268
57269  $output->write("\0337");
57270
57271  $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
57272
57273  $output->write("\0338");
57274 }
57275 }
57276
57277
57278  shell_exec(sprintf('stty %s', $sttyMode));
57279
57280 return $ret;
57281 }
57282
57283
57284
57285
57286
57287
57288
57289
57290
57291
57292
57293 private function getHiddenResponse(OutputInterface $output, $inputStream)
57294 {
57295 if ('\\' === \DIRECTORY_SEPARATOR) {
57296 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
57297
57298
57299  if ('phar:' === substr(__FILE__, 0, 5)) {
57300 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
57301 copy($exe, $tmpExe);
57302 $exe = $tmpExe;
57303 }
57304
57305 $value = rtrim(shell_exec($exe));
57306 $output->writeln('');
57307
57308 if (isset($tmpExe)) {
57309 unlink($tmpExe);
57310 }
57311
57312 return $value;
57313 }
57314
57315 if ($this->hasSttyAvailable()) {
57316 $sttyMode = shell_exec('stty -g');
57317
57318 shell_exec('stty -echo');
57319 $value = fgets($inputStream, 4096);
57320 shell_exec(sprintf('stty %s', $sttyMode));
57321
57322 if (false === $value) {
57323 throw new RuntimeException('Aborted');
57324 }
57325
57326 $value = trim($value);
57327 $output->writeln('');
57328
57329 return $value;
57330 }
57331
57332 if (false !== $shell = $this->getShell()) {
57333 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
57334 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
57335 $value = rtrim(shell_exec($command));
57336 $output->writeln('');
57337
57338 return $value;
57339 }
57340
57341 throw new RuntimeException('Unable to hide the response.');
57342 }
57343
57344
57345
57346
57347
57348
57349
57350
57351
57352
57353
57354
57355 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
57356 {
57357 $error = null;
57358 $attempts = $question->getMaxAttempts();
57359 while (null === $attempts || $attempts--) {
57360 if (null !== $error) {
57361 $this->writeError($output, $error);
57362 }
57363
57364 try {
57365 return \call_user_func($question->getValidator(), $interviewer());
57366 } catch (RuntimeException $e) {
57367 throw $e;
57368 } catch (\Exception $error) {
57369 }
57370 }
57371
57372 throw $error;
57373 }
57374
57375
57376
57377
57378
57379
57380 private function getShell()
57381 {
57382 if (null !== self::$shell) {
57383 return self::$shell;
57384 }
57385
57386 self::$shell = false;
57387
57388 if (file_exists('/usr/bin/env')) {
57389
57390  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
57391 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
57392 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
57393 self::$shell = $sh;
57394 break;
57395 }
57396 }
57397 }
57398
57399 return self::$shell;
57400 }
57401
57402
57403
57404
57405
57406
57407 private function hasSttyAvailable()
57408 {
57409 if (null !== self::$stty) {
57410 return self::$stty;
57411 }
57412
57413 exec('stty 2>&1', $output, $exitcode);
57414
57415 return self::$stty = 0 === $exitcode;
57416 }
57417 }
57418 <?php
57419
57420
57421
57422
57423
57424
57425
57426
57427
57428
57429 namespace Symfony\Component\Console\Helper;
57430
57431 use Symfony\Component\Console\Exception\LogicException;
57432 use Symfony\Component\Console\Formatter\OutputFormatter;
57433 use Symfony\Component\Console\Input\InputInterface;
57434 use Symfony\Component\Console\Output\OutputInterface;
57435 use Symfony\Component\Console\Question\ChoiceQuestion;
57436 use Symfony\Component\Console\Question\ConfirmationQuestion;
57437 use Symfony\Component\Console\Question\Question;
57438 use Symfony\Component\Console\Style\SymfonyStyle;
57439
57440
57441
57442
57443
57444
57445 class SymfonyQuestionHelper extends QuestionHelper
57446 {
57447
57448
57449
57450 public function ask(InputInterface $input, OutputInterface $output, Question $question)
57451 {
57452 $validator = $question->getValidator();
57453 $question->setValidator(function ($value) use ($validator) {
57454 if (null !== $validator) {
57455 $value = $validator($value);
57456 } else {
57457
57458  if (!\is_array($value) && !\is_bool($value) && 0 === \strlen($value)) {
57459 throw new LogicException('A value is required.');
57460 }
57461 }
57462
57463 return $value;
57464 });
57465
57466 return parent::ask($input, $output, $question);
57467 }
57468
57469
57470
57471
57472 protected function writePrompt(OutputInterface $output, Question $question)
57473 {
57474 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
57475 $default = $question->getDefault();
57476
57477 switch (true) {
57478 case null === $default:
57479 $text = sprintf(' <info>%s</info>:', $text);
57480
57481 break;
57482
57483 case $question instanceof ConfirmationQuestion:
57484 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
57485
57486 break;
57487
57488 case $question instanceof ChoiceQuestion && $question->isMultiselect():
57489 $choices = $question->getChoices();
57490 $default = explode(',', $default);
57491
57492 foreach ($default as $key => $value) {
57493 $default[$key] = $choices[trim($value)];
57494 }
57495
57496 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
57497
57498 break;
57499
57500 case $question instanceof ChoiceQuestion:
57501 $choices = $question->getChoices();
57502 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default));
57503
57504 break;
57505
57506 default:
57507 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
57508 }
57509
57510 $output->writeln($text);
57511
57512 if ($question instanceof ChoiceQuestion) {
57513 $width = max(array_map('strlen', array_keys($question->getChoices())));
57514
57515 foreach ($question->getChoices() as $key => $value) {
57516 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
57517 }
57518 }
57519
57520 $output->write(' > ');
57521 }
57522
57523
57524
57525
57526 protected function writeError(OutputInterface $output, \Exception $error)
57527 {
57528 if ($output instanceof SymfonyStyle) {
57529 $output->newLine();
57530 $output->error($error->getMessage());
57531
57532 return;
57533 }
57534
57535 parent::writeError($output, $error);
57536 }
57537 }
57538 <?php
57539
57540
57541
57542
57543
57544
57545
57546
57547
57548
57549 namespace Symfony\Component\Console\Helper;
57550
57551 use Symfony\Component\Console\Exception\InvalidArgumentException;
57552 use Symfony\Component\Console\Output\OutputInterface;
57553
57554
57555
57556
57557
57558
57559
57560
57561
57562 class Table
57563 {
57564
57565
57566
57567 private $headers = array();
57568
57569
57570
57571
57572 private $rows = array();
57573
57574
57575
57576
57577 private $columnWidths = array();
57578
57579
57580
57581
57582
57583
57584 private $numberOfColumns;
57585
57586
57587
57588
57589 private $output;
57590
57591
57592
57593
57594 private $style;
57595
57596
57597
57598
57599 private $columnStyles = array();
57600
57601 private static $styles;
57602
57603 public function __construct(OutputInterface $output)
57604 {
57605 $this->output = $output;
57606
57607 if (!self::$styles) {
57608 self::$styles = self::initStyles();
57609 }
57610
57611 $this->setStyle('default');
57612 }
57613
57614
57615
57616
57617
57618
57619
57620 public static function setStyleDefinition($name, TableStyle $style)
57621 {
57622 if (!self::$styles) {
57623 self::$styles = self::initStyles();
57624 }
57625
57626 self::$styles[$name] = $style;
57627 }
57628
57629
57630
57631
57632
57633
57634
57635
57636 public static function getStyleDefinition($name)
57637 {
57638 if (!self::$styles) {
57639 self::$styles = self::initStyles();
57640 }
57641
57642 if (isset(self::$styles[$name])) {
57643 return self::$styles[$name];
57644 }
57645
57646 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
57647 }
57648
57649
57650
57651
57652
57653
57654
57655
57656 public function setStyle($name)
57657 {
57658 $this->style = $this->resolveStyle($name);
57659
57660 return $this;
57661 }
57662
57663
57664
57665
57666
57667
57668 public function getStyle()
57669 {
57670 return $this->style;
57671 }
57672
57673
57674
57675
57676
57677
57678
57679
57680
57681 public function setColumnStyle($columnIndex, $name)
57682 {
57683 $columnIndex = (int) $columnIndex;
57684
57685 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
57686
57687 return $this;
57688 }
57689
57690
57691
57692
57693
57694
57695
57696
57697
57698
57699 public function getColumnStyle($columnIndex)
57700 {
57701 if (isset($this->columnStyles[$columnIndex])) {
57702 return $this->columnStyles[$columnIndex];
57703 }
57704
57705 return $this->getStyle();
57706 }
57707
57708 public function setHeaders(array $headers)
57709 {
57710 $headers = array_values($headers);
57711 if (!empty($headers) && !\is_array($headers[0])) {
57712 $headers = array($headers);
57713 }
57714
57715 $this->headers = $headers;
57716
57717 return $this;
57718 }
57719
57720 public function setRows(array $rows)
57721 {
57722 $this->rows = array();
57723
57724 return $this->addRows($rows);
57725 }
57726
57727 public function addRows(array $rows)
57728 {
57729 foreach ($rows as $row) {
57730 $this->addRow($row);
57731 }
57732
57733 return $this;
57734 }
57735
57736 public function addRow($row)
57737 {
57738 if ($row instanceof TableSeparator) {
57739 $this->rows[] = $row;
57740
57741 return $this;
57742 }
57743
57744 if (!\is_array($row)) {
57745 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
57746 }
57747
57748 $this->rows[] = array_values($row);
57749
57750 return $this;
57751 }
57752
57753 public function setRow($column, array $row)
57754 {
57755 $this->rows[$column] = $row;
57756
57757 return $this;
57758 }
57759
57760
57761
57762
57763
57764
57765
57766
57767
57768
57769
57770
57771
57772
57773 public function render()
57774 {
57775 $this->calculateNumberOfColumns();
57776 $rows = $this->buildTableRows($this->rows);
57777 $headers = $this->buildTableRows($this->headers);
57778
57779 $this->calculateColumnsWidth(array_merge($headers, $rows));
57780
57781 $this->renderRowSeparator();
57782 if (!empty($headers)) {
57783 foreach ($headers as $header) {
57784 $this->renderRow($header, $this->style->getCellHeaderFormat());
57785 $this->renderRowSeparator();
57786 }
57787 }
57788 foreach ($rows as $row) {
57789 if ($row instanceof TableSeparator) {
57790 $this->renderRowSeparator();
57791 } else {
57792 $this->renderRow($row, $this->style->getCellRowFormat());
57793 }
57794 }
57795 if (!empty($rows)) {
57796 $this->renderRowSeparator();
57797 }
57798
57799 $this->cleanup();
57800 }
57801
57802
57803
57804
57805
57806
57807
57808
57809 private function renderRowSeparator()
57810 {
57811 if (0 === $count = $this->numberOfColumns) {
57812 return;
57813 }
57814
57815 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
57816 return;
57817 }
57818
57819 $markup = $this->style->getCrossingChar();
57820 for ($column = 0; $column < $count; ++$column) {
57821 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
57822 }
57823
57824 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
57825 }
57826
57827
57828
57829
57830 private function renderColumnSeparator()
57831 {
57832 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
57833 }
57834
57835
57836
57837
57838
57839
57840
57841
57842
57843
57844
57845 private function renderRow(array $row, $cellFormat)
57846 {
57847 if (empty($row)) {
57848 return;
57849 }
57850
57851 $rowContent = $this->renderColumnSeparator();
57852 foreach ($this->getRowColumns($row) as $column) {
57853 $rowContent .= $this->renderCell($row, $column, $cellFormat);
57854 $rowContent .= $this->renderColumnSeparator();
57855 }
57856 $this->output->writeln($rowContent);
57857 }
57858
57859
57860
57861
57862
57863
57864
57865
57866 private function renderCell(array $row, $column, $cellFormat)
57867 {
57868 $cell = isset($row[$column]) ? $row[$column] : '';
57869 $width = $this->columnWidths[$column];
57870 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
57871
57872  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
57873 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
57874 }
57875 }
57876
57877
57878  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
57879 $width += \strlen($cell) - mb_strwidth($cell, $encoding);
57880 }
57881
57882 $style = $this->getColumnStyle($column);
57883
57884 if ($cell instanceof TableSeparator) {
57885 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
57886 }
57887
57888 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
57889 $content = sprintf($style->getCellRowContentFormat(), $cell);
57890
57891 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
57892 }
57893
57894
57895
57896
57897 private function calculateNumberOfColumns()
57898 {
57899 if (null !== $this->numberOfColumns) {
57900 return;
57901 }
57902
57903 $columns = array(0);
57904 foreach (array_merge($this->headers, $this->rows) as $row) {
57905 if ($row instanceof TableSeparator) {
57906 continue;
57907 }
57908
57909 $columns[] = $this->getNumberOfColumns($row);
57910 }
57911
57912 $this->numberOfColumns = max($columns);
57913 }
57914
57915 private function buildTableRows($rows)
57916 {
57917 $unmergedRows = array();
57918 for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
57919 $rows = $this->fillNextRows($rows, $rowKey);
57920
57921
57922  foreach ($rows[$rowKey] as $column => $cell) {
57923 if (!strstr($cell, "\n")) {
57924 continue;
57925 }
57926 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
57927 foreach ($lines as $lineKey => $line) {
57928 if ($cell instanceof TableCell) {
57929 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
57930 }
57931 if (0 === $lineKey) {
57932 $rows[$rowKey][$column] = $line;
57933 } else {
57934 $unmergedRows[$rowKey][$lineKey][$column] = $line;
57935 }
57936 }
57937 }
57938 }
57939
57940 $tableRows = array();
57941 foreach ($rows as $rowKey => $row) {
57942 $tableRows[] = $this->fillCells($row);
57943 if (isset($unmergedRows[$rowKey])) {
57944 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
57945 }
57946 }
57947
57948 return $tableRows;
57949 }
57950
57951
57952
57953
57954
57955
57956
57957
57958
57959 private function fillNextRows(array $rows, $line)
57960 {
57961 $unmergedRows = array();
57962 foreach ($rows[$line] as $column => $cell) {
57963 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
57964 $nbLines = $cell->getRowspan() - 1;
57965 $lines = array($cell);
57966 if (strstr($cell, "\n")) {
57967 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
57968 $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
57969
57970 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
57971 unset($lines[0]);
57972 }
57973
57974
57975  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
57976 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
57977 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
57978 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
57979 if ($nbLines === $unmergedRowKey - $line) {
57980 break;
57981 }
57982 }
57983 }
57984 }
57985
57986 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
57987
57988  if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
57989 foreach ($unmergedRow as $cellKey => $cell) {
57990
57991  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
57992 }
57993 } else {
57994 $row = $this->copyRow($rows, $unmergedRowKey - 1);
57995 foreach ($unmergedRow as $column => $cell) {
57996 if (!empty($cell)) {
57997 $row[$column] = $unmergedRow[$column];
57998 }
57999 }
58000 array_splice($rows, $unmergedRowKey, 0, array($row));
58001 }
58002 }
58003
58004 return $rows;
58005 }
58006
58007
58008
58009
58010
58011
58012 private function fillCells($row)
58013 {
58014 $newRow = array();
58015 foreach ($row as $column => $cell) {
58016 $newRow[] = $cell;
58017 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
58018 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
58019
58020  $newRow[] = '';
58021 }
58022 }
58023 }
58024
58025 return $newRow ?: $row;
58026 }
58027
58028
58029
58030
58031
58032
58033
58034 private function copyRow(array $rows, $line)
58035 {
58036 $row = $rows[$line];
58037 foreach ($row as $cellKey => $cellValue) {
58038 $row[$cellKey] = '';
58039 if ($cellValue instanceof TableCell) {
58040 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
58041 }
58042 }
58043
58044 return $row;
58045 }
58046
58047
58048
58049
58050
58051
58052 private function getNumberOfColumns(array $row)
58053 {
58054 $columns = \count($row);
58055 foreach ($row as $column) {
58056 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
58057 }
58058
58059 return $columns;
58060 }
58061
58062
58063
58064
58065
58066
58067 private function getRowColumns(array $row)
58068 {
58069 $columns = range(0, $this->numberOfColumns - 1);
58070 foreach ($row as $cellKey => $cell) {
58071 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
58072
58073  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
58074 }
58075 }
58076
58077 return $columns;
58078 }
58079
58080
58081
58082
58083
58084
58085 private function calculateColumnsWidth($rows)
58086 {
58087 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
58088 $lengths = array();
58089 foreach ($rows as $row) {
58090 if ($row instanceof TableSeparator) {
58091 continue;
58092 }
58093
58094 foreach ($row as $i => $cell) {
58095 if ($cell instanceof TableCell) {
58096 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
58097 $textLength = Helper::strlen($textContent);
58098 if ($textLength > 0) {
58099 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
58100 foreach ($contentColumns as $position => $content) {
58101 $row[$i + $position] = $content;
58102 }
58103 }
58104 }
58105 }
58106
58107 $lengths[] = $this->getCellWidth($row, $column);
58108 }
58109
58110 $this->columnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2;
58111 }
58112 }
58113
58114
58115
58116
58117
58118
58119 private function getColumnSeparatorWidth()
58120 {
58121 return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
58122 }
58123
58124
58125
58126
58127
58128
58129
58130
58131
58132 private function getCellWidth(array $row, $column)
58133 {
58134 if (isset($row[$column])) {
58135 $cell = $row[$column];
58136 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
58137
58138 return $cellWidth;
58139 }
58140
58141 return 0;
58142 }
58143
58144
58145
58146
58147 private function cleanup()
58148 {
58149 $this->columnWidths = array();
58150 $this->numberOfColumns = null;
58151 }
58152
58153 private static function initStyles()
58154 {
58155 $borderless = new TableStyle();
58156 $borderless
58157 ->setHorizontalBorderChar('=')
58158 ->setVerticalBorderChar(' ')
58159 ->setCrossingChar(' ')
58160 ;
58161
58162 $compact = new TableStyle();
58163 $compact
58164 ->setHorizontalBorderChar('')
58165 ->setVerticalBorderChar(' ')
58166 ->setCrossingChar('')
58167 ->setCellRowContentFormat('%s')
58168 ;
58169
58170 $styleGuide = new TableStyle();
58171 $styleGuide
58172 ->setHorizontalBorderChar('-')
58173 ->setVerticalBorderChar(' ')
58174 ->setCrossingChar(' ')
58175 ->setCellHeaderFormat('%s')
58176 ;
58177
58178 return array(
58179 'default' => new TableStyle(),
58180 'borderless' => $borderless,
58181 'compact' => $compact,
58182 'symfony-style-guide' => $styleGuide,
58183 );
58184 }
58185
58186 private function resolveStyle($name)
58187 {
58188 if ($name instanceof TableStyle) {
58189 return $name;
58190 }
58191
58192 if (isset(self::$styles[$name])) {
58193 return self::$styles[$name];
58194 }
58195
58196 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
58197 }
58198 }
58199 <?php
58200
58201
58202
58203
58204
58205
58206
58207
58208
58209
58210 namespace Symfony\Component\Console\Helper;
58211
58212 use Symfony\Component\Console\Exception\InvalidArgumentException;
58213
58214
58215
58216
58217 class TableCell
58218 {
58219 private $value;
58220 private $options = array(
58221 'rowspan' => 1,
58222 'colspan' => 1,
58223 );
58224
58225
58226
58227
58228
58229 public function __construct($value = '', array $options = array())
58230 {
58231 if (is_numeric($value) && !\is_string($value)) {
58232 $value = (string) $value;
58233 }
58234
58235 $this->value = $value;
58236
58237
58238  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
58239 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
58240 }
58241
58242 $this->options = array_merge($this->options, $options);
58243 }
58244
58245
58246
58247
58248
58249
58250 public function __toString()
58251 {
58252 return $this->value;
58253 }
58254
58255
58256
58257
58258
58259
58260 public function getColspan()
58261 {
58262 return (int) $this->options['colspan'];
58263 }
58264
58265
58266
58267
58268
58269
58270 public function getRowspan()
58271 {
58272 return (int) $this->options['rowspan'];
58273 }
58274 }
58275 <?php
58276
58277
58278
58279
58280
58281
58282
58283
58284
58285
58286 namespace Symfony\Component\Console\Helper;
58287
58288 use Symfony\Component\Console\Exception\InvalidArgumentException;
58289 use Symfony\Component\Console\Output\NullOutput;
58290 use Symfony\Component\Console\Output\OutputInterface;
58291
58292
58293
58294
58295
58296
58297
58298
58299
58300
58301 class TableHelper extends Helper
58302 {
58303 const LAYOUT_DEFAULT = 0;
58304 const LAYOUT_BORDERLESS = 1;
58305 const LAYOUT_COMPACT = 2;
58306
58307 private $table;
58308
58309 public function __construct($triggerDeprecationError = true)
58310 {
58311 if ($triggerDeprecationError) {
58312 @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);
58313 }
58314
58315 $this->table = new Table(new NullOutput());
58316 }
58317
58318
58319
58320
58321
58322
58323
58324
58325
58326
58327 public function setLayout($layout)
58328 {
58329 switch ($layout) {
58330 case self::LAYOUT_BORDERLESS:
58331 $this->table->setStyle('borderless');
58332 break;
58333
58334 case self::LAYOUT_COMPACT:
58335 $this->table->setStyle('compact');
58336 break;
58337
58338 case self::LAYOUT_DEFAULT:
58339 $this->table->setStyle('default');
58340 break;
58341
58342 default:
58343 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
58344 }
58345
58346 return $this;
58347 }
58348
58349 public function setHeaders(array $headers)
58350 {
58351 $this->table->setHeaders($headers);
58352
58353 return $this;
58354 }
58355
58356 public function setRows(array $rows)
58357 {
58358 $this->table->setRows($rows);
58359
58360 return $this;
58361 }
58362
58363 public function addRows(array $rows)
58364 {
58365 $this->table->addRows($rows);
58366
58367 return $this;
58368 }
58369
58370 public function addRow(array $row)
58371 {
58372 $this->table->addRow($row);
58373
58374 return $this;
58375 }
58376
58377 public function setRow($column, array $row)
58378 {
58379 $this->table->setRow($column, $row);
58380
58381 return $this;
58382 }
58383
58384
58385
58386
58387
58388
58389
58390
58391 public function setPaddingChar($paddingChar)
58392 {
58393 $this->table->getStyle()->setPaddingChar($paddingChar);
58394
58395 return $this;
58396 }
58397
58398
58399
58400
58401
58402
58403
58404
58405 public function setHorizontalBorderChar($horizontalBorderChar)
58406 {
58407 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
58408
58409 return $this;
58410 }
58411
58412
58413
58414
58415
58416
58417
58418
58419 public function setVerticalBorderChar($verticalBorderChar)
58420 {
58421 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
58422
58423 return $this;
58424 }
58425
58426
58427
58428
58429
58430
58431
58432
58433 public function setCrossingChar($crossingChar)
58434 {
58435 $this->table->getStyle()->setCrossingChar($crossingChar);
58436
58437 return $this;
58438 }
58439
58440
58441
58442
58443
58444
58445
58446
58447 public function setCellHeaderFormat($cellHeaderFormat)
58448 {
58449 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
58450
58451 return $this;
58452 }
58453
58454
58455
58456
58457
58458
58459
58460
58461 public function setCellRowFormat($cellRowFormat)
58462 {
58463 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
58464
58465 return $this;
58466 }
58467
58468
58469
58470
58471
58472
58473
58474
58475 public function setCellRowContentFormat($cellRowContentFormat)
58476 {
58477 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
58478
58479 return $this;
58480 }
58481
58482
58483
58484
58485
58486
58487
58488
58489 public function setBorderFormat($borderFormat)
58490 {
58491 $this->table->getStyle()->setBorderFormat($borderFormat);
58492
58493 return $this;
58494 }
58495
58496
58497
58498
58499
58500
58501
58502
58503 public function setPadType($padType)
58504 {
58505 $this->table->getStyle()->setPadType($padType);
58506
58507 return $this;
58508 }
58509
58510
58511
58512
58513
58514
58515
58516
58517
58518
58519
58520
58521
58522 public function render(OutputInterface $output)
58523 {
58524 $p = new \ReflectionProperty($this->table, 'output');
58525 $p->setAccessible(true);
58526 $p->setValue($this->table, $output);
58527
58528 $this->table->render();
58529 }
58530
58531
58532
58533
58534 public function getName()
58535 {
58536 return 'table';
58537 }
58538 }
58539 <?php
58540
58541
58542
58543
58544
58545
58546
58547
58548
58549
58550 namespace Symfony\Component\Console\Helper;
58551
58552
58553
58554
58555
58556
58557 class TableSeparator extends TableCell
58558 {
58559 public function __construct(array $options = array())
58560 {
58561 parent::__construct('', $options);
58562 }
58563 }
58564 <?php
58565
58566
58567
58568
58569
58570
58571
58572
58573
58574
58575 namespace Symfony\Component\Console\Helper;
58576
58577 use Symfony\Component\Console\Exception\InvalidArgumentException;
58578 use Symfony\Component\Console\Exception\LogicException;
58579
58580
58581
58582
58583
58584
58585
58586 class TableStyle
58587 {
58588 private $paddingChar = ' ';
58589 private $horizontalBorderChar = '-';
58590 private $verticalBorderChar = '|';
58591 private $crossingChar = '+';
58592 private $cellHeaderFormat = '<info>%s</info>';
58593 private $cellRowFormat = '%s';
58594 private $cellRowContentFormat = ' %s ';
58595 private $borderFormat = '%s';
58596 private $padType = STR_PAD_RIGHT;
58597
58598
58599
58600
58601
58602
58603
58604
58605 public function setPaddingChar($paddingChar)
58606 {
58607 if (!$paddingChar) {
58608 throw new LogicException('The padding char must not be empty');
58609 }
58610
58611 $this->paddingChar = $paddingChar;
58612
58613 return $this;
58614 }
58615
58616
58617
58618
58619
58620
58621 public function getPaddingChar()
58622 {
58623 return $this->paddingChar;
58624 }
58625
58626
58627
58628
58629
58630
58631
58632
58633 public function setHorizontalBorderChar($horizontalBorderChar)
58634 {
58635 $this->horizontalBorderChar = $horizontalBorderChar;
58636
58637 return $this;
58638 }
58639
58640
58641
58642
58643
58644
58645 public function getHorizontalBorderChar()
58646 {
58647 return $this->horizontalBorderChar;
58648 }
58649
58650
58651
58652
58653
58654
58655
58656
58657 public function setVerticalBorderChar($verticalBorderChar)
58658 {
58659 $this->verticalBorderChar = $verticalBorderChar;
58660
58661 return $this;
58662 }
58663
58664
58665
58666
58667
58668
58669 public function getVerticalBorderChar()
58670 {
58671 return $this->verticalBorderChar;
58672 }
58673
58674
58675
58676
58677
58678
58679
58680
58681 public function setCrossingChar($crossingChar)
58682 {
58683 $this->crossingChar = $crossingChar;
58684
58685 return $this;
58686 }
58687
58688
58689
58690
58691
58692
58693 public function getCrossingChar()
58694 {
58695 return $this->crossingChar;
58696 }
58697
58698
58699
58700
58701
58702
58703
58704
58705 public function setCellHeaderFormat($cellHeaderFormat)
58706 {
58707 $this->cellHeaderFormat = $cellHeaderFormat;
58708
58709 return $this;
58710 }
58711
58712
58713
58714
58715
58716
58717 public function getCellHeaderFormat()
58718 {
58719 return $this->cellHeaderFormat;
58720 }
58721
58722
58723
58724
58725
58726
58727
58728
58729 public function setCellRowFormat($cellRowFormat)
58730 {
58731 $this->cellRowFormat = $cellRowFormat;
58732
58733 return $this;
58734 }
58735
58736
58737
58738
58739
58740
58741 public function getCellRowFormat()
58742 {
58743 return $this->cellRowFormat;
58744 }
58745
58746
58747
58748
58749
58750
58751
58752
58753 public function setCellRowContentFormat($cellRowContentFormat)
58754 {
58755 $this->cellRowContentFormat = $cellRowContentFormat;
58756
58757 return $this;
58758 }
58759
58760
58761
58762
58763
58764
58765 public function getCellRowContentFormat()
58766 {
58767 return $this->cellRowContentFormat;
58768 }
58769
58770
58771
58772
58773
58774
58775
58776
58777 public function setBorderFormat($borderFormat)
58778 {
58779 $this->borderFormat = $borderFormat;
58780
58781 return $this;
58782 }
58783
58784
58785
58786
58787
58788
58789 public function getBorderFormat()
58790 {
58791 return $this->borderFormat;
58792 }
58793
58794
58795
58796
58797
58798
58799
58800
58801 public function setPadType($padType)
58802 {
58803 if (!\in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
58804 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
58805 }
58806
58807 $this->padType = $padType;
58808
58809 return $this;
58810 }
58811
58812
58813
58814
58815
58816
58817 public function getPadType()
58818 {
58819 return $this->padType;
58820 }
58821 }
58822 <?php
58823
58824
58825
58826
58827
58828
58829
58830
58831
58832
58833 namespace Symfony\Component\Console\Input;
58834
58835 use Symfony\Component\Console\Exception\RuntimeException;
58836
58837
58838
58839
58840
58841
58842
58843
58844
58845
58846
58847
58848
58849
58850
58851
58852
58853
58854
58855
58856
58857
58858
58859
58860
58861
58862 class ArgvInput extends Input
58863 {
58864 private $tokens;
58865 private $parsed;
58866
58867
58868
58869
58870
58871 public function __construct(array $argv = null, InputDefinition $definition = null)
58872 {
58873 if (null === $argv) {
58874 $argv = $_SERVER['argv'];
58875 }
58876
58877
58878  array_shift($argv);
58879
58880 $this->tokens = $argv;
58881
58882 parent::__construct($definition);
58883 }
58884
58885 protected function setTokens(array $tokens)
58886 {
58887 $this->tokens = $tokens;
58888 }
58889
58890
58891
58892
58893 protected function parse()
58894 {
58895 $parseOptions = true;
58896 $this->parsed = $this->tokens;
58897 while (null !== $token = array_shift($this->parsed)) {
58898 if ($parseOptions && '' == $token) {
58899 $this->parseArgument($token);
58900 } elseif ($parseOptions && '--' == $token) {
58901 $parseOptions = false;
58902 } elseif ($parseOptions && 0 === strpos($token, '--')) {
58903 $this->parseLongOption($token);
58904 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
58905 $this->parseShortOption($token);
58906 } else {
58907 $this->parseArgument($token);
58908 }
58909 }
58910 }
58911
58912
58913
58914
58915
58916
58917 private function parseShortOption($token)
58918 {
58919 $name = substr($token, 1);
58920
58921 if (\strlen($name) > 1) {
58922 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
58923
58924  $this->addShortOption($name[0], substr($name, 1));
58925 } else {
58926 $this->parseShortOptionSet($name);
58927 }
58928 } else {
58929 $this->addShortOption($name, null);
58930 }
58931 }
58932
58933
58934
58935
58936
58937
58938
58939
58940 private function parseShortOptionSet($name)
58941 {
58942 $len = \strlen($name);
58943 for ($i = 0; $i < $len; ++$i) {
58944 if (!$this->definition->hasShortcut($name[$i])) {
58945 $encoding = mb_detect_encoding($name, null, true);
58946 throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
58947 }
58948
58949 $option = $this->definition->getOptionForShortcut($name[$i]);
58950 if ($option->acceptValue()) {
58951 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
58952
58953 break;
58954 } else {
58955 $this->addLongOption($option->getName(), null);
58956 }
58957 }
58958 }
58959
58960
58961
58962
58963
58964
58965 private function parseLongOption($token)
58966 {
58967 $name = substr($token, 2);
58968
58969 if (false !== $pos = strpos($name, '=')) {
58970 if (0 === \strlen($value = substr($name, $pos + 1))) {
58971 array_unshift($this->parsed, null);
58972 }
58973 $this->addLongOption(substr($name, 0, $pos), $value);
58974 } else {
58975 $this->addLongOption($name, null);
58976 }
58977 }
58978
58979
58980
58981
58982
58983
58984
58985
58986 private function parseArgument($token)
58987 {
58988 $c = \count($this->arguments);
58989
58990
58991  if ($this->definition->hasArgument($c)) {
58992 $arg = $this->definition->getArgument($c);
58993 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
58994
58995
58996  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
58997 $arg = $this->definition->getArgument($c - 1);
58998 $this->arguments[$arg->getName()][] = $token;
58999
59000
59001  } else {
59002 $all = $this->definition->getArguments();
59003 if (\count($all)) {
59004 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
59005 }
59006
59007 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
59008 }
59009 }
59010
59011
59012
59013
59014
59015
59016
59017
59018
59019 private function addShortOption($shortcut, $value)
59020 {
59021 if (!$this->definition->hasShortcut($shortcut)) {
59022 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
59023 }
59024
59025 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
59026 }
59027
59028
59029
59030
59031
59032
59033
59034
59035
59036 private function addLongOption($name, $value)
59037 {
59038 if (!$this->definition->hasOption($name)) {
59039 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
59040 }
59041
59042 $option = $this->definition->getOption($name);
59043
59044
59045  if (!isset($value[0])) {
59046 $value = null;
59047 }
59048
59049 if (null !== $value && !$option->acceptValue()) {
59050 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
59051 }
59052
59053 if (null === $value && $option->acceptValue() && \count($this->parsed)) {
59054
59055  
59056  $next = array_shift($this->parsed);
59057 if (isset($next[0]) && '-' !== $next[0]) {
59058 $value = $next;
59059 } elseif (empty($next)) {
59060 $value = null;
59061 } else {
59062 array_unshift($this->parsed, $next);
59063 }
59064 }
59065
59066 if (null === $value) {
59067 if ($option->isValueRequired()) {
59068 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
59069 }
59070
59071 if (!$option->isArray()) {
59072 $value = $option->isValueOptional() ? $option->getDefault() : true;
59073 }
59074 }
59075
59076 if ($option->isArray()) {
59077 $this->options[$name][] = $value;
59078 } else {
59079 $this->options[$name] = $value;
59080 }
59081 }
59082
59083
59084
59085
59086 public function getFirstArgument()
59087 {
59088 foreach ($this->tokens as $token) {
59089 if ($token && '-' === $token[0]) {
59090 continue;
59091 }
59092
59093 return $token;
59094 }
59095 }
59096
59097
59098
59099
59100 public function hasParameterOption($values)
59101 {
59102 $values = (array) $values;
59103
59104 foreach ($this->tokens as $token) {
59105 foreach ($values as $value) {
59106
59107  
59108  
59109  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
59110 if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
59111 return true;
59112 }
59113 }
59114 }
59115
59116 return false;
59117 }
59118
59119
59120
59121
59122 public function getParameterOption($values, $default = false)
59123 {
59124 $values = (array) $values;
59125 $tokens = $this->tokens;
59126
59127 while (0 < \count($tokens)) {
59128 $token = array_shift($tokens);
59129
59130 foreach ($values as $value) {
59131 if ($token === $value) {
59132 return array_shift($tokens);
59133 }
59134
59135  
59136  
59137  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
59138 if ('' !== $leading && 0 === strpos($token, $leading)) {
59139 return substr($token, \strlen($leading));
59140 }
59141 }
59142 }
59143
59144 return $default;
59145 }
59146
59147
59148
59149
59150
59151
59152 public function __toString()
59153 {
59154 $self = $this;
59155 $tokens = array_map(function ($token) use ($self) {
59156 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
59157 return $match[1].$self->escapeToken($match[2]);
59158 }
59159
59160 if ($token && '-' !== $token[0]) {
59161 return $self->escapeToken($token);
59162 }
59163
59164 return $token;
59165 }, $this->tokens);
59166
59167 return implode(' ', $tokens);
59168 }
59169 }
59170 <?php
59171
59172
59173
59174
59175
59176
59177
59178
59179
59180
59181 namespace Symfony\Component\Console\Input;
59182
59183 use Symfony\Component\Console\Exception\InvalidArgumentException;
59184 use Symfony\Component\Console\Exception\InvalidOptionException;
59185
59186
59187
59188
59189
59190
59191
59192
59193
59194
59195 class ArrayInput extends Input
59196 {
59197 private $parameters;
59198
59199 public function __construct(array $parameters, InputDefinition $definition = null)
59200 {
59201 $this->parameters = $parameters;
59202
59203 parent::__construct($definition);
59204 }
59205
59206
59207
59208
59209 public function getFirstArgument()
59210 {
59211 foreach ($this->parameters as $key => $value) {
59212 if ($key && '-' === $key[0]) {
59213 continue;
59214 }
59215
59216 return $value;
59217 }
59218 }
59219
59220
59221
59222
59223 public function hasParameterOption($values)
59224 {
59225 $values = (array) $values;
59226
59227 foreach ($this->parameters as $k => $v) {
59228 if (!\is_int($k)) {
59229 $v = $k;
59230 }
59231
59232 if (\in_array($v, $values)) {
59233 return true;
59234 }
59235 }
59236
59237 return false;
59238 }
59239
59240
59241
59242
59243 public function getParameterOption($values, $default = false)
59244 {
59245 $values = (array) $values;
59246
59247 foreach ($this->parameters as $k => $v) {
59248 if (\is_int($k)) {
59249 if (\in_array($v, $values)) {
59250 return true;
59251 }
59252 } elseif (\in_array($k, $values)) {
59253 return $v;
59254 }
59255 }
59256
59257 return $default;
59258 }
59259
59260
59261
59262
59263
59264
59265 public function __toString()
59266 {
59267 $params = array();
59268 foreach ($this->parameters as $param => $val) {
59269 if ($param && '-' === $param[0]) {
59270 if (\is_array($val)) {
59271 foreach ($val as $v) {
59272 $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
59273 }
59274 } else {
59275 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
59276 }
59277 } else {
59278 $params[] = \is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val);
59279 }
59280 }
59281
59282 return implode(' ', $params);
59283 }
59284
59285
59286
59287
59288 protected function parse()
59289 {
59290 foreach ($this->parameters as $key => $value) {
59291 if (0 === strpos($key, '--')) {
59292 $this->addLongOption(substr($key, 2), $value);
59293 } elseif ('-' === $key[0]) {
59294 $this->addShortOption(substr($key, 1), $value);
59295 } else {
59296 $this->addArgument($key, $value);
59297 }
59298 }
59299 }
59300
59301
59302
59303
59304
59305
59306
59307
59308
59309 private function addShortOption($shortcut, $value)
59310 {
59311 if (!$this->definition->hasShortcut($shortcut)) {
59312 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
59313 }
59314
59315 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
59316 }
59317
59318
59319
59320
59321
59322
59323
59324
59325
59326
59327 private function addLongOption($name, $value)
59328 {
59329 if (!$this->definition->hasOption($name)) {
59330 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
59331 }
59332
59333 $option = $this->definition->getOption($name);
59334
59335 if (null === $value) {
59336 if ($option->isValueRequired()) {
59337 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
59338 }
59339
59340 $value = $option->isValueOptional() ? $option->getDefault() : true;
59341 }
59342
59343 $this->options[$name] = $value;
59344 }
59345
59346
59347
59348
59349
59350
59351
59352
59353
59354 private function addArgument($name, $value)
59355 {
59356 if (!$this->definition->hasArgument($name)) {
59357 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59358 }
59359
59360 $this->arguments[$name] = $value;
59361 }
59362 }
59363 <?php
59364
59365
59366
59367
59368
59369
59370
59371
59372
59373
59374 namespace Symfony\Component\Console\Input;
59375
59376 use Symfony\Component\Console\Exception\InvalidArgumentException;
59377 use Symfony\Component\Console\Exception\RuntimeException;
59378
59379
59380
59381
59382
59383
59384
59385
59386
59387
59388
59389
59390 abstract class Input implements InputInterface
59391 {
59392 protected $definition;
59393 protected $options = array();
59394 protected $arguments = array();
59395 protected $interactive = true;
59396
59397 public function __construct(InputDefinition $definition = null)
59398 {
59399 if (null === $definition) {
59400 $this->definition = new InputDefinition();
59401 } else {
59402 $this->bind($definition);
59403 $this->validate();
59404 }
59405 }
59406
59407
59408
59409
59410 public function bind(InputDefinition $definition)
59411 {
59412 $this->arguments = array();
59413 $this->options = array();
59414 $this->definition = $definition;
59415
59416 $this->parse();
59417 }
59418
59419
59420
59421
59422 abstract protected function parse();
59423
59424
59425
59426
59427 public function validate()
59428 {
59429 $definition = $this->definition;
59430 $givenArguments = $this->arguments;
59431
59432 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
59433 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
59434 });
59435
59436 if (\count($missingArguments) > 0) {
59437 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
59438 }
59439 }
59440
59441
59442
59443
59444 public function isInteractive()
59445 {
59446 return $this->interactive;
59447 }
59448
59449
59450
59451
59452 public function setInteractive($interactive)
59453 {
59454 $this->interactive = (bool) $interactive;
59455 }
59456
59457
59458
59459
59460 public function getArguments()
59461 {
59462 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
59463 }
59464
59465
59466
59467
59468 public function getArgument($name)
59469 {
59470 if (!$this->definition->hasArgument($name)) {
59471 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59472 }
59473
59474 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
59475 }
59476
59477
59478
59479
59480 public function setArgument($name, $value)
59481 {
59482 if (!$this->definition->hasArgument($name)) {
59483 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59484 }
59485
59486 $this->arguments[$name] = $value;
59487 }
59488
59489
59490
59491
59492 public function hasArgument($name)
59493 {
59494 return $this->definition->hasArgument($name);
59495 }
59496
59497
59498
59499
59500 public function getOptions()
59501 {
59502 return array_merge($this->definition->getOptionDefaults(), $this->options);
59503 }
59504
59505
59506
59507
59508 public function getOption($name)
59509 {
59510 if (!$this->definition->hasOption($name)) {
59511 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
59512 }
59513
59514 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
59515 }
59516
59517
59518
59519
59520 public function setOption($name, $value)
59521 {
59522 if (!$this->definition->hasOption($name)) {
59523 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
59524 }
59525
59526 $this->options[$name] = $value;
59527 }
59528
59529
59530
59531
59532 public function hasOption($name)
59533 {
59534 return $this->definition->hasOption($name);
59535 }
59536
59537
59538
59539
59540
59541
59542
59543
59544 public function escapeToken($token)
59545 {
59546 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
59547 }
59548 }
59549 <?php
59550
59551
59552
59553
59554
59555
59556
59557
59558
59559
59560 namespace Symfony\Component\Console\Input;
59561
59562 use Symfony\Component\Console\Exception\InvalidArgumentException;
59563 use Symfony\Component\Console\Exception\LogicException;
59564
59565
59566
59567
59568
59569
59570 class InputArgument
59571 {
59572 const REQUIRED = 1;
59573 const OPTIONAL = 2;
59574 const IS_ARRAY = 4;
59575
59576 private $name;
59577 private $mode;
59578 private $default;
59579 private $description;
59580
59581
59582
59583
59584
59585
59586
59587
59588
59589 public function __construct($name, $mode = null, $description = '', $default = null)
59590 {
59591 if (null === $mode) {
59592 $mode = self::OPTIONAL;
59593 } elseif (!\is_int($mode) || $mode > 7 || $mode < 1) {
59594 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
59595 }
59596
59597 $this->name = $name;
59598 $this->mode = $mode;
59599 $this->description = $description;
59600
59601 $this->setDefault($default);
59602 }
59603
59604
59605
59606
59607
59608
59609 public function getName()
59610 {
59611 return $this->name;
59612 }
59613
59614
59615
59616
59617
59618
59619 public function isRequired()
59620 {
59621 return self::REQUIRED === (self::REQUIRED & $this->mode);
59622 }
59623
59624
59625
59626
59627
59628
59629 public function isArray()
59630 {
59631 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
59632 }
59633
59634
59635
59636
59637
59638
59639
59640
59641 public function setDefault($default = null)
59642 {
59643 if (self::REQUIRED === $this->mode && null !== $default) {
59644 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
59645 }
59646
59647 if ($this->isArray()) {
59648 if (null === $default) {
59649 $default = array();
59650 } elseif (!\is_array($default)) {
59651 throw new LogicException('A default value for an array argument must be an array.');
59652 }
59653 }
59654
59655 $this->default = $default;
59656 }
59657
59658
59659
59660
59661
59662
59663 public function getDefault()
59664 {
59665 return $this->default;
59666 }
59667
59668
59669
59670
59671
59672
59673 public function getDescription()
59674 {
59675 return $this->description;
59676 }
59677 }
59678 <?php
59679
59680
59681
59682
59683
59684
59685
59686
59687
59688
59689 namespace Symfony\Component\Console\Input;
59690
59691
59692
59693
59694
59695
59696
59697 interface InputAwareInterface
59698 {
59699
59700
59701
59702 public function setInput(InputInterface $input);
59703 }
59704 <?php
59705
59706
59707
59708
59709
59710
59711
59712
59713
59714
59715 namespace Symfony\Component\Console\Input;
59716
59717 use Symfony\Component\Console\Descriptor\TextDescriptor;
59718 use Symfony\Component\Console\Descriptor\XmlDescriptor;
59719 use Symfony\Component\Console\Exception\InvalidArgumentException;
59720 use Symfony\Component\Console\Exception\LogicException;
59721 use Symfony\Component\Console\Output\BufferedOutput;
59722
59723
59724
59725
59726
59727
59728
59729
59730
59731
59732
59733
59734
59735 class InputDefinition
59736 {
59737 private $arguments;
59738 private $requiredCount;
59739 private $hasAnArrayArgument = false;
59740 private $hasOptional;
59741 private $options;
59742 private $shortcuts;
59743
59744
59745
59746
59747 public function __construct(array $definition = array())
59748 {
59749 $this->setDefinition($definition);
59750 }
59751
59752
59753
59754
59755 public function setDefinition(array $definition)
59756 {
59757 $arguments = array();
59758 $options = array();
59759 foreach ($definition as $item) {
59760 if ($item instanceof InputOption) {
59761 $options[] = $item;
59762 } else {
59763 $arguments[] = $item;
59764 }
59765 }
59766
59767 $this->setArguments($arguments);
59768 $this->setOptions($options);
59769 }
59770
59771
59772
59773
59774
59775
59776 public function setArguments($arguments = array())
59777 {
59778 $this->arguments = array();
59779 $this->requiredCount = 0;
59780 $this->hasOptional = false;
59781 $this->hasAnArrayArgument = false;
59782 $this->addArguments($arguments);
59783 }
59784
59785
59786
59787
59788
59789
59790 public function addArguments($arguments = array())
59791 {
59792 if (null !== $arguments) {
59793 foreach ($arguments as $argument) {
59794 $this->addArgument($argument);
59795 }
59796 }
59797 }
59798
59799
59800
59801
59802 public function addArgument(InputArgument $argument)
59803 {
59804 if (isset($this->arguments[$argument->getName()])) {
59805 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
59806 }
59807
59808 if ($this->hasAnArrayArgument) {
59809 throw new LogicException('Cannot add an argument after an array argument.');
59810 }
59811
59812 if ($argument->isRequired() && $this->hasOptional) {
59813 throw new LogicException('Cannot add a required argument after an optional one.');
59814 }
59815
59816 if ($argument->isArray()) {
59817 $this->hasAnArrayArgument = true;
59818 }
59819
59820 if ($argument->isRequired()) {
59821 ++$this->requiredCount;
59822 } else {
59823 $this->hasOptional = true;
59824 }
59825
59826 $this->arguments[$argument->getName()] = $argument;
59827 }
59828
59829
59830
59831
59832
59833
59834
59835
59836
59837
59838 public function getArgument($name)
59839 {
59840 if (!$this->hasArgument($name)) {
59841 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
59842 }
59843
59844 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
59845
59846 return $arguments[$name];
59847 }
59848
59849
59850
59851
59852
59853
59854
59855
59856 public function hasArgument($name)
59857 {
59858 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
59859
59860 return isset($arguments[$name]);
59861 }
59862
59863
59864
59865
59866
59867
59868 public function getArguments()
59869 {
59870 return $this->arguments;
59871 }
59872
59873
59874
59875
59876
59877
59878 public function getArgumentCount()
59879 {
59880 return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments);
59881 }
59882
59883
59884
59885
59886
59887
59888 public function getArgumentRequiredCount()
59889 {
59890 return $this->requiredCount;
59891 }
59892
59893
59894
59895
59896
59897
59898 public function getArgumentDefaults()
59899 {
59900 $values = array();
59901 foreach ($this->arguments as $argument) {
59902 $values[$argument->getName()] = $argument->getDefault();
59903 }
59904
59905 return $values;
59906 }
59907
59908
59909
59910
59911
59912
59913 public function setOptions($options = array())
59914 {
59915 $this->options = array();
59916 $this->shortcuts = array();
59917 $this->addOptions($options);
59918 }
59919
59920
59921
59922
59923
59924
59925 public function addOptions($options = array())
59926 {
59927 foreach ($options as $option) {
59928 $this->addOption($option);
59929 }
59930 }
59931
59932
59933
59934
59935 public function addOption(InputOption $option)
59936 {
59937 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
59938 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
59939 }
59940
59941 if ($option->getShortcut()) {
59942 foreach (explode('|', $option->getShortcut()) as $shortcut) {
59943 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
59944 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
59945 }
59946 }
59947 }
59948
59949 $this->options[$option->getName()] = $option;
59950 if ($option->getShortcut()) {
59951 foreach (explode('|', $option->getShortcut()) as $shortcut) {
59952 $this->shortcuts[$shortcut] = $option->getName();
59953 }
59954 }
59955 }
59956
59957
59958
59959
59960
59961
59962
59963
59964
59965
59966 public function getOption($name)
59967 {
59968 if (!$this->hasOption($name)) {
59969 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
59970 }
59971
59972 return $this->options[$name];
59973 }
59974
59975
59976
59977
59978
59979
59980
59981
59982
59983
59984
59985 public function hasOption($name)
59986 {
59987 return isset($this->options[$name]);
59988 }
59989
59990
59991
59992
59993
59994
59995 public function getOptions()
59996 {
59997 return $this->options;
59998 }
59999
60000
60001
60002
60003
60004
60005
60006
60007 public function hasShortcut($name)
60008 {
60009 return isset($this->shortcuts[$name]);
60010 }
60011
60012
60013
60014
60015
60016
60017
60018
60019 public function getOptionForShortcut($shortcut)
60020 {
60021 return $this->getOption($this->shortcutToName($shortcut));
60022 }
60023
60024
60025
60026
60027
60028
60029 public function getOptionDefaults()
60030 {
60031 $values = array();
60032 foreach ($this->options as $option) {
60033 $values[$option->getName()] = $option->getDefault();
60034 }
60035
60036 return $values;
60037 }
60038
60039
60040
60041
60042
60043
60044
60045
60046
60047
60048 private function shortcutToName($shortcut)
60049 {
60050 if (!isset($this->shortcuts[$shortcut])) {
60051 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
60052 }
60053
60054 return $this->shortcuts[$shortcut];
60055 }
60056
60057
60058
60059
60060
60061
60062
60063
60064 public function getSynopsis($short = false)
60065 {
60066 $elements = array();
60067
60068 if ($short && $this->getOptions()) {
60069 $elements[] = '[options]';
60070 } elseif (!$short) {
60071 foreach ($this->getOptions() as $option) {
60072 $value = '';
60073 if ($option->acceptValue()) {
60074 $value = sprintf(
60075 ' %s%s%s',
60076 $option->isValueOptional() ? '[' : '',
60077 strtoupper($option->getName()),
60078 $option->isValueOptional() ? ']' : ''
60079 );
60080 }
60081
60082 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
60083 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
60084 }
60085 }
60086
60087 if (\count($elements) && $this->getArguments()) {
60088 $elements[] = '[--]';
60089 }
60090
60091 foreach ($this->getArguments() as $argument) {
60092 $element = '<'.$argument->getName().'>';
60093 if (!$argument->isRequired()) {
60094 $element = '['.$element.']';
60095 } elseif ($argument->isArray()) {
60096 $element .= ' ('.$element.')';
60097 }
60098
60099 if ($argument->isArray()) {
60100 $element .= '...';
60101 }
60102
60103 $elements[] = $element;
60104 }
60105
60106 return implode(' ', $elements);
60107 }
60108
60109
60110
60111
60112
60113
60114
60115
60116 public function asText()
60117 {
60118 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
60119
60120 $descriptor = new TextDescriptor();
60121 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
60122 $descriptor->describe($output, $this, array('raw_output' => true));
60123
60124 return $output->fetch();
60125 }
60126
60127
60128
60129
60130
60131
60132
60133
60134
60135
60136 public function asXml($asDom = false)
60137 {
60138 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
60139
60140 $descriptor = new XmlDescriptor();
60141
60142 if ($asDom) {
60143 return $descriptor->getInputDefinitionDocument($this);
60144 }
60145
60146 $output = new BufferedOutput();
60147 $descriptor->describe($output, $this);
60148
60149 return $output->fetch();
60150 }
60151 }
60152 <?php
60153
60154
60155
60156
60157
60158
60159
60160
60161
60162
60163 namespace Symfony\Component\Console\Input;
60164
60165 use Symfony\Component\Console\Exception\InvalidArgumentException;
60166 use Symfony\Component\Console\Exception\RuntimeException;
60167
60168
60169
60170
60171
60172
60173 interface InputInterface
60174 {
60175
60176
60177
60178
60179
60180 public function getFirstArgument();
60181
60182
60183
60184
60185
60186
60187
60188
60189
60190
60191
60192
60193
60194 public function hasParameterOption($values);
60195
60196
60197
60198
60199
60200
60201
60202
60203
60204
60205
60206
60207
60208
60209 public function getParameterOption($values, $default = false);
60210
60211
60212
60213
60214
60215
60216 public function bind(InputDefinition $definition);
60217
60218
60219
60220
60221
60222
60223 public function validate();
60224
60225
60226
60227
60228
60229
60230 public function getArguments();
60231
60232
60233
60234
60235
60236
60237
60238
60239
60240
60241 public function getArgument($name);
60242
60243
60244
60245
60246
60247
60248
60249
60250
60251 public function setArgument($name, $value);
60252
60253
60254
60255
60256
60257
60258
60259
60260 public function hasArgument($name);
60261
60262
60263
60264
60265
60266
60267 public function getOptions();
60268
60269
60270
60271
60272
60273
60274
60275
60276
60277
60278 public function getOption($name);
60279
60280
60281
60282
60283
60284
60285
60286
60287
60288 public function setOption($name, $value);
60289
60290
60291
60292
60293
60294
60295
60296
60297 public function hasOption($name);
60298
60299
60300
60301
60302
60303
60304 public function isInteractive();
60305
60306
60307
60308
60309
60310
60311 public function setInteractive($interactive);
60312 }
60313 <?php
60314
60315
60316
60317
60318
60319
60320
60321
60322
60323
60324 namespace Symfony\Component\Console\Input;
60325
60326 use Symfony\Component\Console\Exception\InvalidArgumentException;
60327 use Symfony\Component\Console\Exception\LogicException;
60328
60329
60330
60331
60332
60333
60334 class InputOption
60335 {
60336 const VALUE_NONE = 1;
60337 const VALUE_REQUIRED = 2;
60338 const VALUE_OPTIONAL = 4;
60339 const VALUE_IS_ARRAY = 8;
60340
60341 private $name;
60342 private $shortcut;
60343 private $mode;
60344 private $default;
60345 private $description;
60346
60347
60348
60349
60350
60351
60352
60353
60354
60355
60356 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
60357 {
60358 if (0 === strpos($name, '--')) {
60359 $name = substr($name, 2);
60360 }
60361
60362 if (empty($name)) {
60363 throw new InvalidArgumentException('An option name cannot be empty.');
60364 }
60365
60366 if (empty($shortcut)) {
60367 $shortcut = null;
60368 }
60369
60370 if (null !== $shortcut) {
60371 if (\is_array($shortcut)) {
60372 $shortcut = implode('|', $shortcut);
60373 }
60374 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
60375 $shortcuts = array_filter($shortcuts);
60376 $shortcut = implode('|', $shortcuts);
60377
60378 if (empty($shortcut)) {
60379 throw new InvalidArgumentException('An option shortcut cannot be empty.');
60380 }
60381 }
60382
60383 if (null === $mode) {
60384 $mode = self::VALUE_NONE;
60385 } elseif (!\is_int($mode) || $mode > 15 || $mode < 1) {
60386 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
60387 }
60388
60389 $this->name = $name;
60390 $this->shortcut = $shortcut;
60391 $this->mode = $mode;
60392 $this->description = $description;
60393
60394 if ($this->isArray() && !$this->acceptValue()) {
60395 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
60396 }
60397
60398 $this->setDefault($default);
60399 }
60400
60401
60402
60403
60404
60405
60406 public function getShortcut()
60407 {
60408 return $this->shortcut;
60409 }
60410
60411
60412
60413
60414
60415
60416 public function getName()
60417 {
60418 return $this->name;
60419 }
60420
60421
60422
60423
60424
60425
60426 public function acceptValue()
60427 {
60428 return $this->isValueRequired() || $this->isValueOptional();
60429 }
60430
60431
60432
60433
60434
60435
60436 public function isValueRequired()
60437 {
60438 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
60439 }
60440
60441
60442
60443
60444
60445
60446 public function isValueOptional()
60447 {
60448 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
60449 }
60450
60451
60452
60453
60454
60455
60456 public function isArray()
60457 {
60458 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
60459 }
60460
60461
60462
60463
60464
60465
60466
60467
60468 public function setDefault($default = null)
60469 {
60470 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
60471 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
60472 }
60473
60474 if ($this->isArray()) {
60475 if (null === $default) {
60476 $default = array();
60477 } elseif (!\is_array($default)) {
60478 throw new LogicException('A default value for an array option must be an array.');
60479 }
60480 }
60481
60482 $this->default = $this->acceptValue() ? $default : false;
60483 }
60484
60485
60486
60487
60488
60489
60490 public function getDefault()
60491 {
60492 return $this->default;
60493 }
60494
60495
60496
60497
60498
60499
60500 public function getDescription()
60501 {
60502 return $this->description;
60503 }
60504
60505
60506
60507
60508
60509
60510 public function equals(self $option)
60511 {
60512 return $option->getName() === $this->getName()
60513 && $option->getShortcut() === $this->getShortcut()
60514 && $option->getDefault() === $this->getDefault()
60515 && $option->isArray() === $this->isArray()
60516 && $option->isValueRequired() === $this->isValueRequired()
60517 && $option->isValueOptional() === $this->isValueOptional()
60518 ;
60519 }
60520 }
60521 <?php
60522
60523
60524
60525
60526
60527
60528
60529
60530
60531
60532 namespace Symfony\Component\Console\Input;
60533
60534 use Symfony\Component\Console\Exception\InvalidArgumentException;
60535
60536
60537
60538
60539
60540
60541
60542
60543
60544
60545 class StringInput extends ArgvInput
60546 {
60547 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
60548 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
60549
60550
60551
60552
60553
60554
60555
60556 public function __construct($input, InputDefinition $definition = null)
60557 {
60558 if ($definition) {
60559 @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);
60560 }
60561
60562 parent::__construct(array(), null);
60563
60564 $this->setTokens($this->tokenize($input));
60565
60566 if (null !== $definition) {
60567 $this->bind($definition);
60568 }
60569 }
60570
60571
60572
60573
60574
60575
60576
60577
60578
60579
60580 private function tokenize($input)
60581 {
60582 $tokens = array();
60583 $length = \strlen($input);
60584 $cursor = 0;
60585 while ($cursor < $length) {
60586 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
60587 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
60588 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, \strlen($match[3]) - 2)));
60589 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
60590 $tokens[] = stripcslashes(substr($match[0], 1, \strlen($match[0]) - 2));
60591 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
60592 $tokens[] = stripcslashes($match[1]);
60593 } else {
60594
60595  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
60596 }
60597
60598 $cursor += \strlen($match[0]);
60599 }
60600
60601 return $tokens;
60602 }
60603 }
60604 Copyright (c) 2004-2018 Fabien Potencier
60605
60606 Permission is hereby granted, free of charge, to any person obtaining a copy
60607 of this software and associated documentation files (the "Software"), to deal
60608 in the Software without restriction, including without limitation the rights
60609 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
60610 copies of the Software, and to permit persons to whom the Software is furnished
60611 to do so, subject to the following conditions:
60612
60613 The above copyright notice and this permission notice shall be included in all
60614 copies or substantial portions of the Software.
60615
60616 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60617 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60618 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
60619 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
60620 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60621 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
60622 THE SOFTWARE.
60623 <?php
60624
60625
60626
60627
60628
60629
60630
60631
60632
60633
60634 namespace Symfony\Component\Console\Logger;
60635
60636 use Psr\Log\AbstractLogger;
60637 use Psr\Log\InvalidArgumentException;
60638 use Psr\Log\LogLevel;
60639 use Symfony\Component\Console\Output\ConsoleOutputInterface;
60640 use Symfony\Component\Console\Output\OutputInterface;
60641
60642
60643
60644
60645
60646
60647
60648
60649 class ConsoleLogger extends AbstractLogger
60650 {
60651 const INFO = 'info';
60652 const ERROR = 'error';
60653
60654 private $output;
60655 private $verbosityLevelMap = array(
60656 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
60657 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
60658 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
60659 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
60660 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
60661 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
60662 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
60663 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
60664 );
60665 private $formatLevelMap = array(
60666 LogLevel::EMERGENCY => self::ERROR,
60667 LogLevel::ALERT => self::ERROR,
60668 LogLevel::CRITICAL => self::ERROR,
60669 LogLevel::ERROR => self::ERROR,
60670 LogLevel::WARNING => self::INFO,
60671 LogLevel::NOTICE => self::INFO,
60672 LogLevel::INFO => self::INFO,
60673 LogLevel::DEBUG => self::INFO,
60674 );
60675
60676 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
60677 {
60678 $this->output = $output;
60679 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
60680 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
60681 }
60682
60683
60684
60685
60686 public function log($level, $message, array $context = array())
60687 {
60688 if (!isset($this->verbosityLevelMap[$level])) {
60689 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
60690 }
60691
60692
60693  if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) {
60694 $output = $this->output->getErrorOutput();
60695 } else {
60696 $output = $this->output;
60697 }
60698
60699 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
60700 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
60701 }
60702 }
60703
60704
60705
60706
60707
60708
60709
60710
60711
60712
60713
60714 private function interpolate($message, array $context)
60715 {
60716
60717  $replace = array();
60718 foreach ($context as $key => $val) {
60719 if (!\is_array($val) && (!\is_object($val) || method_exists($val, '__toString'))) {
60720 $replace[sprintf('{%s}', $key)] = $val;
60721 }
60722 }
60723
60724
60725  return strtr($message, $replace);
60726 }
60727 }
60728 <?php
60729
60730
60731
60732
60733
60734
60735
60736
60737
60738
60739 namespace Symfony\Component\Console\Output;
60740
60741
60742
60743
60744 class BufferedOutput extends Output
60745 {
60746 private $buffer = '';
60747
60748
60749
60750
60751
60752
60753 public function fetch()
60754 {
60755 $content = $this->buffer;
60756 $this->buffer = '';
60757
60758 return $content;
60759 }
60760
60761
60762
60763
60764 protected function doWrite($message, $newline)
60765 {
60766 $this->buffer .= $message;
60767
60768 if ($newline) {
60769 $this->buffer .= PHP_EOL;
60770 }
60771 }
60772 }
60773 <?php
60774
60775
60776
60777
60778
60779
60780
60781
60782
60783
60784 namespace Symfony\Component\Console\Output;
60785
60786 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
60787
60788
60789
60790
60791
60792
60793
60794
60795
60796
60797
60798
60799
60800
60801 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
60802 {
60803 private $stderr;
60804
60805
60806
60807
60808
60809
60810 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
60811 {
60812 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
60813
60814 $actualDecorated = $this->isDecorated();
60815 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
60816
60817 if (null === $decorated) {
60818 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
60819 }
60820 }
60821
60822
60823
60824
60825 public function setDecorated($decorated)
60826 {
60827 parent::setDecorated($decorated);
60828 $this->stderr->setDecorated($decorated);
60829 }
60830
60831
60832
60833
60834 public function setFormatter(OutputFormatterInterface $formatter)
60835 {
60836 parent::setFormatter($formatter);
60837 $this->stderr->setFormatter($formatter);
60838 }
60839
60840
60841
60842
60843 public function setVerbosity($level)
60844 {
60845 parent::setVerbosity($level);
60846 $this->stderr->setVerbosity($level);
60847 }
60848
60849
60850
60851
60852 public function getErrorOutput()
60853 {
60854 return $this->stderr;
60855 }
60856
60857
60858
60859
60860 public function setErrorOutput(OutputInterface $error)
60861 {
60862 $this->stderr = $error;
60863 }
60864
60865
60866
60867
60868
60869
60870
60871 protected function hasStdoutSupport()
60872 {
60873 return false === $this->isRunningOS400();
60874 }
60875
60876
60877
60878
60879
60880
60881
60882 protected function hasStderrSupport()
60883 {
60884 return false === $this->isRunningOS400();
60885 }
60886
60887
60888
60889
60890
60891
60892
60893 private function isRunningOS400()
60894 {
60895 $checks = array(
60896 \function_exists('php_uname') ? php_uname('s') : '',
60897 getenv('OSTYPE'),
60898 PHP_OS,
60899 );
60900
60901 return false !== stripos(implode(';', $checks), 'OS400');
60902 }
60903
60904
60905
60906
60907 private function openOutputStream()
60908 {
60909 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
60910
60911 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
60912 }
60913
60914
60915
60916
60917 private function openErrorStream()
60918 {
60919 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
60920
60921 return fopen($errorStream, 'w');
60922 }
60923 }
60924 <?php
60925
60926
60927
60928
60929
60930
60931
60932
60933
60934
60935 namespace Symfony\Component\Console\Output;
60936
60937
60938
60939
60940
60941
60942
60943 interface ConsoleOutputInterface extends OutputInterface
60944 {
60945
60946
60947
60948
60949
60950 public function getErrorOutput();
60951
60952 public function setErrorOutput(OutputInterface $error);
60953 }
60954 <?php
60955
60956
60957
60958
60959
60960
60961
60962
60963
60964
60965 namespace Symfony\Component\Console\Output;
60966
60967 use Symfony\Component\Console\Formatter\OutputFormatter;
60968 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
60969
60970
60971
60972
60973
60974
60975
60976
60977
60978 class NullOutput implements OutputInterface
60979 {
60980
60981
60982
60983 public function setFormatter(OutputFormatterInterface $formatter)
60984 {
60985
60986  }
60987
60988
60989
60990
60991 public function getFormatter()
60992 {
60993
60994  return new OutputFormatter();
60995 }
60996
60997
60998
60999
61000 public function setDecorated($decorated)
61001 {
61002
61003  }
61004
61005
61006
61007
61008 public function isDecorated()
61009 {
61010 return false;
61011 }
61012
61013
61014
61015
61016 public function setVerbosity($level)
61017 {
61018
61019  }
61020
61021
61022
61023
61024 public function getVerbosity()
61025 {
61026 return self::VERBOSITY_QUIET;
61027 }
61028
61029
61030
61031
61032 public function isQuiet()
61033 {
61034 return true;
61035 }
61036
61037
61038
61039
61040 public function isVerbose()
61041 {
61042 return false;
61043 }
61044
61045
61046
61047
61048 public function isVeryVerbose()
61049 {
61050 return false;
61051 }
61052
61053
61054
61055
61056 public function isDebug()
61057 {
61058 return false;
61059 }
61060
61061
61062
61063
61064 public function writeln($messages, $options = self::OUTPUT_NORMAL)
61065 {
61066
61067  }
61068
61069
61070
61071
61072 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
61073 {
61074
61075  }
61076 }
61077 <?php
61078
61079
61080
61081
61082
61083
61084
61085
61086
61087
61088 namespace Symfony\Component\Console\Output;
61089
61090 use Symfony\Component\Console\Formatter\OutputFormatter;
61091 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
61092
61093
61094
61095
61096
61097
61098
61099
61100
61101
61102
61103
61104
61105
61106 abstract class Output implements OutputInterface
61107 {
61108 private $verbosity;
61109 private $formatter;
61110
61111
61112
61113
61114
61115
61116 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
61117 {
61118 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
61119 $this->formatter = $formatter ?: new OutputFormatter();
61120 $this->formatter->setDecorated($decorated);
61121 }
61122
61123
61124
61125
61126 public function setFormatter(OutputFormatterInterface $formatter)
61127 {
61128 $this->formatter = $formatter;
61129 }
61130
61131
61132
61133
61134 public function getFormatter()
61135 {
61136 return $this->formatter;
61137 }
61138
61139
61140
61141
61142 public function setDecorated($decorated)
61143 {
61144 $this->formatter->setDecorated($decorated);
61145 }
61146
61147
61148
61149
61150 public function isDecorated()
61151 {
61152 return $this->formatter->isDecorated();
61153 }
61154
61155
61156
61157
61158 public function setVerbosity($level)
61159 {
61160 $this->verbosity = (int) $level;
61161 }
61162
61163
61164
61165
61166 public function getVerbosity()
61167 {
61168 return $this->verbosity;
61169 }
61170
61171
61172
61173
61174 public function isQuiet()
61175 {
61176 return self::VERBOSITY_QUIET === $this->verbosity;
61177 }
61178
61179
61180
61181
61182 public function isVerbose()
61183 {
61184 return self::VERBOSITY_VERBOSE <= $this->verbosity;
61185 }
61186
61187
61188
61189
61190 public function isVeryVerbose()
61191 {
61192 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
61193 }
61194
61195
61196
61197
61198 public function isDebug()
61199 {
61200 return self::VERBOSITY_DEBUG <= $this->verbosity;
61201 }
61202
61203
61204
61205
61206 public function writeln($messages, $options = self::OUTPUT_NORMAL)
61207 {
61208 $this->write($messages, true, $options);
61209 }
61210
61211
61212
61213
61214 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
61215 {
61216 $messages = (array) $messages;
61217
61218 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
61219 $type = $types & $options ?: self::OUTPUT_NORMAL;
61220
61221 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
61222 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
61223
61224 if ($verbosity > $this->getVerbosity()) {
61225 return;
61226 }
61227
61228 foreach ($messages as $message) {
61229 switch ($type) {
61230 case OutputInterface::OUTPUT_NORMAL:
61231 $message = $this->formatter->format($message);
61232 break;
61233 case OutputInterface::OUTPUT_RAW:
61234 break;
61235 case OutputInterface::OUTPUT_PLAIN:
61236 $message = strip_tags($this->formatter->format($message));
61237 break;
61238 }
61239
61240 $this->doWrite($message, $newline);
61241 }
61242 }
61243
61244
61245
61246
61247
61248
61249
61250 abstract protected function doWrite($message, $newline);
61251 }
61252 <?php
61253
61254
61255
61256
61257
61258
61259
61260
61261
61262
61263 namespace Symfony\Component\Console\Output;
61264
61265 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
61266
61267
61268
61269
61270
61271
61272 interface OutputInterface
61273 {
61274 const VERBOSITY_QUIET = 16;
61275 const VERBOSITY_NORMAL = 32;
61276 const VERBOSITY_VERBOSE = 64;
61277 const VERBOSITY_VERY_VERBOSE = 128;
61278 const VERBOSITY_DEBUG = 256;
61279
61280 const OUTPUT_NORMAL = 1;
61281 const OUTPUT_RAW = 2;
61282 const OUTPUT_PLAIN = 4;
61283
61284
61285
61286
61287
61288
61289
61290
61291 public function write($messages, $newline = false, $options = 0);
61292
61293
61294
61295
61296
61297
61298
61299 public function writeln($messages, $options = 0);
61300
61301
61302
61303
61304
61305
61306 public function setVerbosity($level);
61307
61308
61309
61310
61311
61312
61313 public function getVerbosity();
61314
61315
61316
61317
61318
61319
61320 public function setDecorated($decorated);
61321
61322
61323
61324
61325
61326
61327 public function isDecorated();
61328
61329 public function setFormatter(OutputFormatterInterface $formatter);
61330
61331
61332
61333
61334
61335
61336 public function getFormatter();
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\Exception\InvalidArgumentException;
61352 use Symfony\Component\Console\Exception\RuntimeException;
61353 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
61354
61355
61356
61357
61358
61359
61360
61361
61362
61363
61364
61365
61366
61367
61368 class StreamOutput extends Output
61369 {
61370 private $stream;
61371
61372
61373
61374
61375
61376
61377
61378
61379
61380 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
61381 {
61382 if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
61383 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
61384 }
61385
61386 $this->stream = $stream;
61387
61388 if (null === $decorated) {
61389 $decorated = $this->hasColorSupport();
61390 }
61391
61392 parent::__construct($verbosity, $decorated, $formatter);
61393 }
61394
61395
61396
61397
61398
61399
61400 public function getStream()
61401 {
61402 return $this->stream;
61403 }
61404
61405
61406
61407
61408 protected function doWrite($message, $newline)
61409 {
61410 if ($newline) {
61411 $message .= PHP_EOL;
61412 }
61413
61414 if (false === @fwrite($this->stream, $message)) {
61415
61416  throw new RuntimeException('Unable to write output.');
61417 }
61418
61419 fflush($this->stream);
61420 }
61421
61422
61423
61424
61425
61426
61427
61428
61429
61430
61431
61432
61433
61434
61435 protected function hasColorSupport()
61436 {
61437 if ('Hyper' === getenv('TERM_PROGRAM')) {
61438 return true;
61439 }
61440
61441 if (\DIRECTORY_SEPARATOR === '\\') {
61442 return (\function_exists('sapi_windows_vt100_support')
61443 && @sapi_windows_vt100_support($this->stream))
61444 || false !== getenv('ANSICON')
61445 || 'ON' === getenv('ConEmuANSI')
61446 || 'xterm' === getenv('TERM');
61447 }
61448
61449 if (\function_exists('stream_isatty')) {
61450 return @stream_isatty($this->stream);
61451 }
61452
61453 if (\function_exists('posix_isatty')) {
61454 return @posix_isatty($this->stream);
61455 }
61456
61457 $stat = @fstat($this->stream);
61458
61459  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
61460 }
61461 }
61462 <?php
61463
61464
61465
61466
61467
61468
61469
61470
61471
61472
61473 namespace Symfony\Component\Console\Question;
61474
61475 use Symfony\Component\Console\Exception\InvalidArgumentException;
61476
61477
61478
61479
61480
61481
61482 class ChoiceQuestion extends Question
61483 {
61484 private $choices;
61485 private $multiselect = false;
61486 private $prompt = ' > ';
61487 private $errorMessage = 'Value "%s" is invalid';
61488
61489
61490
61491
61492
61493
61494 public function __construct($question, array $choices, $default = null)
61495 {
61496 if (!$choices) {
61497 throw new \LogicException('Choice question must have at least 1 choice available.');
61498 }
61499
61500 parent::__construct($question, $default);
61501
61502 $this->choices = $choices;
61503 $this->setValidator($this->getDefaultValidator());
61504 $this->setAutocompleterValues($choices);
61505 }
61506
61507
61508
61509
61510
61511
61512 public function getChoices()
61513 {
61514 return $this->choices;
61515 }
61516
61517
61518
61519
61520
61521
61522
61523
61524
61525
61526 public function setMultiselect($multiselect)
61527 {
61528 $this->multiselect = $multiselect;
61529 $this->setValidator($this->getDefaultValidator());
61530
61531 return $this;
61532 }
61533
61534
61535
61536
61537
61538
61539 public function isMultiselect()
61540 {
61541 return $this->multiselect;
61542 }
61543
61544
61545
61546
61547
61548
61549 public function getPrompt()
61550 {
61551 return $this->prompt;
61552 }
61553
61554
61555
61556
61557
61558
61559
61560
61561 public function setPrompt($prompt)
61562 {
61563 $this->prompt = $prompt;
61564
61565 return $this;
61566 }
61567
61568
61569
61570
61571
61572
61573
61574
61575
61576
61577 public function setErrorMessage($errorMessage)
61578 {
61579 $this->errorMessage = $errorMessage;
61580 $this->setValidator($this->getDefaultValidator());
61581
61582 return $this;
61583 }
61584
61585
61586
61587
61588
61589
61590 private function getDefaultValidator()
61591 {
61592 $choices = $this->choices;
61593 $errorMessage = $this->errorMessage;
61594 $multiselect = $this->multiselect;
61595 $isAssoc = $this->isAssoc($choices);
61596
61597 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
61598
61599  $selectedChoices = str_replace(' ', '', $selected);
61600
61601 if ($multiselect) {
61602
61603  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
61604 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
61605 }
61606 $selectedChoices = explode(',', $selectedChoices);
61607 } else {
61608 $selectedChoices = array($selected);
61609 }
61610
61611 $multiselectChoices = array();
61612 foreach ($selectedChoices as $value) {
61613 $results = array();
61614 foreach ($choices as $key => $choice) {
61615 if ($choice === $value) {
61616 $results[] = $key;
61617 }
61618 }
61619
61620 if (\count($results) > 1) {
61621 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
61622 }
61623
61624 $result = array_search($value, $choices);
61625
61626 if (!$isAssoc) {
61627 if (false !== $result) {
61628 $result = $choices[$result];
61629 } elseif (isset($choices[$value])) {
61630 $result = $choices[$value];
61631 }
61632 } elseif (false === $result && isset($choices[$value])) {
61633 $result = $value;
61634 }
61635
61636 if (false === $result) {
61637 throw new InvalidArgumentException(sprintf($errorMessage, $value));
61638 }
61639
61640 $multiselectChoices[] = (string) $result;
61641 }
61642
61643 if ($multiselect) {
61644 return $multiselectChoices;
61645 }
61646
61647 return current($multiselectChoices);
61648 };
61649 }
61650 }
61651 <?php
61652
61653
61654
61655
61656
61657
61658
61659
61660
61661
61662 namespace Symfony\Component\Console\Question;
61663
61664
61665
61666
61667
61668
61669 class ConfirmationQuestion extends Question
61670 {
61671 private $trueAnswerRegex;
61672
61673
61674
61675
61676
61677
61678 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
61679 {
61680 parent::__construct($question, (bool) $default);
61681
61682 $this->trueAnswerRegex = $trueAnswerRegex;
61683 $this->setNormalizer($this->getDefaultNormalizer());
61684 }
61685
61686
61687
61688
61689
61690
61691 private function getDefaultNormalizer()
61692 {
61693 $default = $this->getDefault();
61694 $regex = $this->trueAnswerRegex;
61695
61696 return function ($answer) use ($default, $regex) {
61697 if (\is_bool($answer)) {
61698 return $answer;
61699 }
61700
61701 $answerIsTrue = (bool) preg_match($regex, $answer);
61702 if (false === $default) {
61703 return $answer && $answerIsTrue;
61704 }
61705
61706 return !$answer || $answerIsTrue;
61707 };
61708 }
61709 }
61710 <?php
61711
61712
61713
61714
61715
61716
61717
61718
61719
61720
61721 namespace Symfony\Component\Console\Question;
61722
61723 use Symfony\Component\Console\Exception\InvalidArgumentException;
61724 use Symfony\Component\Console\Exception\LogicException;
61725
61726
61727
61728
61729
61730
61731 class Question
61732 {
61733 private $question;
61734 private $attempts;
61735 private $hidden = false;
61736 private $hiddenFallback = true;
61737 private $autocompleterValues;
61738 private $validator;
61739 private $default;
61740 private $normalizer;
61741
61742
61743
61744
61745
61746 public function __construct($question, $default = null)
61747 {
61748 $this->question = $question;
61749 $this->default = $default;
61750 }
61751
61752
61753
61754
61755
61756
61757 public function getQuestion()
61758 {
61759 return $this->question;
61760 }
61761
61762
61763
61764
61765
61766
61767 public function getDefault()
61768 {
61769 return $this->default;
61770 }
61771
61772
61773
61774
61775
61776
61777 public function isHidden()
61778 {
61779 return $this->hidden;
61780 }
61781
61782
61783
61784
61785
61786
61787
61788
61789
61790
61791 public function setHidden($hidden)
61792 {
61793 if ($this->autocompleterValues) {
61794 throw new LogicException('A hidden question cannot use the autocompleter.');
61795 }
61796
61797 $this->hidden = (bool) $hidden;
61798
61799 return $this;
61800 }
61801
61802
61803
61804
61805
61806
61807 public function isHiddenFallback()
61808 {
61809 return $this->hiddenFallback;
61810 }
61811
61812
61813
61814
61815
61816
61817
61818
61819 public function setHiddenFallback($fallback)
61820 {
61821 $this->hiddenFallback = (bool) $fallback;
61822
61823 return $this;
61824 }
61825
61826
61827
61828
61829
61830
61831 public function getAutocompleterValues()
61832 {
61833 return $this->autocompleterValues;
61834 }
61835
61836
61837
61838
61839
61840
61841
61842
61843
61844
61845
61846 public function setAutocompleterValues($values)
61847 {
61848 if (\is_array($values)) {
61849 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
61850 }
61851
61852 if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) {
61853 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
61854 }
61855
61856 if ($this->hidden) {
61857 throw new LogicException('A hidden question cannot use the autocompleter.');
61858 }
61859
61860 $this->autocompleterValues = $values;
61861
61862 return $this;
61863 }
61864
61865
61866
61867
61868
61869
61870
61871
61872 public function setValidator($validator)
61873 {
61874 $this->validator = $validator;
61875
61876 return $this;
61877 }
61878
61879
61880
61881
61882
61883
61884 public function getValidator()
61885 {
61886 return $this->validator;
61887 }
61888
61889
61890
61891
61892
61893
61894
61895
61896
61897
61898
61899
61900 public function setMaxAttempts($attempts)
61901 {
61902 if (null !== $attempts && $attempts < 1) {
61903 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
61904 }
61905
61906 $this->attempts = $attempts;
61907
61908 return $this;
61909 }
61910
61911
61912
61913
61914
61915
61916
61917
61918 public function getMaxAttempts()
61919 {
61920 return $this->attempts;
61921 }
61922
61923
61924
61925
61926
61927
61928
61929
61930
61931
61932 public function setNormalizer($normalizer)
61933 {
61934 $this->normalizer = $normalizer;
61935
61936 return $this;
61937 }
61938
61939
61940
61941
61942
61943
61944
61945
61946 public function getNormalizer()
61947 {
61948 return $this->normalizer;
61949 }
61950
61951 protected function isAssoc($array)
61952 {
61953 return (bool) \count(array_filter(array_keys($array), 'is_string'));
61954 }
61955 }
61956 <?php
61957
61958
61959
61960
61961
61962
61963
61964
61965
61966
61967 namespace Symfony\Component\Console;
61968
61969 use Symfony\Component\Console\Exception\RuntimeException;
61970 use Symfony\Component\Console\Input\StringInput;
61971 use Symfony\Component\Console\Output\ConsoleOutput;
61972 use Symfony\Component\Process\PhpExecutableFinder;
61973 use Symfony\Component\Process\ProcessBuilder;
61974
61975
61976
61977
61978
61979
61980
61981
61982
61983
61984
61985
61986 class Shell
61987 {
61988 private $application;
61989 private $history;
61990 private $output;
61991 private $hasReadline;
61992 private $processIsolation = false;
61993
61994
61995
61996
61997
61998 public function __construct(Application $application)
61999 {
62000 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
62001
62002 $this->hasReadline = \function_exists('readline');
62003 $this->application = $application;
62004 $this->history = getenv('HOME').'/.history_'.$application->getName();
62005 $this->output = new ConsoleOutput();
62006 }
62007
62008
62009
62010
62011 public function run()
62012 {
62013 $this->application->setAutoExit(false);
62014 $this->application->setCatchExceptions(true);
62015
62016 if ($this->hasReadline) {
62017 readline_read_history($this->history);
62018 readline_completion_function(array($this, 'autocompleter'));
62019 }
62020
62021 $this->output->writeln($this->getHeader());
62022 $php = null;
62023 if ($this->processIsolation) {
62024 $finder = new PhpExecutableFinder();
62025 $php = $finder->find();
62026 $this->output->writeln(<<<'EOF'
62027 <info>Running with process isolation, you should consider this:</info>
62028   * each command is executed as separate process,
62029   * commands don't support interactivity, all params must be passed explicitly,
62030   * commands output is not colorized.
62031
62032 EOF
62033 );
62034 }
62035
62036 while (true) {
62037 $command = $this->readline();
62038
62039 if (false === $command) {
62040 $this->output->writeln("\n");
62041
62042 break;
62043 }
62044
62045 if ($this->hasReadline) {
62046 readline_add_history($command);
62047 readline_write_history($this->history);
62048 }
62049
62050 if ($this->processIsolation) {
62051 $pb = new ProcessBuilder();
62052
62053 $process = $pb
62054 ->add($php)
62055 ->add($_SERVER['argv'][0])
62056 ->add($command)
62057 ->inheritEnvironmentVariables(true)
62058 ->getProcess()
62059 ;
62060
62061 $output = $this->output;
62062 $process->run(function ($type, $data) use ($output) {
62063 $output->writeln($data);
62064 });
62065
62066 $ret = $process->getExitCode();
62067 } else {
62068 $ret = $this->application->run(new StringInput($command), $this->output);
62069 }
62070
62071 if (0 !== $ret) {
62072 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
62073 }
62074 }
62075 }
62076
62077
62078
62079
62080
62081
62082 protected function getHeader()
62083 {
62084 return <<<EOF
62085
62086 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
62087
62088 At the prompt, type <comment>help</comment> for some help,
62089 or <comment>list</comment> to get a list of available commands.
62090
62091 To exit the shell, type <comment>^D</comment>.
62092
62093 EOF;
62094 }
62095
62096
62097
62098
62099
62100
62101 protected function getPrompt()
62102 {
62103
62104  return $this->output->getFormatter()->format($this->application->getName().' > ');
62105 }
62106
62107 protected function getOutput()
62108 {
62109 return $this->output;
62110 }
62111
62112 protected function getApplication()
62113 {
62114 return $this->application;
62115 }
62116
62117
62118
62119
62120
62121
62122
62123
62124 private function autocompleter($text)
62125 {
62126 $info = readline_info();
62127 $text = substr($info['line_buffer'], 0, $info['end']);
62128
62129 if ($info['point'] !== $info['end']) {
62130 return true;
62131 }
62132
62133
62134  if (false === strpos($text, ' ') || !$text) {
62135 return array_keys($this->application->all());
62136 }
62137
62138
62139  try {
62140 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
62141 } catch (\Exception $e) {
62142 return true;
62143 }
62144
62145 $list = array('--help');
62146 foreach ($command->getDefinition()->getOptions() as $option) {
62147 $list[] = '--'.$option->getName();
62148 }
62149
62150 return $list;
62151 }
62152
62153
62154
62155
62156
62157
62158 private function readline()
62159 {
62160 if ($this->hasReadline) {
62161 $line = readline($this->getPrompt());
62162 } else {
62163 $this->output->write($this->getPrompt());
62164 $line = fgets(STDIN, 1024);
62165 $line = (false === $line || '' === $line) ? false : rtrim($line);
62166 }
62167
62168 return $line;
62169 }
62170
62171 public function getProcessIsolation()
62172 {
62173 return $this->processIsolation;
62174 }
62175
62176 public function setProcessIsolation($processIsolation)
62177 {
62178 $this->processIsolation = (bool) $processIsolation;
62179
62180 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
62181 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
62182 }
62183 }
62184 }
62185 <?php
62186
62187
62188
62189
62190
62191
62192
62193
62194
62195
62196 namespace Symfony\Component\Console\Style;
62197
62198 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
62199 use Symfony\Component\Console\Helper\ProgressBar;
62200 use Symfony\Component\Console\Output\OutputInterface;
62201
62202
62203
62204
62205
62206
62207 abstract class OutputStyle implements OutputInterface, StyleInterface
62208 {
62209 private $output;
62210
62211 public function __construct(OutputInterface $output)
62212 {
62213 $this->output = $output;
62214 }
62215
62216
62217
62218
62219 public function newLine($count = 1)
62220 {
62221 $this->output->write(str_repeat(PHP_EOL, $count));
62222 }
62223
62224
62225
62226
62227
62228
62229 public function createProgressBar($max = 0)
62230 {
62231 return new ProgressBar($this->output, $max);
62232 }
62233
62234
62235
62236
62237 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
62238 {
62239 $this->output->write($messages, $newline, $type);
62240 }
62241
62242
62243
62244
62245 public function writeln($messages, $type = self::OUTPUT_NORMAL)
62246 {
62247 $this->output->writeln($messages, $type);
62248 }
62249
62250
62251
62252
62253 public function setVerbosity($level)
62254 {
62255 $this->output->setVerbosity($level);
62256 }
62257
62258
62259
62260
62261 public function getVerbosity()
62262 {
62263 return $this->output->getVerbosity();
62264 }
62265
62266
62267
62268
62269 public function setDecorated($decorated)
62270 {
62271 $this->output->setDecorated($decorated);
62272 }
62273
62274
62275
62276
62277 public function isDecorated()
62278 {
62279 return $this->output->isDecorated();
62280 }
62281
62282
62283
62284
62285 public function setFormatter(OutputFormatterInterface $formatter)
62286 {
62287 $this->output->setFormatter($formatter);
62288 }
62289
62290
62291
62292
62293 public function getFormatter()
62294 {
62295 return $this->output->getFormatter();
62296 }
62297 }
62298 <?php
62299
62300
62301
62302
62303
62304
62305
62306
62307
62308
62309 namespace Symfony\Component\Console\Style;
62310
62311
62312
62313
62314
62315
62316 interface StyleInterface
62317 {
62318
62319
62320
62321
62322
62323 public function title($message);
62324
62325
62326
62327
62328
62329
62330 public function section($message);
62331
62332
62333
62334
62335 public function listing(array $elements);
62336
62337
62338
62339
62340
62341
62342 public function text($message);
62343
62344
62345
62346
62347
62348
62349 public function success($message);
62350
62351
62352
62353
62354
62355
62356 public function error($message);
62357
62358
62359
62360
62361
62362
62363 public function warning($message);
62364
62365
62366
62367
62368
62369
62370 public function note($message);
62371
62372
62373
62374
62375
62376
62377 public function caution($message);
62378
62379
62380
62381
62382 public function table(array $headers, array $rows);
62383
62384
62385
62386
62387
62388
62389
62390
62391
62392
62393 public function ask($question, $default = null, $validator = null);
62394
62395
62396
62397
62398
62399
62400
62401
62402
62403 public function askHidden($question, $validator = null);
62404
62405
62406
62407
62408
62409
62410
62411
62412
62413 public function confirm($question, $default = true);
62414
62415
62416
62417
62418
62419
62420
62421
62422
62423
62424 public function choice($question, array $choices, $default = null);
62425
62426
62427
62428
62429
62430
62431 public function newLine($count = 1);
62432
62433
62434
62435
62436
62437
62438 public function progressStart($max = 0);
62439
62440
62441
62442
62443
62444
62445 public function progressAdvance($step = 1);
62446
62447
62448
62449
62450 public function progressFinish();
62451 }
62452 <?php
62453
62454
62455
62456
62457
62458
62459
62460
62461
62462
62463 namespace Symfony\Component\Console\Style;
62464
62465 use Symfony\Component\Console\Application;
62466 use Symfony\Component\Console\Exception\RuntimeException;
62467 use Symfony\Component\Console\Formatter\OutputFormatter;
62468 use Symfony\Component\Console\Helper\Helper;
62469 use Symfony\Component\Console\Helper\ProgressBar;
62470 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
62471 use Symfony\Component\Console\Helper\Table;
62472 use Symfony\Component\Console\Input\InputInterface;
62473 use Symfony\Component\Console\Output\BufferedOutput;
62474 use Symfony\Component\Console\Output\OutputInterface;
62475 use Symfony\Component\Console\Question\ChoiceQuestion;
62476 use Symfony\Component\Console\Question\ConfirmationQuestion;
62477 use Symfony\Component\Console\Question\Question;
62478
62479
62480
62481
62482
62483
62484 class SymfonyStyle extends OutputStyle
62485 {
62486 const MAX_LINE_LENGTH = 120;
62487
62488 private $input;
62489 private $questionHelper;
62490 private $progressBar;
62491 private $lineLength;
62492 private $bufferedOutput;
62493
62494 public function __construct(InputInterface $input, OutputInterface $output)
62495 {
62496 $this->input = $input;
62497 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
62498
62499  $this->lineLength = min($this->getTerminalWidth() - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
62500
62501 parent::__construct($output);
62502 }
62503
62504
62505
62506
62507
62508
62509
62510
62511
62512
62513 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
62514 {
62515 $messages = \is_array($messages) ? array_values($messages) : array($messages);
62516
62517 $this->autoPrependBlock();
62518 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
62519 $this->newLine();
62520 }
62521
62522
62523
62524
62525 public function title($message)
62526 {
62527 $this->autoPrependBlock();
62528 $this->writeln(array(
62529 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
62530 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
62531 ));
62532 $this->newLine();
62533 }
62534
62535
62536
62537
62538 public function section($message)
62539 {
62540 $this->autoPrependBlock();
62541 $this->writeln(array(
62542 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
62543 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
62544 ));
62545 $this->newLine();
62546 }
62547
62548
62549
62550
62551 public function listing(array $elements)
62552 {
62553 $this->autoPrependText();
62554 $elements = array_map(function ($element) {
62555 return sprintf(' * %s', $element);
62556 }, $elements);
62557
62558 $this->writeln($elements);
62559 $this->newLine();
62560 }
62561
62562
62563
62564
62565 public function text($message)
62566 {
62567 $this->autoPrependText();
62568
62569 $messages = \is_array($message) ? array_values($message) : array($message);
62570 foreach ($messages as $message) {
62571 $this->writeln(sprintf(' %s', $message));
62572 }
62573 }
62574
62575
62576
62577
62578
62579
62580 public function comment($message)
62581 {
62582 $messages = \is_array($message) ? array_values($message) : array($message);
62583
62584 $this->autoPrependBlock();
62585 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
62586 $this->newLine();
62587 }
62588
62589
62590
62591
62592 public function success($message)
62593 {
62594 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
62595 }
62596
62597
62598
62599
62600 public function error($message)
62601 {
62602 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
62603 }
62604
62605
62606
62607
62608 public function warning($message)
62609 {
62610 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
62611 }
62612
62613
62614
62615
62616 public function note($message)
62617 {
62618 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
62619 }
62620
62621
62622
62623
62624 public function caution($message)
62625 {
62626 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
62627 }
62628
62629
62630
62631
62632 public function table(array $headers, array $rows)
62633 {
62634 $style = clone Table::getStyleDefinition('symfony-style-guide');
62635 $style->setCellHeaderFormat('<info>%s</info>');
62636
62637 $table = new Table($this);
62638 $table->setHeaders($headers);
62639 $table->setRows($rows);
62640 $table->setStyle($style);
62641
62642 $table->render();
62643 $this->newLine();
62644 }
62645
62646
62647
62648
62649 public function ask($question, $default = null, $validator = null)
62650 {
62651 $question = new Question($question, $default);
62652 $question->setValidator($validator);
62653
62654 return $this->askQuestion($question);
62655 }
62656
62657
62658
62659
62660 public function askHidden($question, $validator = null)
62661 {
62662 $question = new Question($question);
62663
62664 $question->setHidden(true);
62665 $question->setValidator($validator);
62666
62667 return $this->askQuestion($question);
62668 }
62669
62670
62671
62672
62673 public function confirm($question, $default = true)
62674 {
62675 return $this->askQuestion(new ConfirmationQuestion($question, $default));
62676 }
62677
62678
62679
62680
62681 public function choice($question, array $choices, $default = null)
62682 {
62683 if (null !== $default) {
62684 $values = array_flip($choices);
62685 $default = $values[$default];
62686 }
62687
62688 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
62689 }
62690
62691
62692
62693
62694 public function progressStart($max = 0)
62695 {
62696 $this->progressBar = $this->createProgressBar($max);
62697 $this->progressBar->start();
62698 }
62699
62700
62701
62702
62703 public function progressAdvance($step = 1)
62704 {
62705 $this->getProgressBar()->advance($step);
62706 }
62707
62708
62709
62710
62711 public function progressFinish()
62712 {
62713 $this->getProgressBar()->finish();
62714 $this->newLine(2);
62715 $this->progressBar = null;
62716 }
62717
62718
62719
62720
62721 public function createProgressBar($max = 0)
62722 {
62723 $progressBar = parent::createProgressBar($max);
62724
62725 if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
62726 $progressBar->setEmptyBarCharacter('░'); 
62727  $progressBar->setProgressCharacter('');
62728 $progressBar->setBarCharacter('▓'); 
62729  }
62730
62731 return $progressBar;
62732 }
62733
62734
62735
62736
62737 public function askQuestion(Question $question)
62738 {
62739 if ($this->input->isInteractive()) {
62740 $this->autoPrependBlock();
62741 }
62742
62743 if (!$this->questionHelper) {
62744 $this->questionHelper = new SymfonyQuestionHelper();
62745 }
62746
62747 $answer = $this->questionHelper->ask($this->input, $this, $question);
62748
62749 if ($this->input->isInteractive()) {
62750 $this->newLine();
62751 $this->bufferedOutput->write("\n");
62752 }
62753
62754 return $answer;
62755 }
62756
62757
62758
62759
62760 public function writeln($messages, $type = self::OUTPUT_NORMAL)
62761 {
62762 parent::writeln($messages, $type);
62763 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
62764 }
62765
62766
62767
62768
62769 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
62770 {
62771 parent::write($messages, $newline, $type);
62772 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
62773 }
62774
62775
62776
62777
62778 public function newLine($count = 1)
62779 {
62780 parent::newLine($count);
62781 $this->bufferedOutput->write(str_repeat("\n", $count));
62782 }
62783
62784
62785
62786
62787 private function getProgressBar()
62788 {
62789 if (!$this->progressBar) {
62790 throw new RuntimeException('The ProgressBar is not started.');
62791 }
62792
62793 return $this->progressBar;
62794 }
62795
62796 private function getTerminalWidth()
62797 {
62798 $application = new Application();
62799 $dimensions = $application->getTerminalDimensions();
62800
62801 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
62802 }
62803
62804 private function autoPrependBlock()
62805 {
62806 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
62807
62808 if (!isset($chars[0])) {
62809 return $this->newLine(); 
62810  }
62811
62812  $this->newLine(2 - substr_count($chars, "\n"));
62813 }
62814
62815 private function autoPrependText()
62816 {
62817 $fetched = $this->bufferedOutput->fetch();
62818
62819  if ("\n" !== substr($fetched, -1)) {
62820 $this->newLine();
62821 }
62822 }
62823
62824 private function reduceBuffer($messages)
62825 {
62826
62827  
62828  return array_map(function ($value) {
62829 return substr($value, -4);
62830 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
62831 }
62832
62833 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
62834 {
62835 $indentLength = 0;
62836 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
62837 $lines = array();
62838
62839 if (null !== $type) {
62840 $type = sprintf('[%s] ', $type);
62841 $indentLength = \strlen($type);
62842 $lineIndentation = str_repeat(' ', $indentLength);
62843 }
62844
62845
62846  foreach ($messages as $key => $message) {
62847 if ($escape) {
62848 $message = OutputFormatter::escape($message);
62849 }
62850
62851 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
62852
62853 if (\count($messages) > 1 && $key < \count($messages) - 1) {
62854 $lines[] = '';
62855 }
62856 }
62857
62858 $firstLineIndex = 0;
62859 if ($padding && $this->isDecorated()) {
62860 $firstLineIndex = 1;
62861 array_unshift($lines, '');
62862 $lines[] = '';
62863 }
62864
62865 foreach ($lines as $i => &$line) {
62866 if (null !== $type) {
62867 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
62868 }
62869
62870 $line = $prefix.$line;
62871 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
62872
62873 if ($style) {
62874 $line = sprintf('<%s>%s</>', $style, $line);
62875 }
62876 }
62877
62878 return $lines;
62879 }
62880 }
62881 <?php
62882
62883
62884
62885
62886
62887
62888
62889
62890
62891
62892 namespace Symfony\Component\Console\Tester;
62893
62894 use Symfony\Component\Console\Application;
62895 use Symfony\Component\Console\Input\ArrayInput;
62896 use Symfony\Component\Console\Input\InputInterface;
62897 use Symfony\Component\Console\Output\OutputInterface;
62898 use Symfony\Component\Console\Output\StreamOutput;
62899
62900
62901
62902
62903
62904
62905
62906
62907
62908
62909
62910 class ApplicationTester
62911 {
62912 private $application;
62913 private $input;
62914 private $output;
62915 private $statusCode;
62916
62917 public function __construct(Application $application)
62918 {
62919 $this->application = $application;
62920 }
62921
62922
62923
62924
62925
62926
62927
62928
62929
62930
62931
62932
62933
62934
62935
62936 public function run(array $input, $options = array())
62937 {
62938 $this->input = new ArrayInput($input);
62939 if (isset($options['interactive'])) {
62940 $this->input->setInteractive($options['interactive']);
62941 }
62942
62943 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
62944 if (isset($options['decorated'])) {
62945 $this->output->setDecorated($options['decorated']);
62946 }
62947 if (isset($options['verbosity'])) {
62948 $this->output->setVerbosity($options['verbosity']);
62949 }
62950
62951 return $this->statusCode = $this->application->run($this->input, $this->output);
62952 }
62953
62954
62955
62956
62957
62958
62959
62960
62961 public function getDisplay($normalize = false)
62962 {
62963 rewind($this->output->getStream());
62964
62965 $display = stream_get_contents($this->output->getStream());
62966
62967 if ($normalize) {
62968 $display = str_replace(PHP_EOL, "\n", $display);
62969 }
62970
62971 return $display;
62972 }
62973
62974
62975
62976
62977
62978
62979 public function getInput()
62980 {
62981 return $this->input;
62982 }
62983
62984
62985
62986
62987
62988
62989 public function getOutput()
62990 {
62991 return $this->output;
62992 }
62993
62994
62995
62996
62997
62998
62999 public function getStatusCode()
63000 {
63001 return $this->statusCode;
63002 }
63003 }
63004 <?php
63005
63006
63007
63008
63009
63010
63011
63012
63013
63014
63015 namespace Symfony\Component\Console\Tester;
63016
63017 use Symfony\Component\Console\Command\Command;
63018 use Symfony\Component\Console\Input\ArrayInput;
63019 use Symfony\Component\Console\Input\InputInterface;
63020 use Symfony\Component\Console\Output\OutputInterface;
63021 use Symfony\Component\Console\Output\StreamOutput;
63022
63023
63024
63025
63026
63027
63028 class CommandTester
63029 {
63030 private $command;
63031 private $input;
63032 private $output;
63033 private $statusCode;
63034
63035 public function __construct(Command $command)
63036 {
63037 $this->command = $command;
63038 }
63039
63040
63041
63042
63043
63044
63045
63046
63047
63048
63049
63050
63051
63052
63053
63054 public function execute(array $input, array $options = array())
63055 {
63056
63057  
63058  if (!isset($input['command'])
63059 && (null !== $application = $this->command->getApplication())
63060 && $application->getDefinition()->hasArgument('command')
63061 ) {
63062 $input = array_merge(array('command' => $this->command->getName()), $input);
63063 }
63064
63065 $this->input = new ArrayInput($input);
63066 if (isset($options['interactive'])) {
63067 $this->input->setInteractive($options['interactive']);
63068 }
63069
63070 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
63071 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
63072 if (isset($options['verbosity'])) {
63073 $this->output->setVerbosity($options['verbosity']);
63074 }
63075
63076 return $this->statusCode = $this->command->run($this->input, $this->output);
63077 }
63078
63079
63080
63081
63082
63083
63084
63085
63086 public function getDisplay($normalize = false)
63087 {
63088 rewind($this->output->getStream());
63089
63090 $display = stream_get_contents($this->output->getStream());
63091
63092 if ($normalize) {
63093 $display = str_replace(PHP_EOL, "\n", $display);
63094 }
63095
63096 return $display;
63097 }
63098
63099
63100
63101
63102
63103
63104 public function getInput()
63105 {
63106 return $this->input;
63107 }
63108
63109
63110
63111
63112
63113
63114 public function getOutput()
63115 {
63116 return $this->output;
63117 }
63118
63119
63120
63121
63122
63123
63124 public function getStatusCode()
63125 {
63126 return $this->statusCode;
63127 }
63128 }
63129 <?php
63130
63131
63132
63133
63134
63135
63136
63137
63138
63139
63140 namespace Symfony\Component\Debug;
63141
63142 use Psr\Log\AbstractLogger;
63143
63144
63145
63146
63147
63148
63149 class BufferingLogger extends AbstractLogger
63150 {
63151 private $logs = array();
63152
63153 public function log($level, $message, array $context = array())
63154 {
63155 $this->logs[] = array($level, $message, $context);
63156 }
63157
63158 public function cleanLogs()
63159 {
63160 $logs = $this->logs;
63161 $this->logs = array();
63162
63163 return $logs;
63164 }
63165 }
63166 <?php
63167
63168
63169
63170
63171
63172
63173
63174
63175
63176
63177 namespace Symfony\Component\Debug;
63178
63179
63180
63181
63182
63183
63184 class Debug
63185 {
63186 private static $enabled = false;
63187
63188
63189
63190
63191
63192
63193
63194
63195
63196 public static function enable($errorReportingLevel = null, $displayErrors = true)
63197 {
63198 if (static::$enabled) {
63199 return;
63200 }
63201
63202 static::$enabled = true;
63203
63204 if (null !== $errorReportingLevel) {
63205 error_reporting($errorReportingLevel);
63206 } else {
63207 error_reporting(-1);
63208 }
63209
63210 if (!\in_array(\PHP_SAPI, array('cli', 'phpdbg'), true)) {
63211 ini_set('display_errors', 0);
63212 ExceptionHandler::register();
63213 } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) {
63214
63215  ini_set('display_errors', 1);
63216 }
63217 if ($displayErrors) {
63218 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
63219 } else {
63220 ErrorHandler::register()->throwAt(0, true);
63221 }
63222
63223 DebugClassLoader::enable();
63224 }
63225 }
63226 <?php
63227
63228
63229
63230
63231
63232
63233
63234
63235
63236
63237 namespace Symfony\Component\Debug;
63238
63239
63240
63241
63242
63243
63244
63245
63246
63247
63248
63249
63250 class DebugClassLoader
63251 {
63252 private $classLoader;
63253 private $isFinder;
63254 private $loaded = array();
63255 private $wasFinder;
63256 private static $caseCheck;
63257 private static $deprecated = array();
63258 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
63259 private static $darwinCache = array('/' => array('/', array()));
63260
63261
63262
63263
63264 public function __construct($classLoader)
63265 {
63266 $this->wasFinder = \is_object($classLoader) && method_exists($classLoader, 'findFile');
63267
63268 if ($this->wasFinder) {
63269 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
63270 $this->classLoader = array($classLoader, 'loadClass');
63271 $this->isFinder = true;
63272 } else {
63273 $this->classLoader = $classLoader;
63274 $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
63275 }
63276
63277 if (!isset(self::$caseCheck)) {
63278 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
63279 $i = strrpos($file, \DIRECTORY_SEPARATOR);
63280 $dir = substr($file, 0, 1 + $i);
63281 $file = substr($file, 1 + $i);
63282 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
63283 $test = realpath($dir.$test);
63284
63285 if (false === $test || false === $i) {
63286
63287  self::$caseCheck = 0;
63288 } elseif (substr($test, -\strlen($file)) === $file) {
63289
63290  self::$caseCheck = 1;
63291 } elseif (false !== stripos(PHP_OS, 'darwin')) {
63292
63293  self::$caseCheck = 2;
63294 } else {
63295
63296  self::$caseCheck = 0;
63297 }
63298 }
63299 }
63300
63301
63302
63303
63304
63305
63306 public function getClassLoader()
63307 {
63308 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
63309 }
63310
63311
63312
63313
63314 public static function enable()
63315 {
63316
63317  class_exists('Symfony\Component\Debug\ErrorHandler');
63318 class_exists('Psr\Log\LogLevel');
63319
63320 if (!\is_array($functions = spl_autoload_functions())) {
63321 return;
63322 }
63323
63324 foreach ($functions as $function) {
63325 spl_autoload_unregister($function);
63326 }
63327
63328 foreach ($functions as $function) {
63329 if (!\is_array($function) || !$function[0] instanceof self) {
63330 $function = array(new static($function), 'loadClass');
63331 }
63332
63333 spl_autoload_register($function);
63334 }
63335 }
63336
63337
63338
63339
63340 public static function disable()
63341 {
63342 if (!\is_array($functions = spl_autoload_functions())) {
63343 return;
63344 }
63345
63346 foreach ($functions as $function) {
63347 spl_autoload_unregister($function);
63348 }
63349
63350 foreach ($functions as $function) {
63351 if (\is_array($function) && $function[0] instanceof self) {
63352 $function = $function[0]->getClassLoader();
63353 }
63354
63355 spl_autoload_register($function);
63356 }
63357 }
63358
63359
63360
63361
63362
63363
63364
63365
63366
63367
63368 public function findFile($class)
63369 {
63370 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
63371
63372 if ($this->wasFinder) {
63373 return $this->classLoader[0]->findFile($class);
63374 }
63375 }
63376
63377
63378
63379
63380
63381
63382
63383
63384
63385
63386 public function loadClass($class)
63387 {
63388 ErrorHandler::stackErrors();
63389
63390 try {
63391 if ($this->isFinder && !isset($this->loaded[$class])) {
63392 $this->loaded[$class] = true;
63393 if ($file = $this->classLoader[0]->findFile($class)) {
63394 require $file;
63395 }
63396 } else {
63397 \call_user_func($this->classLoader, $class);
63398 $file = false;
63399 }
63400 } catch (\Exception $e) {
63401 ErrorHandler::unstackErrors();
63402
63403 throw $e;
63404 } catch (\Throwable $e) {
63405 ErrorHandler::unstackErrors();
63406
63407 throw $e;
63408 }
63409
63410 ErrorHandler::unstackErrors();
63411
63412 $exists = class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
63413
63414 if ($class && '\\' === $class[0]) {
63415 $class = substr($class, 1);
63416 }
63417
63418 if ($exists) {
63419 $refl = new \ReflectionClass($class);
63420 $name = $refl->getName();
63421
63422 if ($name !== $class && 0 === strcasecmp($name, $class)) {
63423 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
63424 }
63425
63426 if (\in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
63427 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
63428 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
63429 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
63430 } else {
63431 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
63432 $len = 0;
63433 $ns = '';
63434 } else {
63435 $ns = substr($name, 0, $len);
63436 }
63437 $parent = get_parent_class($class);
63438
63439 if (!$parent || strncmp($ns, $parent, $len)) {
63440 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
63441 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
63442 }
63443
63444 $parentInterfaces = array();
63445 $deprecatedInterfaces = array();
63446 if ($parent) {
63447 foreach (class_implements($parent) as $interface) {
63448 $parentInterfaces[$interface] = 1;
63449 }
63450 }
63451
63452 foreach ($refl->getInterfaceNames() as $interface) {
63453 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
63454 $deprecatedInterfaces[] = $interface;
63455 }
63456 foreach (class_implements($interface) as $interface) {
63457 $parentInterfaces[$interface] = 1;
63458 }
63459 }
63460
63461 foreach ($deprecatedInterfaces as $interface) {
63462 if (!isset($parentInterfaces[$interface])) {
63463 @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);
63464 }
63465 }
63466 }
63467 }
63468 }
63469
63470 if ($file) {
63471 if (!$exists) {
63472 if (false !== strpos($class, '/')) {
63473 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));
63474 }
63475
63476 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));
63477 }
63478 if (self::$caseCheck) {
63479 $real = explode('\\', $class.strrchr($file, '.'));
63480 $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
63481
63482 $i = \count($tail) - 1;
63483 $j = \count($real) - 1;
63484
63485 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
63486 --$i;
63487 --$j;
63488 }
63489
63490 array_splice($tail, 0, $i + 1);
63491 }
63492 if (self::$caseCheck && $tail) {
63493 $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
63494 $tailLen = \strlen($tail);
63495 $real = $refl->getFileName();
63496
63497 if (2 === self::$caseCheck) {
63498
63499
63500 $i = 1 + strrpos($real, '/');
63501 $file = substr($real, $i);
63502 $real = substr($real, 0, $i);
63503
63504 if (isset(self::$darwinCache[$real])) {
63505 $kDir = $real;
63506 } else {
63507 $kDir = strtolower($real);
63508
63509 if (isset(self::$darwinCache[$kDir])) {
63510 $real = self::$darwinCache[$kDir][0];
63511 } else {
63512 $dir = getcwd();
63513 chdir($real);
63514 $real = getcwd().'/';
63515 chdir($dir);
63516
63517 $dir = $real;
63518 $k = $kDir;
63519 $i = \strlen($dir) - 1;
63520 while (!isset(self::$darwinCache[$k])) {
63521 self::$darwinCache[$k] = array($dir, array());
63522 self::$darwinCache[$dir] = &self::$darwinCache[$k];
63523
63524 while ('/' !== $dir[--$i]) {
63525 }
63526 $k = substr($k, 0, ++$i);
63527 $dir = substr($dir, 0, $i--);
63528 }
63529 }
63530 }
63531
63532 $dirFiles = self::$darwinCache[$kDir][1];
63533
63534 if (isset($dirFiles[$file])) {
63535 $kFile = $file;
63536 } else {
63537 $kFile = strtolower($file);
63538
63539 if (!isset($dirFiles[$kFile])) {
63540 foreach (scandir($real, 2) as $f) {
63541 if ('.' !== $f[0]) {
63542 $dirFiles[$f] = $f;
63543 if ($f === $file) {
63544 $kFile = $k = $file;
63545 } elseif ($f !== $k = strtolower($f)) {
63546 $dirFiles[$k] = $f;
63547 }
63548 }
63549 }
63550 self::$darwinCache[$kDir][1] = $dirFiles;
63551 }
63552 }
63553
63554 $real .= $dirFiles[$kFile];
63555 }
63556
63557 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
63558 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
63559 ) {
63560 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)));
63561 }
63562 }
63563
63564 return true;
63565 }
63566 }
63567 }
63568 <?php
63569
63570
63571
63572
63573
63574
63575
63576
63577
63578
63579 namespace Symfony\Component\Debug;
63580
63581 use Psr\Log\LoggerInterface;
63582 use Psr\Log\LogLevel;
63583 use Symfony\Component\Debug\Exception\ContextErrorException;
63584 use Symfony\Component\Debug\Exception\FatalErrorException;
63585 use Symfony\Component\Debug\Exception\FatalThrowableError;
63586 use Symfony\Component\Debug\Exception\OutOfMemoryException;
63587 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
63588 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
63589 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
63590 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
63591
63592
63593
63594
63595
63596
63597
63598
63599
63600
63601
63602
63603
63604
63605
63606
63607
63608
63609
63610
63611
63612
63613
63614 class ErrorHandler
63615 {
63616
63617
63618
63619 const TYPE_DEPRECATION = -100;
63620
63621 private $levels = array(
63622 E_DEPRECATED => 'Deprecated',
63623 E_USER_DEPRECATED => 'User Deprecated',
63624 E_NOTICE => 'Notice',
63625 E_USER_NOTICE => 'User Notice',
63626 E_STRICT => 'Runtime Notice',
63627 E_WARNING => 'Warning',
63628 E_USER_WARNING => 'User Warning',
63629 E_COMPILE_WARNING => 'Compile Warning',
63630 E_CORE_WARNING => 'Core Warning',
63631 E_USER_ERROR => 'User Error',
63632 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
63633 E_COMPILE_ERROR => 'Compile Error',
63634 E_PARSE => 'Parse Error',
63635 E_ERROR => 'Error',
63636 E_CORE_ERROR => 'Core Error',
63637 );
63638
63639 private $loggers = array(
63640 E_DEPRECATED => array(null, LogLevel::INFO),
63641 E_USER_DEPRECATED => array(null, LogLevel::INFO),
63642 E_NOTICE => array(null, LogLevel::WARNING),
63643 E_USER_NOTICE => array(null, LogLevel::WARNING),
63644 E_STRICT => array(null, LogLevel::WARNING),
63645 E_WARNING => array(null, LogLevel::WARNING),
63646 E_USER_WARNING => array(null, LogLevel::WARNING),
63647 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
63648 E_CORE_WARNING => array(null, LogLevel::WARNING),
63649 E_USER_ERROR => array(null, LogLevel::CRITICAL),
63650 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
63651 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
63652 E_PARSE => array(null, LogLevel::CRITICAL),
63653 E_ERROR => array(null, LogLevel::CRITICAL),
63654 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
63655 );
63656
63657 private $thrownErrors = 0x1FFF; 
63658  private $scopedErrors = 0x1FFF; 
63659  private $tracedErrors = 0x77FB; 
63660  private $screamedErrors = 0x55; 
63661  private $loggedErrors = 0;
63662
63663 private $loggedTraces = array();
63664 private $isRecursive = 0;
63665 private $isRoot = false;
63666 private $exceptionHandler;
63667 private $bootstrappingLogger;
63668
63669 private static $reservedMemory;
63670 private static $stackedErrors = array();
63671 private static $stackedErrorLevels = array();
63672 private static $toStringException = null;
63673 private static $exitCode = 0;
63674
63675
63676
63677
63678
63679
63680 private $displayErrors = 0x1FFF;
63681
63682
63683
63684
63685
63686
63687
63688
63689
63690 public static function register($handler = null, $replace = true)
63691 {
63692 if (null === self::$reservedMemory) {
63693 self::$reservedMemory = str_repeat('x', 10240);
63694 register_shutdown_function(__CLASS__.'::handleFatalError');
63695 }
63696
63697 $levels = -1;
63698
63699 if ($handlerIsNew = !$handler instanceof self) {
63700
63701  if (null !== $handler) {
63702 $levels = $replace ? $handler : 0;
63703 $replace = true;
63704 }
63705 $handler = new static();
63706 }
63707
63708 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
63709 restore_error_handler();
63710
63711  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
63712 $handler->isRoot = true;
63713 }
63714
63715 if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) {
63716 $handler = $prev[0];
63717 $replace = false;
63718 }
63719 if (!$replace && $prev) {
63720 restore_error_handler();
63721 $handlerIsRegistered = \is_array($prev) && $handler === $prev[0];
63722 } else {
63723 $handlerIsRegistered = true;
63724 }
63725 if (\is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
63726 restore_exception_handler();
63727 if (!$handlerIsRegistered) {
63728 $handler = $prev[0];
63729 } elseif ($handler !== $prev[0] && $replace) {
63730 set_exception_handler(array($handler, 'handleException'));
63731 $p = $prev[0]->setExceptionHandler(null);
63732 $handler->setExceptionHandler($p);
63733 $prev[0]->setExceptionHandler($p);
63734 }
63735 } else {
63736 $handler->setExceptionHandler($prev);
63737 }
63738
63739 $handler->throwAt($levels & $handler->thrownErrors, true);
63740
63741 return $handler;
63742 }
63743
63744 public function __construct(BufferingLogger $bootstrappingLogger = null)
63745 {
63746 if ($bootstrappingLogger) {
63747 $this->bootstrappingLogger = $bootstrappingLogger;
63748 $this->setDefaultLogger($bootstrappingLogger);
63749 }
63750 }
63751
63752
63753
63754
63755
63756
63757
63758
63759 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
63760 {
63761 $loggers = array();
63762
63763 if (\is_array($levels)) {
63764 foreach ($levels as $type => $logLevel) {
63765 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
63766 $loggers[$type] = array($logger, $logLevel);
63767 }
63768 }
63769 } else {
63770 if (null === $levels) {
63771 $levels = E_ALL | E_STRICT;
63772 }
63773 foreach ($this->loggers as $type => $log) {
63774 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
63775 $log[0] = $logger;
63776 $loggers[$type] = $log;
63777 }
63778 }
63779 }
63780
63781 $this->setLoggers($loggers);
63782 }
63783
63784
63785
63786
63787
63788
63789
63790
63791
63792
63793 public function setLoggers(array $loggers)
63794 {
63795 $prevLogged = $this->loggedErrors;
63796 $prev = $this->loggers;
63797 $flush = array();
63798
63799 foreach ($loggers as $type => $log) {
63800 if (!isset($prev[$type])) {
63801 throw new \InvalidArgumentException('Unknown error type: '.$type);
63802 }
63803 if (!\is_array($log)) {
63804 $log = array($log);
63805 } elseif (!array_key_exists(0, $log)) {
63806 throw new \InvalidArgumentException('No logger provided');
63807 }
63808 if (null === $log[0]) {
63809 $this->loggedErrors &= ~$type;
63810 } elseif ($log[0] instanceof LoggerInterface) {
63811 $this->loggedErrors |= $type;
63812 } else {
63813 throw new \InvalidArgumentException('Invalid logger provided');
63814 }
63815 $this->loggers[$type] = $log + $prev[$type];
63816
63817 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
63818 $flush[$type] = $type;
63819 }
63820 }
63821 $this->reRegister($prevLogged | $this->thrownErrors);
63822
63823 if ($flush) {
63824 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
63825 $type = $log[2]['type'];
63826 if (!isset($flush[$type])) {
63827 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
63828 } elseif ($this->loggers[$type][0]) {
63829 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
63830 }
63831 }
63832 }
63833
63834 return $prev;
63835 }
63836
63837
63838
63839
63840
63841
63842
63843
63844
63845
63846 public function setExceptionHandler($handler)
63847 {
63848 if (null !== $handler && !\is_callable($handler)) {
63849 throw new \LogicException('The exception handler must be a valid PHP callable.');
63850 }
63851 $prev = $this->exceptionHandler;
63852 $this->exceptionHandler = $handler;
63853
63854 return $prev;
63855 }
63856
63857
63858
63859
63860
63861
63862
63863
63864
63865 public function throwAt($levels, $replace = false)
63866 {
63867 $prev = $this->thrownErrors;
63868 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
63869 if (!$replace) {
63870 $this->thrownErrors |= $prev;
63871 }
63872 $this->reRegister($prev | $this->loggedErrors);
63873
63874
63875  $this->displayErrors = $this->thrownErrors;
63876
63877 return $prev;
63878 }
63879
63880
63881
63882
63883
63884
63885
63886
63887
63888 public function scopeAt($levels, $replace = false)
63889 {
63890 $prev = $this->scopedErrors;
63891 $this->scopedErrors = (int) $levels;
63892 if (!$replace) {
63893 $this->scopedErrors |= $prev;
63894 }
63895
63896 return $prev;
63897 }
63898
63899
63900
63901
63902
63903
63904
63905
63906
63907 public function traceAt($levels, $replace = false)
63908 {
63909 $prev = $this->tracedErrors;
63910 $this->tracedErrors = (int) $levels;
63911 if (!$replace) {
63912 $this->tracedErrors |= $prev;
63913 }
63914
63915 return $prev;
63916 }
63917
63918
63919
63920
63921
63922
63923
63924
63925
63926 public function screamAt($levels, $replace = false)
63927 {
63928 $prev = $this->screamedErrors;
63929 $this->screamedErrors = (int) $levels;
63930 if (!$replace) {
63931 $this->screamedErrors |= $prev;
63932 }
63933
63934 return $prev;
63935 }
63936
63937
63938
63939
63940 private function reRegister($prev)
63941 {
63942 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
63943 $handler = set_error_handler('var_dump');
63944 $handler = \is_array($handler) ? $handler[0] : null;
63945 restore_error_handler();
63946 if ($handler === $this) {
63947 restore_error_handler();
63948 if ($this->isRoot) {
63949 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
63950 } else {
63951 set_error_handler(array($this, 'handleError'));
63952 }
63953 }
63954 }
63955 }
63956
63957
63958
63959
63960
63961
63962
63963
63964
63965
63966
63967
63968
63969
63970
63971 public function handleError($type, $message, $file, $line)
63972 {
63973 $level = error_reporting();
63974 $silenced = 0 === ($level & $type);
63975 $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
63976 $log = $this->loggedErrors & $type;
63977 $throw = $this->thrownErrors & $type & $level;
63978 $type &= $level | $this->screamedErrors;
63979
63980 if (!$type || (!$log && !$throw)) {
63981 return !$silenced && $type && $log;
63982 }
63983 $scope = $this->scopedErrors & $type;
63984
63985 if (4 < $numArgs = \func_num_args()) {
63986 $context = $scope ? (func_get_arg(4) ?: array()) : array();
63987 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
63988  } else {
63989 $context = array();
63990 $backtrace = null;
63991 }
63992
63993 if (isset($context['GLOBALS']) && $scope) {
63994 $e = $context; 
63995  unset($e['GLOBALS'], $context); 
63996  $context = $e;
63997 }
63998
63999 if (null !== $backtrace && $type & E_ERROR) {
64000
64001  
64002  
64003  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
64004
64005 return true;
64006 }
64007
64008 if ($throw) {
64009 if (null !== self::$toStringException) {
64010 $throw = self::$toStringException;
64011 self::$toStringException = null;
64012 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
64013
64014  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
64015 } else {
64016 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
64017 }
64018
64019 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
64020
64021  
64022  
64023
64024 $throw->errorHandlerCanary = new ErrorHandlerCanary();
64025 }
64026
64027 if (E_USER_ERROR & $type) {
64028 $backtrace = $backtrace ?: $throw->getTrace();
64029
64030 for ($i = 1; isset($backtrace[$i]); ++$i) {
64031 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
64032 && '__toString' === $backtrace[$i]['function']
64033 && '->' === $backtrace[$i]['type']
64034 && !isset($backtrace[$i - 1]['class'])
64035 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
64036 ) {
64037
64038  
64039  
64040  
64041  
64042  
64043
64044 foreach ($context as $e) {
64045 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
64046 if (1 === $i) {
64047
64048  $throw = $e;
64049 break;
64050 }
64051 self::$toStringException = $e;
64052
64053 return true;
64054 }
64055 }
64056
64057 if (1 < $i) {
64058
64059  $this->handleException($throw);
64060
64061
64062  return false;
64063 }
64064 }
64065 }
64066 }
64067
64068 throw $throw;
64069 }
64070
64071
64072  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
64073 $trace = true;
64074
64075 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
64076 $trace = false;
64077 } else {
64078 $this->loggedTraces[$e] = 1;
64079 }
64080
64081 $e = compact('type', 'file', 'line', 'level');
64082
64083 if ($type & $level) {
64084 if ($scope) {
64085 $e['scope_vars'] = $context;
64086 if ($trace) {
64087 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
64088 }
64089 } elseif ($trace) {
64090 if (null === $backtrace) {
64091 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
64092 } else {
64093 foreach ($backtrace as &$frame) {
64094 unset($frame['args'], $frame);
64095 }
64096 $e['stack'] = $backtrace;
64097 }
64098 }
64099 }
64100
64101 if ($this->isRecursive) {
64102 $log = 0;
64103 } elseif (self::$stackedErrorLevels) {
64104 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
64105 } else {
64106 try {
64107 $this->isRecursive = true;
64108 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
64109 $this->isRecursive = false;
64110 } catch (\Exception $e) {
64111 $this->isRecursive = false;
64112
64113 throw $e;
64114 } catch (\Throwable $e) {
64115 $this->isRecursive = false;
64116
64117 throw $e;
64118 }
64119 }
64120
64121 return !$silenced && $type && $log;
64122 }
64123
64124
64125
64126
64127
64128
64129
64130
64131
64132 public function handleException($exception, array $error = null)
64133 {
64134 if (null === $error) {
64135 self::$exitCode = 255;
64136 }
64137 if (!$exception instanceof \Exception) {
64138 $exception = new FatalThrowableError($exception);
64139 }
64140 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
64141 $handlerException = null;
64142
64143 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
64144 $e = array(
64145 'type' => $type,
64146 'file' => $exception->getFile(),
64147 'line' => $exception->getLine(),
64148 'level' => error_reporting(),
64149 'stack' => $exception->getTrace(),
64150 );
64151 if ($exception instanceof FatalErrorException) {
64152 if ($exception instanceof FatalThrowableError) {
64153 $error = array(
64154 'type' => $type,
64155 'message' => $message = $exception->getMessage(),
64156 'file' => $e['file'],
64157 'line' => $e['line'],
64158 );
64159 } else {
64160 $message = 'Fatal '.$exception->getMessage();
64161 }
64162 } elseif ($exception instanceof \ErrorException) {
64163 $message = 'Uncaught '.$exception->getMessage();
64164 if ($exception instanceof ContextErrorException) {
64165 $e['context'] = $exception->getContext();
64166 }
64167 } else {
64168 $message = 'Uncaught Exception: '.$exception->getMessage();
64169 }
64170 }
64171 if ($this->loggedErrors & $type) {
64172 try {
64173 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
64174 } catch (\Exception $handlerException) {
64175 } catch (\Throwable $handlerException) {
64176 }
64177 }
64178 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
64179 foreach ($this->getFatalErrorHandlers() as $handler) {
64180 if ($e = $handler->handleError($error, $exception)) {
64181 $exception = $e;
64182 break;
64183 }
64184 }
64185 }
64186 $exceptionHandler = $this->exceptionHandler;
64187 $this->exceptionHandler = null;
64188 try {
64189 if (null !== $exceptionHandler) {
64190 return \call_user_func($exceptionHandler, $exception);
64191 }
64192 $handlerException = $handlerException ?: $exception;
64193 } catch (\Exception $handlerException) {
64194 } catch (\Throwable $handlerException) {
64195 }
64196 if ($exception === $handlerException) {
64197 self::$reservedMemory = null; 
64198  throw $exception; 
64199  }
64200 $this->handleException($handlerException);
64201 }
64202
64203
64204
64205
64206
64207
64208
64209
64210 public static function handleFatalError(array $error = null)
64211 {
64212 if (null === self::$reservedMemory) {
64213 return;
64214 }
64215
64216 $handler = self::$reservedMemory = null;
64217 $handlers = array();
64218 $previousHandler = null;
64219 $sameHandlerLimit = 10;
64220
64221 while (!\is_array($handler) || !$handler[0] instanceof self) {
64222 $handler = set_exception_handler('var_dump');
64223 restore_exception_handler();
64224
64225 if (!$handler) {
64226 break;
64227 }
64228 restore_exception_handler();
64229
64230 if ($handler !== $previousHandler) {
64231 array_unshift($handlers, $handler);
64232 $previousHandler = $handler;
64233 } elseif (0 === --$sameHandlerLimit) {
64234 $handler = null;
64235 break;
64236 }
64237 }
64238 foreach ($handlers as $h) {
64239 set_exception_handler($h);
64240 }
64241 if (!$handler) {
64242 return;
64243 }
64244 if ($handler !== $h) {
64245 $handler[0]->setExceptionHandler($h);
64246 }
64247 $handler = $handler[0];
64248 $handlers = array();
64249
64250 if ($exit = null === $error) {
64251 $error = error_get_last();
64252 }
64253
64254 try {
64255 while (self::$stackedErrorLevels) {
64256 static::unstackErrors();
64257 }
64258 } catch (\Exception $exception) {
64259
64260  } catch (\Throwable $exception) {
64261
64262  }
64263
64264 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
64265
64266  $handler->throwAt(0, true);
64267 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
64268
64269 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
64270 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
64271 } else {
64272 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
64273 }
64274 }
64275
64276 try {
64277 if (isset($exception)) {
64278 self::$exitCode = 255;
64279 $handler->handleException($exception, $error);
64280 }
64281 } catch (FatalErrorException $e) {
64282
64283  }
64284
64285 if ($exit && self::$exitCode) {
64286 $exitCode = self::$exitCode;
64287 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
64288 }
64289 }
64290
64291
64292
64293
64294
64295
64296
64297
64298
64299
64300
64301
64302 public static function stackErrors()
64303 {
64304 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
64305 }
64306
64307
64308
64309
64310 public static function unstackErrors()
64311 {
64312 $level = array_pop(self::$stackedErrorLevels);
64313
64314 if (null !== $level) {
64315 $e = error_reporting($level);
64316 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
64317
64318  error_reporting($e);
64319 }
64320 }
64321
64322 if (empty(self::$stackedErrorLevels)) {
64323 $errors = self::$stackedErrors;
64324 self::$stackedErrors = array();
64325
64326 foreach ($errors as $e) {
64327 $e[0]->log($e[1], $e[2], $e[3]);
64328 }
64329 }
64330 }
64331
64332
64333
64334
64335
64336
64337
64338
64339 protected function getFatalErrorHandlers()
64340 {
64341 return array(
64342 new UndefinedFunctionFatalErrorHandler(),
64343 new UndefinedMethodFatalErrorHandler(),
64344 new ClassNotFoundFatalErrorHandler(),
64345 );
64346 }
64347
64348
64349
64350
64351
64352
64353
64354
64355 public function setLevel($level)
64356 {
64357 @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);
64358
64359 $level = null === $level ? error_reporting() : $level;
64360 $this->throwAt($level, true);
64361 }
64362
64363
64364
64365
64366
64367
64368
64369
64370 public function setDisplayErrors($displayErrors)
64371 {
64372 @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);
64373
64374 if ($displayErrors) {
64375 $this->throwAt($this->displayErrors, true);
64376 } else {
64377 $displayErrors = $this->displayErrors;
64378 $this->throwAt(0, true);
64379 $this->displayErrors = $displayErrors;
64380 }
64381 }
64382
64383
64384
64385
64386
64387
64388
64389
64390
64391 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
64392 {
64393 @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);
64394
64395 $handler = set_error_handler('var_dump');
64396 $handler = \is_array($handler) ? $handler[0] : null;
64397 restore_error_handler();
64398 if (!$handler instanceof self) {
64399 return;
64400 }
64401 if ('deprecation' === $channel) {
64402 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
64403 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
64404 } elseif ('scream' === $channel) {
64405 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
64406 $handler->screamAt(E_ALL | E_STRICT);
64407 } elseif ('emergency' === $channel) {
64408 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
64409 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
64410 }
64411 }
64412
64413
64414
64415
64416 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
64417 {
64418 $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());
64419
64420 return $this->handleError($level, $message, $file, $line, (array) $context);
64421 }
64422
64423
64424
64425
64426
64427
64428 public function handleFatal()
64429 {
64430 @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);
64431
64432 static::handleFatalError();
64433 }
64434 }
64435
64436
64437
64438
64439
64440
64441
64442
64443 class ErrorHandlerCanary
64444 {
64445 private static $displayErrors = null;
64446
64447 public function __construct()
64448 {
64449 if (null === self::$displayErrors) {
64450 self::$displayErrors = ini_set('display_errors', 1);
64451 }
64452 }
64453
64454 public function __destruct()
64455 {
64456 if (null !== self::$displayErrors) {
64457 ini_set('display_errors', self::$displayErrors);
64458 self::$displayErrors = null;
64459 }
64460 }
64461 }
64462 <?php
64463
64464
64465
64466
64467
64468
64469
64470
64471
64472
64473 namespace Symfony\Component\Debug\Exception;
64474
64475
64476
64477
64478
64479
64480 class ClassNotFoundException extends FatalErrorException
64481 {
64482 public function __construct($message, \ErrorException $previous)
64483 {
64484 parent::__construct(
64485 $message,
64486 $previous->getCode(),
64487 $previous->getSeverity(),
64488 $previous->getFile(),
64489 $previous->getLine(),
64490 null,
64491 true,
64492 null,
64493 $previous->getPrevious()
64494 );
64495 $this->setTrace($previous->getTrace());
64496 }
64497 }
64498 <?php
64499
64500
64501
64502
64503
64504
64505
64506
64507
64508
64509 namespace Symfony\Component\Debug\Exception;
64510
64511
64512
64513
64514
64515
64516 class ContextErrorException extends \ErrorException
64517 {
64518 private $context = array();
64519
64520 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
64521 {
64522 parent::__construct($message, $code, $severity, $filename, $lineno);
64523 $this->context = $context;
64524 }
64525
64526
64527
64528
64529 public function getContext()
64530 {
64531 return $this->context;
64532 }
64533 }
64534 <?php
64535
64536
64537
64538
64539
64540
64541
64542
64543
64544
64545 namespace Symfony\Component\Debug\Exception;
64546
64547 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
64548
64549
64550
64551
64552
64553
64554 class DummyException extends \ErrorException
64555 {
64556 }
64557 <?php
64558
64559
64560
64561
64562
64563
64564
64565
64566
64567
64568 namespace Symfony\Component\HttpKernel\Exception;
64569
64570
64571
64572
64573
64574
64575
64576
64577
64578
64579 class FatalErrorException extends \ErrorException
64580 {
64581 }
64582
64583 namespace Symfony\Component\Debug\Exception;
64584
64585 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
64586
64587
64588
64589
64590
64591
64592 class FatalErrorException extends LegacyFatalErrorException
64593 {
64594 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null, $previous = null)
64595 {
64596 parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
64597
64598 if (null !== $trace) {
64599 if (!$traceArgs) {
64600 foreach ($trace as &$frame) {
64601 unset($frame['args'], $frame['this'], $frame);
64602 }
64603 }
64604
64605 $this->setTrace($trace);
64606 } elseif (null !== $traceOffset) {
64607 if (\function_exists('xdebug_get_function_stack')) {
64608 $trace = xdebug_get_function_stack();
64609 if (0 < $traceOffset) {
64610 array_splice($trace, -$traceOffset);
64611 }
64612
64613 foreach ($trace as &$frame) {
64614 if (!isset($frame['type'])) {
64615
64616  if (isset($frame['class'])) {
64617 $frame['type'] = '::';
64618 }
64619 } elseif ('dynamic' === $frame['type']) {
64620 $frame['type'] = '->';
64621 } elseif ('static' === $frame['type']) {
64622 $frame['type'] = '::';
64623 }
64624
64625
64626  if (!$traceArgs) {
64627 unset($frame['params'], $frame['args']);
64628 } elseif (isset($frame['params']) && !isset($frame['args'])) {
64629 $frame['args'] = $frame['params'];
64630 unset($frame['params']);
64631 }
64632 }
64633
64634 unset($frame);
64635 $trace = array_reverse($trace);
64636 } elseif (\function_exists('symfony_debug_backtrace')) {
64637 $trace = symfony_debug_backtrace();
64638 if (0 < $traceOffset) {
64639 array_splice($trace, 0, $traceOffset);
64640 }
64641 } else {
64642 $trace = array();
64643 }
64644
64645 $this->setTrace($trace);
64646 }
64647 }
64648
64649 protected function setTrace($trace)
64650 {
64651 $traceReflector = new \ReflectionProperty('Exception', 'trace');
64652 $traceReflector->setAccessible(true);
64653 $traceReflector->setValue($this, $trace);
64654 }
64655 }
64656 <?php
64657
64658
64659
64660
64661
64662
64663
64664
64665
64666
64667 namespace Symfony\Component\Debug\Exception;
64668
64669
64670
64671
64672
64673
64674 class FatalThrowableError extends FatalErrorException
64675 {
64676 public function __construct(\Throwable $e)
64677 {
64678 if ($e instanceof \ParseError) {
64679 $message = 'Parse error: '.$e->getMessage();
64680 $severity = E_PARSE;
64681 } elseif ($e instanceof \TypeError) {
64682 $message = 'Type error: '.$e->getMessage();
64683 $severity = E_RECOVERABLE_ERROR;
64684 } else {
64685 $message = $e->getMessage();
64686 $severity = E_ERROR;
64687 }
64688
64689 \ErrorException::__construct(
64690 $message,
64691 $e->getCode(),
64692 $severity,
64693 $e->getFile(),
64694 $e->getLine(),
64695 $e->getPrevious()
64696 );
64697
64698 $this->setTrace($e->getTrace());
64699 }
64700 }
64701 <?php
64702
64703
64704
64705
64706
64707
64708
64709
64710
64711
64712 namespace Symfony\Component\HttpKernel\Exception;
64713
64714 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
64715
64716
64717
64718
64719
64720
64721
64722
64723
64724
64725 class FlattenException
64726 {
64727 private $handler;
64728
64729 public static function __callStatic($method, $args)
64730 {
64731 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
64732 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_called_class(), $method));
64733 }
64734
64735 return \call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
64736 }
64737
64738 public function __call($method, $args)
64739 {
64740 if (!isset($this->handler)) {
64741 $this->handler = new DebugFlattenException();
64742 }
64743
64744 if (!method_exists($this->handler, $method)) {
64745 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_class($this), $method));
64746 }
64747
64748 return \call_user_func_array(array($this->handler, $method), $args);
64749 }
64750 }
64751
64752 namespace Symfony\Component\Debug\Exception;
64753
64754 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
64755 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
64756
64757
64758
64759
64760
64761
64762
64763
64764 class FlattenException extends LegacyFlattenException
64765 {
64766 private $message;
64767 private $code;
64768 private $previous;
64769 private $trace;
64770 private $class;
64771 private $statusCode;
64772 private $headers;
64773 private $file;
64774 private $line;
64775
64776 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
64777 {
64778 $e = new static();
64779 $e->setMessage($exception->getMessage());
64780 $e->setCode($exception->getCode());
64781
64782 if ($exception instanceof HttpExceptionInterface) {
64783 $statusCode = $exception->getStatusCode();
64784 $headers = array_merge($headers, $exception->getHeaders());
64785 }
64786
64787 if (null === $statusCode) {
64788 $statusCode = 500;
64789 }
64790
64791 $e->setStatusCode($statusCode);
64792 $e->setHeaders($headers);
64793 $e->setTraceFromException($exception);
64794 $e->setClass(\get_class($exception));
64795 $e->setFile($exception->getFile());
64796 $e->setLine($exception->getLine());
64797
64798 $previous = $exception->getPrevious();
64799
64800 if ($previous instanceof \Exception) {
64801 $e->setPrevious(static::create($previous));
64802 } elseif ($previous instanceof \Throwable) {
64803 $e->setPrevious(static::create(new FatalThrowableError($previous)));
64804 }
64805
64806 return $e;
64807 }
64808
64809 public function toArray()
64810 {
64811 $exceptions = array();
64812 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
64813 $exceptions[] = array(
64814 'message' => $exception->getMessage(),
64815 'class' => $exception->getClass(),
64816 'trace' => $exception->getTrace(),
64817 );
64818 }
64819
64820 return $exceptions;
64821 }
64822
64823 public function getStatusCode()
64824 {
64825 return $this->statusCode;
64826 }
64827
64828 public function setStatusCode($code)
64829 {
64830 $this->statusCode = $code;
64831 }
64832
64833 public function getHeaders()
64834 {
64835 return $this->headers;
64836 }
64837
64838 public function setHeaders(array $headers)
64839 {
64840 $this->headers = $headers;
64841 }
64842
64843 public function getClass()
64844 {
64845 return $this->class;
64846 }
64847
64848 public function setClass($class)
64849 {
64850 $this->class = $class;
64851 }
64852
64853 public function getFile()
64854 {
64855 return $this->file;
64856 }
64857
64858 public function setFile($file)
64859 {
64860 $this->file = $file;
64861 }
64862
64863 public function getLine()
64864 {
64865 return $this->line;
64866 }
64867
64868 public function setLine($line)
64869 {
64870 $this->line = $line;
64871 }
64872
64873 public function getMessage()
64874 {
64875 return $this->message;
64876 }
64877
64878 public function setMessage($message)
64879 {
64880 $this->message = $message;
64881 }
64882
64883 public function getCode()
64884 {
64885 return $this->code;
64886 }
64887
64888 public function setCode($code)
64889 {
64890 $this->code = $code;
64891 }
64892
64893 public function getPrevious()
64894 {
64895 return $this->previous;
64896 }
64897
64898 public function setPrevious(FlattenException $previous)
64899 {
64900 $this->previous = $previous;
64901 }
64902
64903 public function getAllPrevious()
64904 {
64905 $exceptions = array();
64906 $e = $this;
64907 while ($e = $e->getPrevious()) {
64908 $exceptions[] = $e;
64909 }
64910
64911 return $exceptions;
64912 }
64913
64914 public function getTrace()
64915 {
64916 return $this->trace;
64917 }
64918
64919 public function setTraceFromException(\Exception $exception)
64920 {
64921 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
64922 }
64923
64924 public function setTrace($trace, $file, $line)
64925 {
64926 $this->trace = array();
64927 $this->trace[] = array(
64928 'namespace' => '',
64929 'short_class' => '',
64930 'class' => '',
64931 'type' => '',
64932 'function' => '',
64933 'file' => $file,
64934 'line' => $line,
64935 'args' => array(),
64936 );
64937 foreach ($trace as $entry) {
64938 $class = '';
64939 $namespace = '';
64940 if (isset($entry['class'])) {
64941 $parts = explode('\\', $entry['class']);
64942 $class = array_pop($parts);
64943 $namespace = implode('\\', $parts);
64944 }
64945
64946 $this->trace[] = array(
64947 'namespace' => $namespace,
64948 'short_class' => $class,
64949 'class' => isset($entry['class']) ? $entry['class'] : '',
64950 'type' => isset($entry['type']) ? $entry['type'] : '',
64951 'function' => isset($entry['function']) ? $entry['function'] : null,
64952 'file' => isset($entry['file']) ? $entry['file'] : null,
64953 'line' => isset($entry['line']) ? $entry['line'] : null,
64954 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
64955 );
64956 }
64957 }
64958
64959 private function flattenArgs($args, $level = 0, &$count = 0)
64960 {
64961 $result = array();
64962 foreach ($args as $key => $value) {
64963 if (++$count > 1e4) {
64964 return array('array', '*SKIPPED over 10000 entries*');
64965 }
64966 if ($value instanceof \__PHP_Incomplete_Class) {
64967
64968  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
64969 } elseif (\is_object($value)) {
64970 $result[$key] = array('object', \get_class($value));
64971 } elseif (\is_array($value)) {
64972 if ($level > 10) {
64973 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
64974 } else {
64975 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
64976 }
64977 } elseif (null === $value) {
64978 $result[$key] = array('null', null);
64979 } elseif (\is_bool($value)) {
64980 $result[$key] = array('boolean', $value);
64981 } elseif (\is_resource($value)) {
64982 $result[$key] = array('resource', get_resource_type($value));
64983 } else {
64984 $result[$key] = array('string', (string) $value);
64985 }
64986 }
64987
64988 return $result;
64989 }
64990
64991 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
64992 {
64993 $array = new \ArrayObject($value);
64994
64995 return $array['__PHP_Incomplete_Class_Name'];
64996 }
64997 }
64998 <?php
64999
65000
65001
65002
65003
65004
65005
65006
65007
65008
65009 namespace Symfony\Component\Debug\Exception;
65010
65011
65012
65013
65014
65015
65016 class OutOfMemoryException extends FatalErrorException
65017 {
65018 }
65019 <?php
65020
65021
65022
65023
65024
65025
65026
65027
65028
65029
65030 namespace Symfony\Component\Debug\Exception;
65031
65032
65033
65034
65035
65036
65037 class UndefinedFunctionException extends FatalErrorException
65038 {
65039 public function __construct($message, \ErrorException $previous)
65040 {
65041 parent::__construct(
65042 $message,
65043 $previous->getCode(),
65044 $previous->getSeverity(),
65045 $previous->getFile(),
65046 $previous->getLine(),
65047 null,
65048 true,
65049 null,
65050 $previous->getPrevious()
65051 );
65052 $this->setTrace($previous->getTrace());
65053 }
65054 }
65055 <?php
65056
65057
65058
65059
65060
65061
65062
65063
65064
65065
65066 namespace Symfony\Component\Debug\Exception;
65067
65068
65069
65070
65071
65072
65073 class UndefinedMethodException extends FatalErrorException
65074 {
65075 public function __construct($message, \ErrorException $previous)
65076 {
65077 parent::__construct(
65078 $message,
65079 $previous->getCode(),
65080 $previous->getSeverity(),
65081 $previous->getFile(),
65082 $previous->getLine(),
65083 null,
65084 true,
65085 null,
65086 $previous->getPrevious()
65087 );
65088 $this->setTrace($previous->getTrace());
65089 }
65090 }
65091 <?php
65092
65093
65094
65095
65096
65097
65098
65099
65100
65101
65102 namespace Symfony\Component\Debug;
65103
65104 use Symfony\Component\Debug\Exception\FlattenException;
65105 use Symfony\Component\Debug\Exception\OutOfMemoryException;
65106 use Symfony\Component\HttpFoundation\Response;
65107
65108
65109
65110
65111
65112
65113
65114
65115
65116
65117
65118
65119
65120 class ExceptionHandler
65121 {
65122 private $debug;
65123 private $charset;
65124 private $handler;
65125 private $caughtBuffer;
65126 private $caughtLength;
65127 private $fileLinkFormat;
65128
65129 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
65130 {
65131 if (false !== strpos($charset, '%')) {
65132 @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);
65133
65134
65135  $pivot = $fileLinkFormat;
65136 $fileLinkFormat = $charset;
65137 $charset = $pivot;
65138 }
65139 $this->debug = $debug;
65140 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
65141 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
65142 }
65143
65144
65145
65146
65147
65148
65149
65150
65151
65152
65153 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
65154 {
65155 $handler = new static($debug, $charset, $fileLinkFormat);
65156
65157 $prev = set_exception_handler(array($handler, 'handle'));
65158 if (\is_array($prev) && $prev[0] instanceof ErrorHandler) {
65159 restore_exception_handler();
65160 $prev[0]->setExceptionHandler(array($handler, 'handle'));
65161 }
65162
65163 return $handler;
65164 }
65165
65166
65167
65168
65169
65170
65171
65172
65173 public function setHandler($handler)
65174 {
65175 if (null !== $handler && !\is_callable($handler)) {
65176 throw new \LogicException('The exception handler must be a valid PHP callable.');
65177 }
65178 $old = $this->handler;
65179 $this->handler = $handler;
65180
65181 return $old;
65182 }
65183
65184
65185
65186
65187
65188
65189
65190
65191 public function setFileLinkFormat($format)
65192 {
65193 $old = $this->fileLinkFormat;
65194 $this->fileLinkFormat = $format;
65195
65196 return $old;
65197 }
65198
65199
65200
65201
65202
65203
65204
65205
65206
65207 public function handle(\Exception $exception)
65208 {
65209 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
65210 $this->failSafeHandle($exception);
65211
65212 return;
65213 }
65214
65215 $caughtLength = $this->caughtLength = 0;
65216
65217 ob_start(array($this, 'catchOutput'));
65218 $this->failSafeHandle($exception);
65219 while (null === $this->caughtBuffer && ob_end_flush()) {
65220
65221  }
65222 if (isset($this->caughtBuffer[0])) {
65223 ob_start(array($this, 'cleanOutput'));
65224 echo $this->caughtBuffer;
65225 $caughtLength = ob_get_length();
65226 }
65227 $this->caughtBuffer = null;
65228
65229 try {
65230 \call_user_func($this->handler, $exception);
65231 $this->caughtLength = $caughtLength;
65232 } catch (\Exception $e) {
65233 if (!$caughtLength) {
65234
65235  throw $exception;
65236 }
65237 }
65238 }
65239
65240
65241
65242
65243
65244
65245
65246
65247 private function failSafeHandle(\Exception $exception)
65248 {
65249 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
65250 && __CLASS__ !== \get_class($this)
65251 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
65252 && __CLASS__ !== $reflector->class
65253 ) {
65254 $response = $this->createResponse($exception);
65255 $response->sendHeaders();
65256 $response->sendContent();
65257 @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);
65258
65259 return;
65260 }
65261
65262 $this->sendPhpResponse($exception);
65263 }
65264
65265
65266
65267
65268
65269
65270
65271
65272
65273 public function sendPhpResponse($exception)
65274 {
65275 if (!$exception instanceof FlattenException) {
65276 $exception = FlattenException::create($exception);
65277 }
65278
65279 if (!headers_sent()) {
65280 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
65281 foreach ($exception->getHeaders() as $name => $value) {
65282 header($name.': '.$value, false);
65283 }
65284 header('Content-Type: text/html; charset='.$this->charset);
65285 }
65286
65287 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
65288 }
65289
65290
65291
65292
65293
65294
65295
65296
65297
65298
65299 public function createResponse($exception)
65300 {
65301 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65302
65303 if (!$exception instanceof FlattenException) {
65304 $exception = FlattenException::create($exception);
65305 }
65306
65307 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
65308 }
65309
65310
65311
65312
65313
65314
65315
65316
65317 public function getHtml($exception)
65318 {
65319 if (!$exception instanceof FlattenException) {
65320 $exception = FlattenException::create($exception);
65321 }
65322
65323 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
65324 }
65325
65326
65327
65328
65329
65330
65331 public function getContent(FlattenException $exception)
65332 {
65333 switch ($exception->getStatusCode()) {
65334 case 404:
65335 $title = 'Sorry, the page you are looking for could not be found.';
65336 break;
65337 default:
65338 $title = 'Whoops, looks like something went wrong.';
65339 }
65340
65341 $content = '';
65342 if ($this->debug) {
65343 try {
65344 $count = \count($exception->getAllPrevious());
65345 $total = $count + 1;
65346 foreach ($exception->toArray() as $position => $e) {
65347 $ind = $count - $position + 1;
65348 $class = $this->formatClass($e['class']);
65349 $message = nl2br($this->escapeHtml($e['message']));
65350 $content .= sprintf(<<<'EOF'
65351                         <h2 class="block_exception clear_fix">
65352                             <span class="exception_counter">%d/%d</span>
65353                             <span class="exception_title">%s%s:</span>
65354                             <span class="exception_message">%s</span>
65355                         </h2>
65356                         <div class="block">
65357                             <ol class="traces list_exception">
65358
65359 EOF
65360 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
65361 foreach ($e['trace'] as $trace) {
65362 $content .= '       <li>';
65363 if ($trace['function']) {
65364 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
65365 }
65366 if (isset($trace['file']) && isset($trace['line'])) {
65367 $content .= $this->formatPath($trace['file'], $trace['line']);
65368 }
65369 $content .= "</li>\n";
65370 }
65371
65372 $content .= "    </ol>\n</div>\n";
65373 }
65374 } catch (\Exception $e) {
65375
65376  if ($this->debug) {
65377 $title = sprintf('Exception thrown when handling an exception (%s: %s)', \get_class($e), $this->escapeHtml($e->getMessage()));
65378 } else {
65379 $title = 'Whoops, looks like something went wrong.';
65380 }
65381 }
65382 }
65383
65384 return <<<EOF
65385             <div id="sf-resetcontent" class="sf-reset">
65386                 <h1>$title</h1>
65387                 $content
65388             </div>
65389 EOF;
65390 }
65391
65392
65393
65394
65395
65396
65397 public function getStylesheet(FlattenException $exception)
65398 {
65399 return <<<'EOF'
65400             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
65401             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
65402             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
65403             .sf-reset .clear_fix { display:inline-block; }
65404             .sf-reset * html .clear_fix { height:1%; }
65405             .sf-reset .clear_fix { display:block; }
65406             .sf-reset, .sf-reset .block { margin: auto }
65407             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
65408             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
65409             .sf-reset strong { font-weight:bold; }
65410             .sf-reset a { color:#6c6159; cursor: default; }
65411             .sf-reset a img { border:none; }
65412             .sf-reset a:hover { text-decoration:underline; }
65413             .sf-reset em { font-style:italic; }
65414             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
65415             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
65416             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
65417             .sf-reset .exception_message { margin-left: 3em; display: block; }
65418             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
65419             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
65420                 -webkit-border-bottom-right-radius: 16px;
65421                 -webkit-border-bottom-left-radius: 16px;
65422                 -moz-border-radius-bottomright: 16px;
65423                 -moz-border-radius-bottomleft: 16px;
65424                 border-bottom-right-radius: 16px;
65425                 border-bottom-left-radius: 16px;
65426                 border-bottom:1px solid #ccc;
65427                 border-right:1px solid #ccc;
65428                 border-left:1px solid #ccc;
65429                 word-wrap: break-word;
65430             }
65431             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
65432                 -webkit-border-top-left-radius: 16px;
65433                 -webkit-border-top-right-radius: 16px;
65434                 -moz-border-radius-topleft: 16px;
65435                 -moz-border-radius-topright: 16px;
65436                 border-top-left-radius: 16px;
65437                 border-top-right-radius: 16px;
65438                 border-top:1px solid #ccc;
65439                 border-right:1px solid #ccc;
65440                 border-left:1px solid #ccc;
65441                 overflow: hidden;
65442                 word-wrap: break-word;
65443             }
65444             .sf-reset a { background:none; color:#868686; text-decoration:none; }
65445             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
65446             .sf-reset ol { padding: 10px 0; }
65447             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
65448                 -webkit-border-radius: 10px;
65449                 -moz-border-radius: 10px;
65450                 border-radius: 10px;
65451                 border: 1px solid #ccc;
65452             }
65453 EOF;
65454 }
65455
65456 private function decorate($content, $css)
65457 {
65458 return <<<EOF
65459 <!DOCTYPE html>
65460 <html>
65461     <head>
65462         <meta charset="{$this->charset}" />
65463         <meta name="robots" content="noindex,nofollow" />
65464         <style>
65465             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
65466             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;}
65467
65468             html { background: #eee; padding: 10px }
65469             img { border: 0; }
65470             #sf-resetcontent { width:970px; margin:0 auto; }
65471             $css
65472         </style>
65473     </head>
65474     <body>
65475         $content
65476     </body>
65477 </html>
65478 EOF;
65479 }
65480
65481 private function formatClass($class)
65482 {
65483 $parts = explode('\\', $class);
65484
65485 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
65486 }
65487
65488 private function formatPath($path, $line)
65489 {
65490 $path = $this->escapeHtml($path);
65491 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
65492
65493 if ($linkFormat = $this->fileLinkFormat) {
65494 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
65495
65496 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
65497 }
65498
65499 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);
65500 }
65501
65502
65503
65504
65505
65506
65507
65508
65509 private function formatArgs(array $args)
65510 {
65511 $result = array();
65512 foreach ($args as $key => $item) {
65513 if ('object' === $item[0]) {
65514 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
65515 } elseif ('array' === $item[0]) {
65516 $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
65517 } elseif ('string' === $item[0]) {
65518 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
65519 } elseif ('null' === $item[0]) {
65520 $formattedValue = '<em>null</em>';
65521 } elseif ('boolean' === $item[0]) {
65522 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
65523 } elseif ('resource' === $item[0]) {
65524 $formattedValue = '<em>resource</em>';
65525 } else {
65526 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
65527 }
65528
65529 $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
65530 }
65531
65532 return implode(', ', $result);
65533 }
65534
65535
65536
65537
65538
65539
65540 protected static function utf8Htmlize($str)
65541 {
65542 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
65543
65544 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
65545 }
65546
65547
65548
65549
65550 private function escapeHtml($str)
65551 {
65552 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
65553 }
65554
65555
65556
65557
65558 public function catchOutput($buffer)
65559 {
65560 $this->caughtBuffer = $buffer;
65561
65562 return '';
65563 }
65564
65565
65566
65567
65568 public function cleanOutput($buffer)
65569 {
65570 if ($this->caughtLength) {
65571
65572  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
65573 if (isset($cleanBuffer[0])) {
65574 $buffer = $cleanBuffer;
65575 }
65576 }
65577
65578 return $buffer;
65579 }
65580 }
65581 <?php
65582
65583
65584
65585
65586
65587
65588
65589
65590
65591
65592 namespace Symfony\Component\Debug\FatalErrorHandler;
65593
65594 use Composer\Autoload\ClassLoader as ComposerClassLoader;
65595 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
65596 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
65597 use Symfony\Component\Debug\DebugClassLoader;
65598 use Symfony\Component\Debug\Exception\ClassNotFoundException;
65599 use Symfony\Component\Debug\Exception\FatalErrorException;
65600
65601
65602
65603
65604
65605
65606 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
65607 {
65608
65609
65610
65611 public function handleError(array $error, FatalErrorException $exception)
65612 {
65613 $messageLen = \strlen($error['message']);
65614 $notFoundSuffix = '\' not found';
65615 $notFoundSuffixLen = \strlen($notFoundSuffix);
65616 if ($notFoundSuffixLen > $messageLen) {
65617 return;
65618 }
65619
65620 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
65621 return;
65622 }
65623
65624 foreach (array('class', 'interface', 'trait') as $typeName) {
65625 $prefix = ucfirst($typeName).' \'';
65626 $prefixLen = \strlen($prefix);
65627 if (0 !== strpos($error['message'], $prefix)) {
65628 continue;
65629 }
65630
65631 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
65632 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
65633 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
65634 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
65635 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
65636 $tail = ' for another namespace?';
65637 } else {
65638 $className = $fullyQualifiedClassName;
65639 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
65640 $tail = '?';
65641 }
65642
65643 if ($candidates = $this->getClassCandidates($className)) {
65644 $tail = array_pop($candidates).'"?';
65645 if ($candidates) {
65646 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
65647 } else {
65648 $tail = ' for "'.$tail;
65649 }
65650 }
65651 $message .= "\nDid you forget a \"use\" statement".$tail;
65652
65653 return new ClassNotFoundException($message, $exception);
65654 }
65655 }
65656
65657
65658
65659
65660
65661
65662
65663
65664
65665
65666
65667 private function getClassCandidates($class)
65668 {
65669 if (!\is_array($functions = spl_autoload_functions())) {
65670 return array();
65671 }
65672
65673
65674  $classes = array();
65675
65676 foreach ($functions as $function) {
65677 if (!\is_array($function)) {
65678 continue;
65679 }
65680
65681  if ($function[0] instanceof DebugClassLoader) {
65682 $function = $function[0]->getClassLoader();
65683
65684
65685  if (\is_object($function)) {
65686 $function = array($function);
65687 }
65688
65689 if (!\is_array($function)) {
65690 continue;
65691 }
65692 }
65693
65694 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
65695 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
65696 foreach ($paths as $path) {
65697 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
65698 }
65699 }
65700 }
65701 if ($function[0] instanceof ComposerClassLoader) {
65702 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
65703 foreach ($paths as $path) {
65704 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
65705 }
65706 }
65707 }
65708 }
65709
65710 return array_unique($classes);
65711 }
65712
65713
65714
65715
65716
65717
65718
65719
65720 private function findClassInPath($path, $class, $prefix)
65721 {
65722 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
65723 return array();
65724 }
65725
65726 $classes = array();
65727 $filename = $class.'.php';
65728 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
65729 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
65730 $classes[] = $class;
65731 }
65732 }
65733
65734 return $classes;
65735 }
65736
65737
65738
65739
65740
65741
65742
65743
65744 private function convertFileToClass($path, $file, $prefix)
65745 {
65746 $candidates = array(
65747
65748  $namespacedClass = str_replace(array($path.\DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
65749
65750  $prefix.$namespacedClass,
65751
65752  $prefix.'\\'.$namespacedClass,
65753
65754  str_replace('\\', '_', $namespacedClass),
65755
65756  str_replace('\\', '_', $prefix.$namespacedClass),
65757
65758  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
65759 );
65760
65761 if ($prefix) {
65762 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
65763 }
65764
65765
65766  
65767  
65768  foreach ($candidates as $candidate) {
65769 if ($this->classExists($candidate)) {
65770 return $candidate;
65771 }
65772 }
65773
65774 require_once $file;
65775
65776 foreach ($candidates as $candidate) {
65777 if ($this->classExists($candidate)) {
65778 return $candidate;
65779 }
65780 }
65781 }
65782
65783
65784
65785
65786
65787
65788 private function classExists($class)
65789 {
65790 return class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
65791 }
65792 }
65793 <?php
65794
65795
65796
65797
65798
65799
65800
65801
65802
65803
65804 namespace Symfony\Component\Debug\FatalErrorHandler;
65805
65806 use Symfony\Component\Debug\Exception\FatalErrorException;
65807
65808
65809
65810
65811
65812
65813 interface FatalErrorHandlerInterface
65814 {
65815
65816
65817
65818
65819
65820
65821
65822
65823 public function handleError(array $error, FatalErrorException $exception);
65824 }
65825 <?php
65826
65827
65828
65829
65830
65831
65832
65833
65834
65835
65836 namespace Symfony\Component\Debug\FatalErrorHandler;
65837
65838 use Symfony\Component\Debug\Exception\FatalErrorException;
65839 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
65840
65841
65842
65843
65844
65845
65846 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
65847 {
65848
65849
65850
65851 public function handleError(array $error, FatalErrorException $exception)
65852 {
65853 $messageLen = \strlen($error['message']);
65854 $notFoundSuffix = '()';
65855 $notFoundSuffixLen = \strlen($notFoundSuffix);
65856 if ($notFoundSuffixLen > $messageLen) {
65857 return;
65858 }
65859
65860 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
65861 return;
65862 }
65863
65864 $prefix = 'Call to undefined function ';
65865 $prefixLen = \strlen($prefix);
65866 if (0 !== strpos($error['message'], $prefix)) {
65867 return;
65868 }
65869
65870 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
65871 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
65872 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
65873 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
65874 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
65875 } else {
65876 $functionName = $fullyQualifiedFunctionName;
65877 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
65878 }
65879
65880 $candidates = array();
65881 foreach (get_defined_functions() as $type => $definedFunctionNames) {
65882 foreach ($definedFunctionNames as $definedFunctionName) {
65883 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
65884 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
65885 } else {
65886 $definedFunctionNameBasename = $definedFunctionName;
65887 }
65888
65889 if ($definedFunctionNameBasename === $functionName) {
65890 $candidates[] = '\\'.$definedFunctionName;
65891 }
65892 }
65893 }
65894
65895 if ($candidates) {
65896 sort($candidates);
65897 $last = array_pop($candidates).'"?';
65898 if ($candidates) {
65899 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
65900 } else {
65901 $candidates = '"'.$last;
65902 }
65903 $message .= "\nDid you mean to call ".$candidates;
65904 }
65905
65906 return new UndefinedFunctionException($message, $exception);
65907 }
65908 }
65909 <?php
65910
65911
65912
65913
65914
65915
65916
65917
65918
65919
65920 namespace Symfony\Component\Debug\FatalErrorHandler;
65921
65922 use Symfony\Component\Debug\Exception\FatalErrorException;
65923 use Symfony\Component\Debug\Exception\UndefinedMethodException;
65924
65925
65926
65927
65928
65929
65930 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
65931 {
65932
65933
65934
65935 public function handleError(array $error, FatalErrorException $exception)
65936 {
65937 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
65938 if (!$matches) {
65939 return;
65940 }
65941
65942 $className = $matches[1];
65943 $methodName = $matches[2];
65944
65945 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
65946
65947 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
65948
65949  return new UndefinedMethodException($message, $exception);
65950 }
65951
65952 $candidates = array();
65953 foreach ($methods as $definedMethodName) {
65954 $lev = levenshtein($methodName, $definedMethodName);
65955 if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
65956 $candidates[] = $definedMethodName;
65957 }
65958 }
65959
65960 if ($candidates) {
65961 sort($candidates);
65962 $last = array_pop($candidates).'"?';
65963 if ($candidates) {
65964 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
65965 } else {
65966 $candidates = '"'.$last;
65967 }
65968
65969 $message .= "\nDid you mean to call ".$candidates;
65970 }
65971
65972 return new UndefinedMethodException($message, $exception);
65973 }
65974 }
65975 Copyright (c) 2004-2018 Fabien Potencier
65976
65977 Permission is hereby granted, free of charge, to any person obtaining a copy
65978 of this software and associated documentation files (the "Software"), to deal
65979 in the Software without restriction, including without limitation the rights
65980 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
65981 copies of the Software, and to permit persons to whom the Software is furnished
65982 to do so, subject to the following conditions:
65983
65984 The above copyright notice and this permission notice shall be included in all
65985 copies or substantial portions of the Software.
65986
65987 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
65988 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65989 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65990 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
65991 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65992 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
65993 THE SOFTWARE.
65994 <?php
65995
65996
65997
65998
65999
66000
66001
66002
66003
66004
66005 namespace Symfony\Component\Filesystem\Exception;
66006
66007
66008
66009
66010
66011
66012 interface ExceptionInterface
66013 {
66014 }
66015 <?php
66016
66017
66018
66019
66020
66021
66022
66023
66024
66025
66026 namespace Symfony\Component\Filesystem\Exception;
66027
66028
66029
66030
66031
66032
66033
66034 class FileNotFoundException extends IOException
66035 {
66036 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
66037 {
66038 if (null === $message) {
66039 if (null === $path) {
66040 $message = 'File could not be found.';
66041 } else {
66042 $message = sprintf('File "%s" could not be found.', $path);
66043 }
66044 }
66045
66046 parent::__construct($message, $code, $previous, $path);
66047 }
66048 }
66049 <?php
66050
66051
66052
66053
66054
66055
66056
66057
66058
66059
66060 namespace Symfony\Component\Filesystem\Exception;
66061
66062
66063
66064
66065
66066
66067
66068
66069 class IOException extends \RuntimeException implements IOExceptionInterface
66070 {
66071 private $path;
66072
66073 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
66074 {
66075 $this->path = $path;
66076
66077 parent::__construct($message, $code, $previous);
66078 }
66079
66080
66081
66082
66083 public function getPath()
66084 {
66085 return $this->path;
66086 }
66087 }
66088 <?php
66089
66090
66091
66092
66093
66094
66095
66096
66097
66098
66099 namespace Symfony\Component\Filesystem\Exception;
66100
66101
66102
66103
66104
66105
66106 interface IOExceptionInterface extends ExceptionInterface
66107 {
66108
66109
66110
66111
66112
66113 public function getPath();
66114 }
66115 <?php
66116
66117
66118
66119
66120
66121
66122
66123
66124
66125
66126 namespace Symfony\Component\Filesystem;
66127
66128 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
66129 use Symfony\Component\Filesystem\Exception\IOException;
66130
66131
66132
66133
66134
66135
66136 class Filesystem
66137 {
66138 private static $lastError;
66139
66140
66141
66142
66143
66144
66145
66146
66147
66148
66149
66150
66151
66152
66153
66154 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
66155 {
66156 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
66157 if ($originIsLocal && !is_file($originFile)) {
66158 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
66159 }
66160
66161 $this->mkdir(\dirname($targetFile));
66162
66163 $doCopy = true;
66164 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
66165 $doCopy = filemtime($originFile) > filemtime($targetFile);
66166 }
66167
66168 if ($doCopy) {
66169
66170  if (false === $source = @fopen($originFile, 'r')) {
66171 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
66172 }
66173
66174
66175  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
66176 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
66177 }
66178
66179 $bytesCopied = stream_copy_to_stream($source, $target);
66180 fclose($source);
66181 fclose($target);
66182 unset($source, $target);
66183
66184 if (!is_file($targetFile)) {
66185 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
66186 }
66187
66188 if ($originIsLocal) {
66189
66190  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
66191
66192 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
66193 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);
66194 }
66195 }
66196 }
66197 }
66198
66199
66200
66201
66202
66203
66204
66205
66206
66207 public function mkdir($dirs, $mode = 0777)
66208 {
66209 foreach ($this->toIterator($dirs) as $dir) {
66210 if (is_dir($dir)) {
66211 continue;
66212 }
66213
66214 if (!self::box('mkdir', $dir, $mode, true)) {
66215 if (!is_dir($dir)) {
66216
66217  if (self::$lastError) {
66218 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
66219 }
66220 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
66221 }
66222 }
66223 }
66224 }
66225
66226
66227
66228
66229
66230
66231
66232
66233 public function exists($files)
66234 {
66235 $maxPathLength = PHP_MAXPATHLEN - 2;
66236
66237 foreach ($this->toIterator($files) as $file) {
66238 if (\strlen($file) > $maxPathLength) {
66239 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
66240 }
66241
66242 if (!file_exists($file)) {
66243 return false;
66244 }
66245 }
66246
66247 return true;
66248 }
66249
66250
66251
66252
66253
66254
66255
66256
66257
66258
66259 public function touch($files, $time = null, $atime = null)
66260 {
66261 foreach ($this->toIterator($files) as $file) {
66262 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
66263 if (true !== $touch) {
66264 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
66265 }
66266 }
66267 }
66268
66269
66270
66271
66272
66273
66274
66275
66276 public function remove($files)
66277 {
66278 if ($files instanceof \Traversable) {
66279 $files = iterator_to_array($files, false);
66280 } elseif (!\is_array($files)) {
66281 $files = array($files);
66282 }
66283 $files = array_reverse($files);
66284 foreach ($files as $file) {
66285 if (is_link($file)) {
66286
66287  if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
66288 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
66289 }
66290 } elseif (is_dir($file)) {
66291 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
66292
66293 if (!self::box('rmdir', $file) && file_exists($file)) {
66294 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
66295 }
66296 } elseif (!self::box('unlink', $file) && file_exists($file)) {
66297 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
66298 }
66299 }
66300 }
66301
66302
66303
66304
66305
66306
66307
66308
66309
66310
66311
66312 public function chmod($files, $mode, $umask = 0000, $recursive = false)
66313 {
66314 foreach ($this->toIterator($files) as $file) {
66315 if (true !== @chmod($file, $mode & ~$umask)) {
66316 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
66317 }
66318 if ($recursive && is_dir($file) && !is_link($file)) {
66319 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
66320 }
66321 }
66322 }
66323
66324
66325
66326
66327
66328
66329
66330
66331
66332
66333 public function chown($files, $user, $recursive = false)
66334 {
66335 foreach ($this->toIterator($files) as $file) {
66336 if ($recursive && is_dir($file) && !is_link($file)) {
66337 $this->chown(new \FilesystemIterator($file), $user, true);
66338 }
66339 if (is_link($file) && \function_exists('lchown')) {
66340 if (true !== @lchown($file, $user)) {
66341 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
66342 }
66343 } else {
66344 if (true !== @chown($file, $user)) {
66345 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
66346 }
66347 }
66348 }
66349 }
66350
66351
66352
66353
66354
66355
66356
66357
66358
66359
66360 public function chgrp($files, $group, $recursive = false)
66361 {
66362 foreach ($this->toIterator($files) as $file) {
66363 if ($recursive && is_dir($file) && !is_link($file)) {
66364 $this->chgrp(new \FilesystemIterator($file), $group, true);
66365 }
66366 if (is_link($file) && \function_exists('lchgrp')) {
66367 if (true !== @lchgrp($file, $group) || (\defined('HHVM_VERSION') && !posix_getgrnam($group))) {
66368 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
66369 }
66370 } else {
66371 if (true !== @chgrp($file, $group)) {
66372 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
66373 }
66374 }
66375 }
66376 }
66377
66378
66379
66380
66381
66382
66383
66384
66385
66386
66387
66388 public function rename($origin, $target, $overwrite = false)
66389 {
66390
66391  if (!$overwrite && $this->isReadable($target)) {
66392 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
66393 }
66394
66395 if (true !== @rename($origin, $target)) {
66396 if (is_dir($origin)) {
66397
66398  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
66399 $this->remove($origin);
66400
66401 return;
66402 }
66403 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
66404 }
66405 }
66406
66407
66408
66409
66410
66411
66412
66413
66414
66415
66416 private function isReadable($filename)
66417 {
66418 $maxPathLength = PHP_MAXPATHLEN - 2;
66419
66420 if (\strlen($filename) > $maxPathLength) {
66421 throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
66422 }
66423
66424 return is_readable($filename);
66425 }
66426
66427
66428
66429
66430
66431
66432
66433
66434
66435
66436 public function symlink($originDir, $targetDir, $copyOnWindows = false)
66437 {
66438 if ('\\' === \DIRECTORY_SEPARATOR) {
66439 $originDir = strtr($originDir, '/', '\\');
66440 $targetDir = strtr($targetDir, '/', '\\');
66441
66442 if ($copyOnWindows) {
66443 $this->mirror($originDir, $targetDir);
66444
66445 return;
66446 }
66447 }
66448
66449 $this->mkdir(\dirname($targetDir));
66450
66451 if (is_link($targetDir)) {
66452 if (readlink($targetDir) === $originDir) {
66453 return;
66454 }
66455 $this->remove($targetDir);
66456 }
66457
66458 if (!self::box('symlink', $originDir, $targetDir)) {
66459 if (null !== self::$lastError) {
66460 if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
66461 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);
66462 }
66463 }
66464 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
66465 }
66466 }
66467
66468
66469
66470
66471
66472
66473
66474
66475
66476 public function makePathRelative($endPath, $startPath)
66477 {
66478
66479  if ('\\' === \DIRECTORY_SEPARATOR) {
66480 $endPath = str_replace('\\', '/', $endPath);
66481 $startPath = str_replace('\\', '/', $startPath);
66482 }
66483
66484 $stripDriveLetter = function ($path) {
66485 if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
66486 return substr($path, 2);
66487 }
66488
66489 return $path;
66490 };
66491
66492 $endPath = $stripDriveLetter($endPath);
66493 $startPath = $stripDriveLetter($startPath);
66494
66495
66496  $startPathArr = explode('/', trim($startPath, '/'));
66497 $endPathArr = explode('/', trim($endPath, '/'));
66498
66499 $normalizePathArray = function ($pathSegments, $absolute) {
66500 $result = array();
66501
66502 foreach ($pathSegments as $segment) {
66503 if ('..' === $segment && ($absolute || \count($result))) {
66504 array_pop($result);
66505 } elseif ('.' !== $segment) {
66506 $result[] = $segment;
66507 }
66508 }
66509
66510 return $result;
66511 };
66512
66513 $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
66514 $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
66515
66516
66517  $index = 0;
66518 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
66519 ++$index;
66520 }
66521
66522
66523  if (1 === \count($startPathArr) && '' === $startPathArr[0]) {
66524 $depth = 0;
66525 } else {
66526 $depth = \count($startPathArr) - $index;
66527 }
66528
66529
66530  $traverser = str_repeat('../', $depth);
66531
66532 $endPathRemainder = implode('/', \array_slice($endPathArr, $index));
66533
66534
66535  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
66536
66537 return '' === $relativePath ? './' : $relativePath;
66538 }
66539
66540
66541
66542
66543
66544
66545
66546
66547
66548
66549
66550
66551
66552
66553
66554
66555
66556
66557
66558
66559 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
66560 {
66561 $targetDir = rtrim($targetDir, '/\\');
66562 $originDir = rtrim($originDir, '/\\');
66563 $originDirLen = \strlen($originDir);
66564
66565
66566  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
66567 $deleteIterator = $iterator;
66568 if (null === $deleteIterator) {
66569 $flags = \FilesystemIterator::SKIP_DOTS;
66570 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
66571 }
66572 $targetDirLen = \strlen($targetDir);
66573 foreach ($deleteIterator as $file) {
66574 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
66575 if (!$this->exists($origin)) {
66576 $this->remove($file);
66577 }
66578 }
66579 }
66580
66581 $copyOnWindows = false;
66582 if (isset($options['copy_on_windows'])) {
66583 $copyOnWindows = $options['copy_on_windows'];
66584 }
66585
66586 if (null === $iterator) {
66587 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
66588 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
66589 }
66590
66591 if ($this->exists($originDir)) {
66592 $this->mkdir($targetDir);
66593 }
66594
66595 foreach ($iterator as $file) {
66596 $target = $targetDir.substr($file->getPathname(), $originDirLen);
66597
66598 if ($copyOnWindows) {
66599 if (is_file($file)) {
66600 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
66601 } elseif (is_dir($file)) {
66602 $this->mkdir($target);
66603 } else {
66604 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
66605 }
66606 } else {
66607 if (is_link($file)) {
66608 $this->symlink($file->getLinkTarget(), $target);
66609 } elseif (is_dir($file)) {
66610 $this->mkdir($target);
66611 } elseif (is_file($file)) {
66612 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
66613 } else {
66614 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
66615 }
66616 }
66617 }
66618 }
66619
66620
66621
66622
66623
66624
66625
66626
66627 public function isAbsolutePath($file)
66628 {
66629 return strspn($file, '/\\', 0, 1)
66630 || (\strlen($file) > 3 && ctype_alpha($file[0])
66631 && ':' === substr($file, 1, 1)
66632 && strspn($file, '/\\', 2, 1)
66633 )
66634 || null !== parse_url($file, PHP_URL_SCHEME)
66635 ;
66636 }
66637
66638
66639
66640
66641
66642
66643
66644
66645
66646
66647 public function tempnam($dir, $prefix)
66648 {
66649 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
66650
66651
66652  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
66653 $tmpFile = @tempnam($hierarchy, $prefix);
66654
66655
66656  if (false !== $tmpFile) {
66657 if (null !== $scheme && 'gs' !== $scheme) {
66658 return $scheme.'://'.$tmpFile;
66659 }
66660
66661 return $tmpFile;
66662 }
66663
66664 throw new IOException('A temporary file could not be created.');
66665 }
66666
66667
66668  for ($i = 0; $i < 10; ++$i) {
66669
66670  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
66671
66672
66673  
66674  $handle = @fopen($tmpFile, 'x+');
66675
66676
66677  if (false === $handle) {
66678 continue;
66679 }
66680
66681
66682  @fclose($handle);
66683
66684 return $tmpFile;
66685 }
66686
66687 throw new IOException('A temporary file could not be created.');
66688 }
66689
66690
66691
66692
66693
66694
66695
66696
66697
66698
66699
66700 public function dumpFile($filename, $content, $mode = 0666)
66701 {
66702 $dir = \dirname($filename);
66703
66704 if (!is_dir($dir)) {
66705 $this->mkdir($dir);
66706 }
66707
66708 if (!is_writable($dir)) {
66709 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
66710 }
66711
66712 $tmpFile = $this->tempnam($dir, basename($filename));
66713
66714 if (false === @file_put_contents($tmpFile, $content)) {
66715 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
66716 }
66717
66718 if (null !== $mode) {
66719 if (\func_num_args() > 2) {
66720 @trigger_error('Support for modifying file permissions is deprecated since Symfony 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
66721 }
66722
66723 $this->chmod($tmpFile, $mode);
66724 } elseif (file_exists($filename)) {
66725 @chmod($tmpFile, fileperms($filename));
66726 }
66727
66728 $this->rename($tmpFile, $filename, true);
66729 }
66730
66731
66732
66733
66734
66735
66736 private function toIterator($files)
66737 {
66738 if (!$files instanceof \Traversable) {
66739 $files = new \ArrayObject(\is_array($files) ? $files : array($files));
66740 }
66741
66742 return $files;
66743 }
66744
66745
66746
66747
66748
66749
66750
66751
66752 private function getSchemeAndHierarchy($filename)
66753 {
66754 $components = explode('://', $filename, 2);
66755
66756 return 2 === \count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
66757 }
66758
66759 private static function box($func)
66760 {
66761 self::$lastError = null;
66762 \set_error_handler(__CLASS__.'::handleError');
66763 try {
66764 $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
66765 \restore_error_handler();
66766
66767 return $result;
66768 } catch (\Throwable $e) {
66769 } catch (\Exception $e) {
66770 }
66771 \restore_error_handler();
66772
66773 throw $e;
66774 }
66775
66776
66777
66778
66779 public static function handleError($type, $msg)
66780 {
66781 self::$lastError = $msg;
66782 }
66783 }
66784 Copyright (c) 2004-2018 Fabien Potencier
66785
66786 Permission is hereby granted, free of charge, to any person obtaining a copy
66787 of this software and associated documentation files (the "Software"), to deal
66788 in the Software without restriction, including without limitation the rights
66789 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66790 copies of the Software, and to permit persons to whom the Software is furnished
66791 to do so, subject to the following conditions:
66792
66793 The above copyright notice and this permission notice shall be included in all
66794 copies or substantial portions of the Software.
66795
66796 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
66797 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
66798 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66799 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66800 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
66801 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
66802 THE SOFTWARE.
66803 <?php
66804
66805
66806
66807
66808
66809
66810
66811
66812
66813
66814 namespace Symfony\Component\Filesystem;
66815
66816 use Symfony\Component\Filesystem\Exception\IOException;
66817
66818
66819
66820
66821
66822
66823
66824
66825
66826
66827
66828
66829
66830
66831 class LockHandler
66832 {
66833 private $file;
66834 private $handle;
66835
66836
66837
66838
66839
66840
66841
66842 public function __construct($name, $lockPath = null)
66843 {
66844 $lockPath = $lockPath ?: sys_get_temp_dir();
66845
66846 if (!is_dir($lockPath)) {
66847 $fs = new Filesystem();
66848 $fs->mkdir($lockPath);
66849 }
66850
66851 if (!is_writable($lockPath)) {
66852 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
66853 }
66854
66855 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
66856 }
66857
66858
66859
66860
66861
66862
66863
66864
66865
66866
66867 public function lock($blocking = false)
66868 {
66869 if ($this->handle) {
66870 return true;
66871 }
66872
66873 $error = null;
66874
66875
66876  set_error_handler(function ($errno, $msg) use (&$error) {
66877 $error = $msg;
66878 });
66879
66880 if (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
66881 if ($this->handle = fopen($this->file, 'x')) {
66882 chmod($this->file, 0666);
66883 } elseif (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
66884 usleep(100); 
66885  $this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r');
66886 }
66887 }
66888 restore_error_handler();
66889
66890 if (!$this->handle) {
66891 throw new IOException($error, 0, null, $this->file);
66892 }
66893
66894
66895  
66896  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
66897 fclose($this->handle);
66898 $this->handle = null;
66899
66900 return false;
66901 }
66902
66903 return true;
66904 }
66905
66906
66907
66908
66909 public function release()
66910 {
66911 if ($this->handle) {
66912 flock($this->handle, LOCK_UN | LOCK_NB);
66913 fclose($this->handle);
66914 $this->handle = null;
66915 }
66916 }
66917 }
66918 <?php
66919
66920
66921
66922
66923
66924
66925
66926
66927
66928
66929 namespace Symfony\Component\Finder\Adapter;
66930
66931 @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);
66932
66933
66934
66935
66936
66937
66938
66939
66940 abstract class AbstractAdapter implements AdapterInterface
66941 {
66942 protected $followLinks = false;
66943 protected $mode = 0;
66944 protected $minDepth = 0;
66945 protected $maxDepth = PHP_INT_MAX;
66946 protected $exclude = array();
66947 protected $names = array();
66948 protected $notNames = array();
66949 protected $contains = array();
66950 protected $notContains = array();
66951 protected $sizes = array();
66952 protected $dates = array();
66953 protected $filters = array();
66954 protected $sort = false;
66955 protected $paths = array();
66956 protected $notPaths = array();
66957 protected $ignoreUnreadableDirs = false;
66958
66959 private static $areSupported = array();
66960
66961
66962
66963
66964 public function isSupported()
66965 {
66966 $name = $this->getName();
66967
66968 if (!array_key_exists($name, self::$areSupported)) {
66969 self::$areSupported[$name] = $this->canBeUsed();
66970 }
66971
66972 return self::$areSupported[$name];
66973 }
66974
66975
66976
66977
66978 public function setFollowLinks($followLinks)
66979 {
66980 $this->followLinks = $followLinks;
66981
66982 return $this;
66983 }
66984
66985
66986
66987
66988 public function setMode($mode)
66989 {
66990 $this->mode = $mode;
66991
66992 return $this;
66993 }
66994
66995
66996
66997
66998 public function setDepths(array $depths)
66999 {
67000 $this->minDepth = 0;
67001 $this->maxDepth = PHP_INT_MAX;
67002
67003 foreach ($depths as $comparator) {
67004 switch ($comparator->getOperator()) {
67005 case '>':
67006 $this->minDepth = $comparator->getTarget() + 1;
67007 break;
67008 case '>=':
67009 $this->minDepth = $comparator->getTarget();
67010 break;
67011 case '<':
67012 $this->maxDepth = $comparator->getTarget() - 1;
67013 break;
67014 case '<=':
67015 $this->maxDepth = $comparator->getTarget();
67016 break;
67017 default:
67018 $this->minDepth = $this->maxDepth = $comparator->getTarget();
67019 }
67020 }
67021
67022 return $this;
67023 }
67024
67025
67026
67027
67028 public function setExclude(array $exclude)
67029 {
67030 $this->exclude = $exclude;
67031
67032 return $this;
67033 }
67034
67035
67036
67037
67038 public function setNames(array $names)
67039 {
67040 $this->names = $names;
67041
67042 return $this;
67043 }
67044
67045
67046
67047
67048 public function setNotNames(array $notNames)
67049 {
67050 $this->notNames = $notNames;
67051
67052 return $this;
67053 }
67054
67055
67056
67057
67058 public function setContains(array $contains)
67059 {
67060 $this->contains = $contains;
67061
67062 return $this;
67063 }
67064
67065
67066
67067
67068 public function setNotContains(array $notContains)
67069 {
67070 $this->notContains = $notContains;
67071
67072 return $this;
67073 }
67074
67075
67076
67077
67078 public function setSizes(array $sizes)
67079 {
67080 $this->sizes = $sizes;
67081
67082 return $this;
67083 }
67084
67085
67086
67087
67088 public function setDates(array $dates)
67089 {
67090 $this->dates = $dates;
67091
67092 return $this;
67093 }
67094
67095
67096
67097
67098 public function setFilters(array $filters)
67099 {
67100 $this->filters = $filters;
67101
67102 return $this;
67103 }
67104
67105
67106
67107
67108 public function setSort($sort)
67109 {
67110 $this->sort = $sort;
67111
67112 return $this;
67113 }
67114
67115
67116
67117
67118 public function setPath(array $paths)
67119 {
67120 $this->paths = $paths;
67121
67122 return $this;
67123 }
67124
67125
67126
67127
67128 public function setNotPath(array $notPaths)
67129 {
67130 $this->notPaths = $notPaths;
67131
67132 return $this;
67133 }
67134
67135
67136
67137
67138 public function ignoreUnreadableDirs($ignore = true)
67139 {
67140 $this->ignoreUnreadableDirs = (bool) $ignore;
67141
67142 return $this;
67143 }
67144
67145
67146
67147
67148
67149
67150
67151
67152
67153
67154
67155
67156 abstract protected function canBeUsed();
67157 }
67158 <?php
67159
67160
67161
67162
67163
67164
67165
67166
67167
67168
67169 namespace Symfony\Component\Finder\Adapter;
67170
67171 @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);
67172
67173 use Symfony\Component\Finder\Comparator\DateComparator;
67174 use Symfony\Component\Finder\Comparator\NumberComparator;
67175 use Symfony\Component\Finder\Exception\AccessDeniedException;
67176 use Symfony\Component\Finder\Expression\Expression;
67177 use Symfony\Component\Finder\Iterator;
67178 use Symfony\Component\Finder\Shell\Command;
67179 use Symfony\Component\Finder\Shell\Shell;
67180
67181
67182
67183
67184
67185
67186
67187
67188 abstract class AbstractFindAdapter extends AbstractAdapter
67189 {
67190 protected $shell;
67191
67192 public function __construct()
67193 {
67194 $this->shell = new Shell();
67195 }
67196
67197
67198
67199
67200 public function searchInDirectory($dir)
67201 {
67202
67203  $dir = realpath($dir);
67204
67205
67206  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
67207 return new Iterator\FilePathsIterator(array(), $dir);
67208 }
67209
67210 $command = Command::create();
67211 $find = $this->buildFindCommand($command, $dir);
67212
67213 if ($this->followLinks) {
67214 $find->add('-follow');
67215 }
67216
67217 $find->add('-mindepth')->add($this->minDepth + 1);
67218
67219 if (PHP_INT_MAX !== $this->maxDepth) {
67220 $find->add('-maxdepth')->add($this->maxDepth + 1);
67221 }
67222
67223 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
67224 $find->add('-type d');
67225 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
67226 $find->add('-type f');
67227 }
67228
67229 $this->buildNamesFiltering($find, $this->names);
67230 $this->buildNamesFiltering($find, $this->notNames, true);
67231 $this->buildPathsFiltering($find, $dir, $this->paths);
67232 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
67233 $this->buildSizesFiltering($find, $this->sizes);
67234 $this->buildDatesFiltering($find, $this->dates);
67235
67236 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
67237 $useSort = \is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
67238
67239 if ($useGrep && ($this->contains || $this->notContains)) {
67240 $grep = $command->ins('grep');
67241 $this->buildContentFiltering($grep, $this->contains);
67242 $this->buildContentFiltering($grep, $this->notContains, true);
67243 }
67244
67245 if ($useSort) {
67246 $this->buildSorting($command, $this->sort);
67247 }
67248
67249 $command->setErrorHandler(
67250 $this->ignoreUnreadableDirs
67251
67252  ? function ($stderr) { }
67253 : function ($stderr) { throw new AccessDeniedException($stderr); }
67254 );
67255
67256 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
67257 $iterator = new Iterator\FilePathsIterator($paths, $dir);
67258
67259 if ($this->exclude) {
67260 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
67261 }
67262
67263 if (!$useGrep && ($this->contains || $this->notContains)) {
67264 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
67265 }
67266
67267 if ($this->filters) {
67268 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
67269 }
67270
67271 if (!$useSort && $this->sort) {
67272 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
67273 $iterator = $iteratorAggregate->getIterator();
67274 }
67275
67276 return $iterator;
67277 }
67278
67279
67280
67281
67282 protected function canBeUsed()
67283 {
67284 return $this->shell->testCommand('find');
67285 }
67286
67287
67288
67289
67290
67291
67292
67293 protected function buildFindCommand(Command $command, $dir)
67294 {
67295 return $command
67296 ->ins('find')
67297 ->add('find ')
67298 ->arg($dir)
67299 ->add('-noleaf'); 
67300  }
67301
67302
67303
67304
67305
67306
67307 private function buildNamesFiltering(Command $command, array $names, $not = false)
67308 {
67309 if (0 === \count($names)) {
67310 return;
67311 }
67312
67313 $command->add($not ? '-not' : null)->cmd('(');
67314
67315 foreach ($names as $i => $name) {
67316 $expr = Expression::create($name);
67317
67318
67319  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
67320 $expr = Expression::create($expr->getGlob()->toRegex(false));
67321 }
67322
67323
67324  
67325  
67326  if ($expr->isRegex()) {
67327 $regex = $expr->getRegex();
67328 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
67329 ->setStartFlag(false)
67330 ->setStartJoker(true)
67331 ->replaceJokers('[^/]');
67332 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
67333 $regex->setEndJoker(false)->append('[^/]*');
67334 }
67335 }
67336
67337 $command
67338 ->add($i > 0 ? '-or' : null)
67339 ->add($expr->isRegex()
67340 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
67341 : ($expr->isCaseSensitive() ? '-name' : '-iname')
67342 )
67343 ->arg($expr->renderPattern());
67344 }
67345
67346 $command->cmd(')');
67347 }
67348
67349
67350
67351
67352
67353
67354
67355 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
67356 {
67357 if (0 === \count($paths)) {
67358 return;
67359 }
67360
67361 $command->add($not ? '-not' : null)->cmd('(');
67362
67363 foreach ($paths as $i => $path) {
67364 $expr = Expression::create($path);
67365
67366
67367  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
67368 $expr = Expression::create($expr->getGlob()->toRegex(false));
67369 }
67370
67371
67372  if ($expr->isRegex()) {
67373 $regex = $expr->getRegex();
67374 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).\DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
67375 } else {
67376 $expr->prepend('*')->append('*');
67377 }
67378
67379 $command
67380 ->add($i > 0 ? '-or' : null)
67381 ->add($expr->isRegex()
67382 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
67383 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
67384 )
67385 ->arg($expr->renderPattern());
67386 }
67387
67388 $command->cmd(')');
67389 }
67390
67391
67392
67393
67394
67395 private function buildSizesFiltering(Command $command, array $sizes)
67396 {
67397 foreach ($sizes as $i => $size) {
67398 $command->add($i > 0 ? '-and' : null);
67399
67400 switch ($size->getOperator()) {
67401 case '<=':
67402 $command->add('-size -'.($size->getTarget() + 1).'c');
67403 break;
67404 case '>=':
67405 $command->add('-size +'.($size->getTarget() - 1).'c');
67406 break;
67407 case '>':
67408 $command->add('-size +'.$size->getTarget().'c');
67409 break;
67410 case '!=':
67411 $command->add('-size -'.$size->getTarget().'c');
67412 $command->add('-size +'.$size->getTarget().'c');
67413 break;
67414 case '<':
67415 default:
67416 $command->add('-size -'.$size->getTarget().'c');
67417 }
67418 }
67419 }
67420
67421
67422
67423
67424
67425 private function buildDatesFiltering(Command $command, array $dates)
67426 {
67427 foreach ($dates as $i => $date) {
67428 $command->add($i > 0 ? '-and' : null);
67429
67430 $mins = (int) round((time() - $date->getTarget()) / 60);
67431
67432 if (0 > $mins) {
67433
67434  $command->add(' -mmin -0');
67435
67436  return;
67437 }
67438
67439 switch ($date->getOperator()) {
67440 case '<=':
67441 $command->add('-mmin +'.($mins - 1));
67442 break;
67443 case '>=':
67444 $command->add('-mmin -'.($mins + 1));
67445 break;
67446 case '>':
67447 $command->add('-mmin -'.$mins);
67448 break;
67449 case '!=':
67450 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
67451 break;
67452 case '<':
67453 default:
67454 $command->add('-mmin +'.$mins);
67455 }
67456 }
67457 }
67458
67459
67460
67461
67462
67463
67464
67465 private function buildSorting(Command $command, $sort)
67466 {
67467 $this->buildFormatSorting($command, $sort);
67468 }
67469
67470
67471
67472
67473
67474 abstract protected function buildFormatSorting(Command $command, $sort);
67475
67476
67477
67478
67479
67480
67481 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
67482 }
67483 <?php
67484
67485
67486
67487
67488
67489
67490
67491
67492
67493
67494 namespace Symfony\Component\Finder\Adapter;
67495
67496
67497
67498
67499
67500
67501 interface AdapterInterface
67502 {
67503
67504
67505
67506
67507
67508 public function setFollowLinks($followLinks);
67509
67510
67511
67512
67513
67514
67515 public function setMode($mode);
67516
67517
67518
67519
67520 public function setExclude(array $exclude);
67521
67522
67523
67524
67525 public function setDepths(array $depths);
67526
67527
67528
67529
67530 public function setNames(array $names);
67531
67532
67533
67534
67535 public function setNotNames(array $notNames);
67536
67537
67538
67539
67540 public function setContains(array $contains);
67541
67542
67543
67544
67545 public function setNotContains(array $notContains);
67546
67547
67548
67549
67550 public function setSizes(array $sizes);
67551
67552
67553
67554
67555 public function setDates(array $dates);
67556
67557
67558
67559
67560 public function setFilters(array $filters);
67561
67562
67563
67564
67565
67566
67567 public function setSort($sort);
67568
67569
67570
67571
67572 public function setPath(array $paths);
67573
67574
67575
67576
67577 public function setNotPath(array $notPaths);
67578
67579
67580
67581
67582
67583
67584 public function ignoreUnreadableDirs($ignore = true);
67585
67586
67587
67588
67589
67590
67591 public function searchInDirectory($dir);
67592
67593
67594
67595
67596
67597
67598 public function isSupported();
67599
67600
67601
67602
67603
67604
67605 public function getName();
67606 }
67607 <?php
67608
67609
67610
67611
67612
67613
67614
67615
67616
67617
67618 namespace Symfony\Component\Finder\Adapter;
67619
67620 @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);
67621
67622 use Symfony\Component\Finder\Expression\Expression;
67623 use Symfony\Component\Finder\Iterator\SortableIterator;
67624 use Symfony\Component\Finder\Shell\Command;
67625 use Symfony\Component\Finder\Shell\Shell;
67626
67627
67628
67629
67630
67631
67632
67633
67634 class BsdFindAdapter extends AbstractFindAdapter
67635 {
67636
67637
67638
67639 public function getName()
67640 {
67641 return 'bsd_find';
67642 }
67643
67644
67645
67646
67647 protected function canBeUsed()
67648 {
67649 return \in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
67650 }
67651
67652
67653
67654
67655 protected function buildFormatSorting(Command $command, $sort)
67656 {
67657 switch ($sort) {
67658 case SortableIterator::SORT_BY_NAME:
67659 $command->ins('sort')->add('| sort');
67660
67661 return;
67662 case SortableIterator::SORT_BY_TYPE:
67663 $format = '%HT';
67664 break;
67665 case SortableIterator::SORT_BY_ACCESSED_TIME:
67666 $format = '%a';
67667 break;
67668 case SortableIterator::SORT_BY_CHANGED_TIME:
67669 $format = '%c';
67670 break;
67671 case SortableIterator::SORT_BY_MODIFIED_TIME:
67672 $format = '%m';
67673 break;
67674 default:
67675 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
67676 }
67677
67678 $command
67679 ->add('-print0 | xargs -0 stat -f')
67680 ->arg($format.'%t%N')
67681 ->add('| sort | cut -f 2');
67682 }
67683
67684
67685
67686
67687 protected function buildFindCommand(Command $command, $dir)
67688 {
67689 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
67690
67691 return $command;
67692 }
67693
67694
67695
67696
67697 protected function buildContentFiltering(Command $command, array $contains, $not = false)
67698 {
67699 foreach ($contains as $contain) {
67700 $expr = Expression::create($contain);
67701
67702
67703  $command
67704 ->add('| grep -v \'^$\'')
67705 ->add('| xargs -I{} grep -I')
67706 ->add($expr->isCaseSensitive() ? null : '-i')
67707 ->add($not ? '-L' : '-l')
67708 ->add('-Ee')->arg($expr->renderPattern())
67709 ->add('{}')
67710 ;
67711 }
67712 }
67713 }
67714 <?php
67715
67716
67717
67718
67719
67720
67721
67722
67723
67724
67725 namespace Symfony\Component\Finder\Adapter;
67726
67727 @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);
67728
67729 use Symfony\Component\Finder\Expression\Expression;
67730 use Symfony\Component\Finder\Iterator\SortableIterator;
67731 use Symfony\Component\Finder\Shell\Command;
67732 use Symfony\Component\Finder\Shell\Shell;
67733
67734
67735
67736
67737
67738
67739
67740
67741 class GnuFindAdapter extends AbstractFindAdapter
67742 {
67743
67744
67745
67746 public function getName()
67747 {
67748 return 'gnu_find';
67749 }
67750
67751
67752
67753
67754 protected function buildFormatSorting(Command $command, $sort)
67755 {
67756 switch ($sort) {
67757 case SortableIterator::SORT_BY_NAME:
67758 $command->ins('sort')->add('| sort');
67759
67760 return;
67761 case SortableIterator::SORT_BY_TYPE:
67762 $format = '%y';
67763 break;
67764 case SortableIterator::SORT_BY_ACCESSED_TIME:
67765 $format = '%A@';
67766 break;
67767 case SortableIterator::SORT_BY_CHANGED_TIME:
67768 $format = '%C@';
67769 break;
67770 case SortableIterator::SORT_BY_MODIFIED_TIME:
67771 $format = '%T@';
67772 break;
67773 default:
67774 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
67775 }
67776
67777 $command
67778 ->get('find')
67779 ->add('-printf')
67780 ->arg($format.' %h/%f\\n')
67781 ->add('| sort | cut')
67782 ->arg('-d ')
67783 ->arg('-f2-')
67784 ;
67785 }
67786
67787
67788
67789
67790 protected function canBeUsed()
67791 {
67792 return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
67793 }
67794
67795
67796
67797
67798 protected function buildFindCommand(Command $command, $dir)
67799 {
67800 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
67801 }
67802
67803
67804
67805
67806 protected function buildContentFiltering(Command $command, array $contains, $not = false)
67807 {
67808 foreach ($contains as $contain) {
67809 $expr = Expression::create($contain);
67810
67811
67812  $command
67813 ->add('| xargs -I{} -r grep -I')
67814 ->add($expr->isCaseSensitive() ? null : '-i')
67815 ->add($not ? '-L' : '-l')
67816 ->add('-Ee')->arg($expr->renderPattern())
67817 ->add('{}')
67818 ;
67819 }
67820 }
67821 }
67822 <?php
67823
67824
67825
67826
67827
67828
67829
67830
67831
67832
67833 namespace Symfony\Component\Finder\Adapter;
67834
67835 @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);
67836
67837 use Symfony\Component\Finder\Iterator;
67838
67839
67840
67841
67842
67843
67844
67845
67846 class PhpAdapter extends AbstractAdapter
67847 {
67848
67849
67850
67851 public function searchInDirectory($dir)
67852 {
67853 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
67854
67855 if ($this->followLinks) {
67856 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
67857 }
67858
67859 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
67860
67861 if ($this->exclude) {
67862 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
67863 }
67864
67865 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
67866
67867 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
67868 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
67869 }
67870
67871 if ($this->mode) {
67872 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
67873 }
67874
67875 if ($this->names || $this->notNames) {
67876 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
67877 }
67878
67879 if ($this->contains || $this->notContains) {
67880 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
67881 }
67882
67883 if ($this->sizes) {
67884 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
67885 }
67886
67887 if ($this->dates) {
67888 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
67889 }
67890
67891 if ($this->filters) {
67892 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
67893 }
67894
67895 if ($this->paths || $this->notPaths) {
67896 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
67897 }
67898
67899 if ($this->sort) {
67900 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
67901 $iterator = $iteratorAggregate->getIterator();
67902 }
67903
67904 return $iterator;
67905 }
67906
67907
67908
67909
67910 public function getName()
67911 {
67912 return 'php';
67913 }
67914
67915
67916
67917
67918 protected function canBeUsed()
67919 {
67920 return true;
67921 }
67922 }
67923 <?php
67924
67925
67926
67927
67928
67929
67930
67931
67932
67933
67934 namespace Symfony\Component\Finder\Comparator;
67935
67936
67937
67938
67939
67940
67941 class Comparator
67942 {
67943 private $target;
67944 private $operator = '==';
67945
67946
67947
67948
67949
67950
67951 public function getTarget()
67952 {
67953 return $this->target;
67954 }
67955
67956
67957
67958
67959
67960
67961 public function setTarget($target)
67962 {
67963 $this->target = $target;
67964 }
67965
67966
67967
67968
67969
67970
67971 public function getOperator()
67972 {
67973 return $this->operator;
67974 }
67975
67976
67977
67978
67979
67980
67981
67982
67983 public function setOperator($operator)
67984 {
67985 if (!$operator) {
67986 $operator = '==';
67987 }
67988
67989 if (!\in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
67990 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
67991 }
67992
67993 $this->operator = $operator;
67994 }
67995
67996
67997
67998
67999
68000
68001
68002
68003 public function test($test)
68004 {
68005 switch ($this->operator) {
68006 case '>':
68007 return $test > $this->target;
68008 case '>=':
68009 return $test >= $this->target;
68010 case '<':
68011 return $test < $this->target;
68012 case '<=':
68013 return $test <= $this->target;
68014 case '!=':
68015 return $test != $this->target;
68016 }
68017
68018 return $test == $this->target;
68019 }
68020 }
68021 <?php
68022
68023
68024
68025
68026
68027
68028
68029
68030
68031
68032 namespace Symfony\Component\Finder\Comparator;
68033
68034
68035
68036
68037
68038
68039 class DateComparator extends Comparator
68040 {
68041
68042
68043
68044
68045
68046 public function __construct($test)
68047 {
68048 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
68049 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
68050 }
68051
68052 try {
68053 $date = new \DateTime($matches[2]);
68054 $target = $date->format('U');
68055 } catch (\Exception $e) {
68056 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
68057 }
68058
68059 $operator = isset($matches[1]) ? $matches[1] : '==';
68060 if ('since' === $operator || 'after' === $operator) {
68061 $operator = '>';
68062 }
68063
68064 if ('until' === $operator || 'before' === $operator) {
68065 $operator = '<';
68066 }
68067
68068 $this->setOperator($operator);
68069 $this->setTarget($target);
68070 }
68071 }
68072 <?php
68073
68074
68075
68076
68077
68078
68079
68080
68081
68082
68083 namespace Symfony\Component\Finder\Comparator;
68084
68085
68086
68087
68088
68089
68090
68091
68092
68093
68094
68095
68096
68097
68098
68099
68100
68101
68102
68103
68104
68105
68106 class NumberComparator extends Comparator
68107 {
68108
68109
68110
68111
68112
68113 public function __construct($test)
68114 {
68115 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
68116 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
68117 }
68118
68119 $target = $matches[2];
68120 if (!is_numeric($target)) {
68121 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
68122 }
68123 if (isset($matches[3])) {
68124
68125  switch (strtolower($matches[3])) {
68126 case 'k':
68127 $target *= 1000;
68128 break;
68129 case 'ki':
68130 $target *= 1024;
68131 break;
68132 case 'm':
68133 $target *= 1000000;
68134 break;
68135 case 'mi':
68136 $target *= 1024 * 1024;
68137 break;
68138 case 'g':
68139 $target *= 1000000000;
68140 break;
68141 case 'gi':
68142 $target *= 1024 * 1024 * 1024;
68143 break;
68144 }
68145 }
68146
68147 $this->setTarget($target);
68148 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
68149 }
68150 }
68151 <?php
68152
68153
68154
68155
68156
68157
68158
68159
68160
68161
68162 namespace Symfony\Component\Finder\Exception;
68163
68164
68165
68166
68167 class AccessDeniedException extends \UnexpectedValueException
68168 {
68169 }
68170 <?php
68171
68172
68173
68174
68175
68176
68177
68178
68179
68180
68181 namespace Symfony\Component\Finder\Exception;
68182
68183 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68184
68185 use Symfony\Component\Finder\Adapter\AdapterInterface;
68186
68187
68188
68189
68190
68191
68192
68193
68194 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
68195 {
68196 private $adapter;
68197
68198
68199
68200
68201
68202
68203 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
68204 {
68205 $this->adapter = $adapter;
68206 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
68207 }
68208
68209
68210
68211
68212 public function getAdapter()
68213 {
68214 return $this->adapter;
68215 }
68216 }
68217 <?php
68218
68219
68220
68221
68222
68223
68224
68225
68226
68227
68228 namespace Symfony\Component\Finder\Exception;
68229
68230
68231
68232
68233 interface ExceptionInterface
68234 {
68235
68236
68237
68238 public function getAdapter();
68239 }
68240 <?php
68241
68242
68243
68244
68245
68246
68247
68248
68249
68250
68251 namespace Symfony\Component\Finder\Exception;
68252
68253 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68254
68255
68256
68257
68258
68259
68260 class OperationNotPermitedException extends AdapterFailureException
68261 {
68262 }
68263 <?php
68264
68265
68266
68267
68268
68269
68270
68271
68272
68273
68274 namespace Symfony\Component\Finder\Exception;
68275
68276 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68277
68278 use Symfony\Component\Finder\Adapter\AdapterInterface;
68279 use Symfony\Component\Finder\Shell\Command;
68280
68281
68282
68283
68284
68285
68286 class ShellCommandFailureException extends AdapterFailureException
68287 {
68288 private $command;
68289
68290 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
68291 {
68292 $this->command = $command;
68293 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
68294 }
68295
68296
68297
68298
68299 public function getCommand()
68300 {
68301 return $this->command;
68302 }
68303 }
68304 <?php
68305
68306
68307
68308
68309
68310
68311
68312
68313
68314
68315 namespace Symfony\Component\Finder\Expression;
68316
68317 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68318
68319
68320
68321
68322 class Expression implements ValueInterface
68323 {
68324 const TYPE_REGEX = 1;
68325 const TYPE_GLOB = 2;
68326
68327
68328
68329
68330 private $value;
68331
68332
68333
68334
68335
68336
68337 public static function create($expr)
68338 {
68339 return new self($expr);
68340 }
68341
68342
68343
68344
68345 public function __construct($expr)
68346 {
68347 try {
68348 $this->value = Regex::create($expr);
68349 } catch (\InvalidArgumentException $e) {
68350 $this->value = new Glob($expr);
68351 }
68352 }
68353
68354
68355
68356
68357 public function __toString()
68358 {
68359 return $this->render();
68360 }
68361
68362
68363
68364
68365 public function render()
68366 {
68367 return $this->value->render();
68368 }
68369
68370
68371
68372
68373 public function renderPattern()
68374 {
68375 return $this->value->renderPattern();
68376 }
68377
68378
68379
68380
68381 public function isCaseSensitive()
68382 {
68383 return $this->value->isCaseSensitive();
68384 }
68385
68386
68387
68388
68389 public function getType()
68390 {
68391 return $this->value->getType();
68392 }
68393
68394
68395
68396
68397 public function prepend($expr)
68398 {
68399 $this->value->prepend($expr);
68400
68401 return $this;
68402 }
68403
68404
68405
68406
68407 public function append($expr)
68408 {
68409 $this->value->append($expr);
68410
68411 return $this;
68412 }
68413
68414
68415
68416
68417 public function isRegex()
68418 {
68419 return self::TYPE_REGEX === $this->value->getType();
68420 }
68421
68422
68423
68424
68425 public function isGlob()
68426 {
68427 return self::TYPE_GLOB === $this->value->getType();
68428 }
68429
68430
68431
68432
68433
68434
68435 public function getGlob()
68436 {
68437 if (self::TYPE_GLOB !== $this->value->getType()) {
68438 throw new \LogicException('Regex can\'t be transformed to glob.');
68439 }
68440
68441 return $this->value;
68442 }
68443
68444
68445
68446
68447 public function getRegex()
68448 {
68449 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
68450 }
68451 }
68452 <?php
68453
68454
68455
68456
68457
68458
68459
68460
68461
68462
68463 namespace Symfony\Component\Finder\Expression;
68464
68465 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68466
68467 use Symfony\Component\Finder\Glob as FinderGlob;
68468
68469
68470
68471
68472 class Glob implements ValueInterface
68473 {
68474 private $pattern;
68475
68476
68477
68478
68479 public function __construct($pattern)
68480 {
68481 $this->pattern = $pattern;
68482 }
68483
68484
68485
68486
68487 public function render()
68488 {
68489 return $this->pattern;
68490 }
68491
68492
68493
68494
68495 public function renderPattern()
68496 {
68497 return $this->pattern;
68498 }
68499
68500
68501
68502
68503 public function getType()
68504 {
68505 return Expression::TYPE_GLOB;
68506 }
68507
68508
68509
68510
68511 public function isCaseSensitive()
68512 {
68513 return true;
68514 }
68515
68516
68517
68518
68519 public function prepend($expr)
68520 {
68521 $this->pattern = $expr.$this->pattern;
68522
68523 return $this;
68524 }
68525
68526
68527
68528
68529 public function append($expr)
68530 {
68531 $this->pattern .= $expr;
68532
68533 return $this;
68534 }
68535
68536
68537
68538
68539
68540
68541 public function isExpandable()
68542 {
68543 return false !== strpos($this->pattern, '{')
68544 && false !== strpos($this->pattern, '}');
68545 }
68546
68547
68548
68549
68550
68551
68552
68553 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
68554 {
68555 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
68556
68557 return new Regex($regex);
68558 }
68559 }
68560 <?php
68561
68562
68563
68564
68565
68566
68567
68568
68569
68570
68571 namespace Symfony\Component\Finder\Expression;
68572
68573 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68574
68575
68576
68577
68578 class Regex implements ValueInterface
68579 {
68580 const START_FLAG = '^';
68581 const END_FLAG = '$';
68582 const BOUNDARY = '~';
68583 const JOKER = '.*';
68584 const ESCAPING = '\\';
68585
68586
68587
68588
68589 private $pattern;
68590
68591
68592
68593
68594 private $options;
68595
68596
68597
68598
68599 private $startFlag;
68600
68601
68602
68603
68604 private $endFlag;
68605
68606
68607
68608
68609 private $startJoker;
68610
68611
68612
68613
68614 private $endJoker;
68615
68616
68617
68618
68619
68620
68621
68622
68623 public static function create($expr)
68624 {
68625 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
68626 $start = substr($m[1], 0, 1);
68627 $end = substr($m[1], -1);
68628
68629 if (
68630 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
68631 || ('{' === $start && '}' === $end)
68632 || ('(' === $start && ')' === $end)
68633 ) {
68634 return new self(substr($m[1], 1, -1), $m[2], $end);
68635 }
68636 }
68637
68638 throw new \InvalidArgumentException('Given expression is not a regex.');
68639 }
68640
68641
68642
68643
68644
68645
68646 public function __construct($pattern, $options = '', $delimiter = null)
68647 {
68648 if (null !== $delimiter) {
68649
68650  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
68651 }
68652
68653 $this->parsePattern($pattern);
68654 $this->options = $options;
68655 }
68656
68657
68658
68659
68660 public function __toString()
68661 {
68662 return $this->render();
68663 }
68664
68665
68666
68667
68668 public function render()
68669 {
68670 return self::BOUNDARY
68671 .$this->renderPattern()
68672 .self::BOUNDARY
68673 .$this->options;
68674 }
68675
68676
68677
68678
68679 public function renderPattern()
68680 {
68681 return ($this->startFlag ? self::START_FLAG : '')
68682 .($this->startJoker ? self::JOKER : '')
68683 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
68684 .($this->endJoker ? self::JOKER : '')
68685 .($this->endFlag ? self::END_FLAG : '');
68686 }
68687
68688
68689
68690
68691 public function isCaseSensitive()
68692 {
68693 return !$this->hasOption('i');
68694 }
68695
68696
68697
68698
68699 public function getType()
68700 {
68701 return Expression::TYPE_REGEX;
68702 }
68703
68704
68705
68706
68707 public function prepend($expr)
68708 {
68709 $this->pattern = $expr.$this->pattern;
68710
68711 return $this;
68712 }
68713
68714
68715
68716
68717 public function append($expr)
68718 {
68719 $this->pattern .= $expr;
68720
68721 return $this;
68722 }
68723
68724
68725
68726
68727
68728
68729 public function hasOption($option)
68730 {
68731 return false !== strpos($this->options, $option);
68732 }
68733
68734
68735
68736
68737
68738
68739 public function addOption($option)
68740 {
68741 if (!$this->hasOption($option)) {
68742 $this->options .= $option;
68743 }
68744
68745 return $this;
68746 }
68747
68748
68749
68750
68751
68752
68753 public function removeOption($option)
68754 {
68755 $this->options = str_replace($option, '', $this->options);
68756
68757 return $this;
68758 }
68759
68760
68761
68762
68763
68764
68765 public function setStartFlag($startFlag)
68766 {
68767 $this->startFlag = $startFlag;
68768
68769 return $this;
68770 }
68771
68772
68773
68774
68775 public function hasStartFlag()
68776 {
68777 return $this->startFlag;
68778 }
68779
68780
68781
68782
68783
68784
68785 public function setEndFlag($endFlag)
68786 {
68787 $this->endFlag = (bool) $endFlag;
68788
68789 return $this;
68790 }
68791
68792
68793
68794
68795 public function hasEndFlag()
68796 {
68797 return $this->endFlag;
68798 }
68799
68800
68801
68802
68803
68804
68805 public function setStartJoker($startJoker)
68806 {
68807 $this->startJoker = $startJoker;
68808
68809 return $this;
68810 }
68811
68812
68813
68814
68815 public function hasStartJoker()
68816 {
68817 return $this->startJoker;
68818 }
68819
68820
68821
68822
68823
68824
68825 public function setEndJoker($endJoker)
68826 {
68827 $this->endJoker = (bool) $endJoker;
68828
68829 return $this;
68830 }
68831
68832
68833
68834
68835 public function hasEndJoker()
68836 {
68837 return $this->endJoker;
68838 }
68839
68840
68841
68842
68843 public function replaceJokers($replacement)
68844 {
68845 $replace = function ($subject) use ($replacement) {
68846 $subject = $subject[0];
68847 $replace = 0 === substr_count($subject, '\\') % 2;
68848
68849 return $replace ? str_replace('.', $replacement, $subject) : $subject;
68850 };
68851
68852 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
68853
68854 return $this;
68855 }
68856
68857
68858
68859
68860 private function parsePattern($pattern)
68861 {
68862 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
68863 $pattern = substr($pattern, 1);
68864 }
68865
68866 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
68867 $pattern = substr($pattern, 2);
68868 }
68869
68870 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
68871 $pattern = substr($pattern, 0, -1);
68872 }
68873
68874 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
68875 $pattern = substr($pattern, 0, -2);
68876 }
68877
68878 $this->pattern = $pattern;
68879 }
68880 }
68881 <?php
68882
68883
68884
68885
68886
68887
68888
68889
68890
68891
68892 namespace Symfony\Component\Finder\Expression;
68893
68894 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68895
68896
68897
68898
68899 interface ValueInterface
68900 {
68901
68902
68903
68904
68905
68906 public function render();
68907
68908
68909
68910
68911
68912
68913 public function renderPattern();
68914
68915
68916
68917
68918
68919
68920 public function isCaseSensitive();
68921
68922
68923
68924
68925
68926
68927 public function getType();
68928
68929
68930
68931
68932
68933
68934 public function prepend($expr);
68935
68936
68937
68938
68939
68940
68941 public function append($expr);
68942 }
68943 <?php
68944
68945
68946
68947
68948
68949
68950
68951
68952
68953
68954 namespace Symfony\Component\Finder;
68955
68956 use Symfony\Component\Finder\Adapter\AdapterInterface;
68957 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
68958 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
68959 use Symfony\Component\Finder\Adapter\PhpAdapter;
68960 use Symfony\Component\Finder\Comparator\DateComparator;
68961 use Symfony\Component\Finder\Comparator\NumberComparator;
68962 use Symfony\Component\Finder\Exception\ExceptionInterface;
68963 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
68964 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
68965 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
68966 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
68967 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
68968 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
68969 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
68970 use Symfony\Component\Finder\Iterator\SortableIterator;
68971
68972
68973
68974
68975
68976
68977
68978
68979
68980
68981
68982
68983
68984
68985 class Finder implements \IteratorAggregate, \Countable
68986 {
68987 const IGNORE_VCS_FILES = 1;
68988 const IGNORE_DOT_FILES = 2;
68989
68990 private $mode = 0;
68991 private $names = array();
68992 private $notNames = array();
68993 private $exclude = array();
68994 private $filters = array();
68995 private $depths = array();
68996 private $sizes = array();
68997 private $followLinks = false;
68998 private $sort = false;
68999 private $ignore = 0;
69000 private $dirs = array();
69001 private $dates = array();
69002 private $iterators = array();
69003 private $contains = array();
69004 private $notContains = array();
69005 private $adapters = null;
69006 private $paths = array();
69007 private $notPaths = array();
69008 private $ignoreUnreadableDirs = false;
69009
69010 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
69011
69012 public function __construct()
69013 {
69014 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
69015 }
69016
69017
69018
69019
69020
69021
69022 public static function create()
69023 {
69024 return new static();
69025 }
69026
69027
69028
69029
69030
69031
69032
69033
69034
69035
69036
69037 public function addAdapter(AdapterInterface $adapter, $priority = 0)
69038 {
69039 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69040
69041 $this->initDefaultAdapters();
69042
69043 $this->adapters[$adapter->getName()] = array(
69044 'adapter' => $adapter,
69045 'priority' => $priority,
69046 'selected' => false,
69047 );
69048
69049 return $this->sortAdapters();
69050 }
69051
69052
69053
69054
69055
69056
69057
69058
69059 public function useBestAdapter()
69060 {
69061 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69062
69063 $this->initDefaultAdapters();
69064
69065 $this->resetAdapterSelection();
69066
69067 return $this->sortAdapters();
69068 }
69069
69070
69071
69072
69073
69074
69075
69076
69077
69078
69079
69080
69081 public function setAdapter($name)
69082 {
69083 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69084
69085 $this->initDefaultAdapters();
69086
69087 if (!isset($this->adapters[$name])) {
69088 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
69089 }
69090
69091 $this->resetAdapterSelection();
69092 $this->adapters[$name]['selected'] = true;
69093
69094 return $this->sortAdapters();
69095 }
69096
69097
69098
69099
69100
69101
69102
69103
69104 public function removeAdapters()
69105 {
69106 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69107
69108 $this->adapters = array();
69109
69110 return $this;
69111 }
69112
69113
69114
69115
69116
69117
69118
69119
69120 public function getAdapters()
69121 {
69122 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69123
69124 $this->initDefaultAdapters();
69125
69126 return array_values(array_map(function (array $adapter) {
69127 return $adapter['adapter'];
69128 }, $this->adapters));
69129 }
69130
69131
69132
69133
69134
69135
69136 public function directories()
69137 {
69138 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
69139
69140 return $this;
69141 }
69142
69143
69144
69145
69146
69147
69148 public function files()
69149 {
69150 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
69151
69152 return $this;
69153 }
69154
69155
69156
69157
69158
69159
69160
69161
69162
69163
69164
69165
69166
69167
69168
69169
69170 public function depth($level)
69171 {
69172 $this->depths[] = new Comparator\NumberComparator($level);
69173
69174 return $this;
69175 }
69176
69177
69178
69179
69180
69181
69182
69183
69184
69185
69186
69187
69188
69189
69190
69191
69192
69193
69194
69195 public function date($date)
69196 {
69197 $this->dates[] = new Comparator\DateComparator($date);
69198
69199 return $this;
69200 }
69201
69202
69203
69204
69205
69206
69207
69208
69209
69210
69211
69212
69213
69214
69215
69216
69217 public function name($pattern)
69218 {
69219 $this->names[] = $pattern;
69220
69221 return $this;
69222 }
69223
69224
69225
69226
69227
69228
69229
69230
69231
69232
69233 public function notName($pattern)
69234 {
69235 $this->notNames[] = $pattern;
69236
69237 return $this;
69238 }
69239
69240
69241
69242
69243
69244
69245
69246
69247
69248
69249
69250
69251
69252
69253
69254 public function contains($pattern)
69255 {
69256 $this->contains[] = $pattern;
69257
69258 return $this;
69259 }
69260
69261
69262
69263
69264
69265
69266
69267
69268
69269
69270
69271
69272
69273
69274
69275 public function notContains($pattern)
69276 {
69277 $this->notContains[] = $pattern;
69278
69279 return $this;
69280 }
69281
69282
69283
69284
69285
69286
69287
69288
69289
69290
69291
69292
69293
69294
69295
69296
69297
69298 public function path($pattern)
69299 {
69300 $this->paths[] = $pattern;
69301
69302 return $this;
69303 }
69304
69305
69306
69307
69308
69309
69310
69311
69312
69313
69314
69315
69316
69317
69318
69319
69320
69321 public function notPath($pattern)
69322 {
69323 $this->notPaths[] = $pattern;
69324
69325 return $this;
69326 }
69327
69328
69329
69330
69331
69332
69333
69334
69335
69336
69337
69338
69339
69340
69341
69342 public function size($size)
69343 {
69344 $this->sizes[] = new Comparator\NumberComparator($size);
69345
69346 return $this;
69347 }
69348
69349
69350
69351
69352
69353
69354
69355
69356
69357
69358
69359
69360
69361
69362 public function exclude($dirs)
69363 {
69364 $this->exclude = array_merge($this->exclude, (array) $dirs);
69365
69366 return $this;
69367 }
69368
69369
69370
69371
69372
69373
69374
69375
69376
69377
69378
69379
69380 public function ignoreDotFiles($ignoreDotFiles)
69381 {
69382 if ($ignoreDotFiles) {
69383 $this->ignore |= static::IGNORE_DOT_FILES;
69384 } else {
69385 $this->ignore &= ~static::IGNORE_DOT_FILES;
69386 }
69387
69388 return $this;
69389 }
69390
69391
69392
69393
69394
69395
69396
69397
69398
69399
69400
69401
69402 public function ignoreVCS($ignoreVCS)
69403 {
69404 if ($ignoreVCS) {
69405 $this->ignore |= static::IGNORE_VCS_FILES;
69406 } else {
69407 $this->ignore &= ~static::IGNORE_VCS_FILES;
69408 }
69409
69410 return $this;
69411 }
69412
69413
69414
69415
69416
69417
69418
69419
69420 public static function addVCSPattern($pattern)
69421 {
69422 foreach ((array) $pattern as $p) {
69423 self::$vcsPatterns[] = $p;
69424 }
69425
69426 self::$vcsPatterns = array_unique(self::$vcsPatterns);
69427 }
69428
69429
69430
69431
69432
69433
69434
69435
69436
69437
69438
69439
69440 public function sort(\Closure $closure)
69441 {
69442 $this->sort = $closure;
69443
69444 return $this;
69445 }
69446
69447
69448
69449
69450
69451
69452
69453
69454
69455
69456 public function sortByName()
69457 {
69458 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
69459
69460 return $this;
69461 }
69462
69463
69464
69465
69466
69467
69468
69469
69470
69471
69472 public function sortByType()
69473 {
69474 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
69475
69476 return $this;
69477 }
69478
69479
69480
69481
69482
69483
69484
69485
69486
69487
69488
69489
69490 public function sortByAccessedTime()
69491 {
69492 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
69493
69494 return $this;
69495 }
69496
69497
69498
69499
69500
69501
69502
69503
69504
69505
69506
69507
69508
69509
69510 public function sortByChangedTime()
69511 {
69512 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
69513
69514 return $this;
69515 }
69516
69517
69518
69519
69520
69521
69522
69523
69524
69525
69526
69527
69528 public function sortByModifiedTime()
69529 {
69530 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
69531
69532 return $this;
69533 }
69534
69535
69536
69537
69538
69539
69540
69541
69542
69543
69544
69545 public function filter(\Closure $closure)
69546 {
69547 $this->filters[] = $closure;
69548
69549 return $this;
69550 }
69551
69552
69553
69554
69555
69556
69557 public function followLinks()
69558 {
69559 $this->followLinks = true;
69560
69561 return $this;
69562 }
69563
69564
69565
69566
69567
69568
69569
69570
69571
69572
69573 public function ignoreUnreadableDirs($ignore = true)
69574 {
69575 $this->ignoreUnreadableDirs = (bool) $ignore;
69576
69577 return $this;
69578 }
69579
69580
69581
69582
69583
69584
69585
69586
69587
69588
69589 public function in($dirs)
69590 {
69591 $resolvedDirs = array();
69592
69593 foreach ((array) $dirs as $dir) {
69594 if (is_dir($dir)) {
69595 $resolvedDirs[] = $this->normalizeDir($dir);
69596 } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
69597 $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob));
69598 } else {
69599 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
69600 }
69601 }
69602
69603 $this->dirs = array_merge($this->dirs, $resolvedDirs);
69604
69605 return $this;
69606 }
69607
69608
69609
69610
69611
69612
69613
69614
69615
69616
69617 public function getIterator()
69618 {
69619 if (0 === \count($this->dirs) && 0 === \count($this->iterators)) {
69620 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
69621 }
69622
69623 if (1 === \count($this->dirs) && 0 === \count($this->iterators)) {
69624 return $this->searchInDirectory($this->dirs[0]);
69625 }
69626
69627 $iterator = new \AppendIterator();
69628 foreach ($this->dirs as $dir) {
69629 $iterator->append($this->searchInDirectory($dir));
69630 }
69631
69632 foreach ($this->iterators as $it) {
69633 $iterator->append($it);
69634 }
69635
69636 return $iterator;
69637 }
69638
69639
69640
69641
69642
69643
69644
69645
69646
69647
69648
69649
69650 public function append($iterator)
69651 {
69652 if ($iterator instanceof \IteratorAggregate) {
69653 $this->iterators[] = $iterator->getIterator();
69654 } elseif ($iterator instanceof \Iterator) {
69655 $this->iterators[] = $iterator;
69656 } elseif ($iterator instanceof \Traversable || \is_array($iterator)) {
69657 $it = new \ArrayIterator();
69658 foreach ($iterator as $file) {
69659 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
69660 }
69661 $this->iterators[] = $it;
69662 } else {
69663 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
69664 }
69665
69666 return $this;
69667 }
69668
69669
69670
69671
69672
69673
69674 public function count()
69675 {
69676 return iterator_count($this->getIterator());
69677 }
69678
69679
69680
69681
69682 private function sortAdapters()
69683 {
69684 uasort($this->adapters, function (array $a, array $b) {
69685 if ($a['selected'] || $b['selected']) {
69686 return $a['selected'] ? -1 : 1;
69687 }
69688
69689 return $a['priority'] > $b['priority'] ? -1 : 1;
69690 });
69691
69692 return $this;
69693 }
69694
69695
69696
69697
69698
69699
69700 private function searchInDirectory($dir)
69701 {
69702 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
69703 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
69704 }
69705
69706 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
69707 $this->notPaths[] = '#(^|/)\..+(/|$)#';
69708 }
69709
69710 if ($this->adapters) {
69711 foreach ($this->adapters as $adapter) {
69712 if ($adapter['adapter']->isSupported()) {
69713 try {
69714 return $this
69715 ->buildAdapter($adapter['adapter'])
69716 ->searchInDirectory($dir);
69717 } catch (ExceptionInterface $e) {
69718 }
69719 }
69720 }
69721 }
69722
69723 $minDepth = 0;
69724 $maxDepth = PHP_INT_MAX;
69725
69726 foreach ($this->depths as $comparator) {
69727 switch ($comparator->getOperator()) {
69728 case '>':
69729 $minDepth = $comparator->getTarget() + 1;
69730 break;
69731 case '>=':
69732 $minDepth = $comparator->getTarget();
69733 break;
69734 case '<':
69735 $maxDepth = $comparator->getTarget() - 1;
69736 break;
69737 case '<=':
69738 $maxDepth = $comparator->getTarget();
69739 break;
69740 default:
69741 $minDepth = $maxDepth = $comparator->getTarget();
69742 }
69743 }
69744
69745 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
69746
69747 if ($this->followLinks) {
69748 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
69749 }
69750
69751 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
69752
69753 if ($this->exclude) {
69754 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
69755 }
69756
69757 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
69758
69759 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
69760 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
69761 }
69762
69763 if ($this->mode) {
69764 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
69765 }
69766
69767 if ($this->names || $this->notNames) {
69768 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
69769 }
69770
69771 if ($this->contains || $this->notContains) {
69772 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
69773 }
69774
69775 if ($this->sizes) {
69776 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
69777 }
69778
69779 if ($this->dates) {
69780 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
69781 }
69782
69783 if ($this->filters) {
69784 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
69785 }
69786
69787 if ($this->paths || $this->notPaths) {
69788 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
69789 }
69790
69791 if ($this->sort) {
69792 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
69793 $iterator = $iteratorAggregate->getIterator();
69794 }
69795
69796 return $iterator;
69797 }
69798
69799
69800
69801
69802 private function buildAdapter(AdapterInterface $adapter)
69803 {
69804 return $adapter
69805 ->setFollowLinks($this->followLinks)
69806 ->setDepths($this->depths)
69807 ->setMode($this->mode)
69808 ->setExclude($this->exclude)
69809 ->setNames($this->names)
69810 ->setNotNames($this->notNames)
69811 ->setContains($this->contains)
69812 ->setNotContains($this->notContains)
69813 ->setSizes($this->sizes)
69814 ->setDates($this->dates)
69815 ->setFilters($this->filters)
69816 ->setSort($this->sort)
69817 ->setPath($this->paths)
69818 ->setNotPath($this->notPaths)
69819 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
69820 }
69821
69822
69823
69824
69825 private function resetAdapterSelection()
69826 {
69827 $this->adapters = array_map(function (array $properties) {
69828 $properties['selected'] = false;
69829
69830 return $properties;
69831 }, $this->adapters);
69832 }
69833
69834 private function initDefaultAdapters()
69835 {
69836 if (null === $this->adapters) {
69837 $this->adapters = array();
69838 $this
69839 ->addAdapter(new GnuFindAdapter())
69840 ->addAdapter(new BsdFindAdapter())
69841 ->addAdapter(new PhpAdapter(), -50)
69842 ->setAdapter('php')
69843 ;
69844 }
69845 }
69846
69847
69848
69849
69850
69851
69852
69853
69854 private function normalizeDir($dir)
69855 {
69856 return rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
69857 }
69858 }
69859 <?php
69860
69861
69862
69863
69864
69865
69866
69867
69868
69869
69870 namespace Symfony\Component\Finder;
69871
69872
69873
69874
69875
69876
69877
69878
69879
69880
69881
69882
69883
69884
69885
69886
69887
69888
69889
69890
69891
69892
69893
69894 class Glob
69895 {
69896
69897
69898
69899
69900
69901
69902
69903
69904
69905
69906 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
69907 {
69908 $firstByte = true;
69909 $escaping = false;
69910 $inCurlies = 0;
69911 $regex = '';
69912 $sizeGlob = \strlen($glob);
69913 for ($i = 0; $i < $sizeGlob; ++$i) {
69914 $car = $glob[$i];
69915 if ($firstByte) {
69916 if ($strictLeadingDot && '.' !== $car) {
69917 $regex .= '(?=[^\.])';
69918 }
69919
69920 $firstByte = false;
69921 }
69922
69923 if ('/' === $car) {
69924 $firstByte = true;
69925 }
69926
69927 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
69928 $regex .= "\\$car";
69929 } elseif ('*' === $car) {
69930 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
69931 } elseif ('?' === $car) {
69932 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
69933 } elseif ('{' === $car) {
69934 $regex .= $escaping ? '\\{' : '(';
69935 if (!$escaping) {
69936 ++$inCurlies;
69937 }
69938 } elseif ('}' === $car && $inCurlies) {
69939 $regex .= $escaping ? '}' : ')';
69940 if (!$escaping) {
69941 --$inCurlies;
69942 }
69943 } elseif (',' === $car && $inCurlies) {
69944 $regex .= $escaping ? ',' : '|';
69945 } elseif ('\\' === $car) {
69946 if ($escaping) {
69947 $regex .= '\\\\';
69948 $escaping = false;
69949 } else {
69950 $escaping = true;
69951 }
69952
69953 continue;
69954 } else {
69955 $regex .= $car;
69956 }
69957 $escaping = false;
69958 }
69959
69960 return $delimiter.'^'.$regex.'$'.$delimiter;
69961 }
69962 }
69963 <?php
69964
69965
69966
69967
69968
69969
69970
69971
69972
69973
69974 namespace Symfony\Component\Finder\Iterator;
69975
69976
69977
69978
69979
69980
69981
69982
69983
69984 class CustomFilterIterator extends FilterIterator
69985 {
69986 private $filters = array();
69987
69988
69989
69990
69991
69992
69993
69994 public function __construct(\Iterator $iterator, array $filters)
69995 {
69996 foreach ($filters as $filter) {
69997 if (!\is_callable($filter)) {
69998 throw new \InvalidArgumentException('Invalid PHP callback.');
69999 }
70000 }
70001 $this->filters = $filters;
70002
70003 parent::__construct($iterator);
70004 }
70005
70006
70007
70008
70009
70010
70011 public function accept()
70012 {
70013 $fileinfo = $this->current();
70014
70015 foreach ($this->filters as $filter) {
70016 if (false === \call_user_func($filter, $fileinfo)) {
70017 return false;
70018 }
70019 }
70020
70021 return true;
70022 }
70023 }
70024 <?php
70025
70026
70027
70028
70029
70030
70031
70032
70033
70034
70035 namespace Symfony\Component\Finder\Iterator;
70036
70037 use Symfony\Component\Finder\Comparator\DateComparator;
70038
70039
70040
70041
70042
70043
70044 class DateRangeFilterIterator extends FilterIterator
70045 {
70046 private $comparators = array();
70047
70048
70049
70050
70051
70052 public function __construct(\Iterator $iterator, array $comparators)
70053 {
70054 $this->comparators = $comparators;
70055
70056 parent::__construct($iterator);
70057 }
70058
70059
70060
70061
70062
70063
70064 public function accept()
70065 {
70066 $fileinfo = $this->current();
70067
70068 if (!file_exists($fileinfo->getPathname())) {
70069 return false;
70070 }
70071
70072 $filedate = $fileinfo->getMTime();
70073 foreach ($this->comparators as $compare) {
70074 if (!$compare->test($filedate)) {
70075 return false;
70076 }
70077 }
70078
70079 return true;
70080 }
70081 }
70082 <?php
70083
70084
70085
70086
70087
70088
70089
70090
70091
70092
70093 namespace Symfony\Component\Finder\Iterator;
70094
70095
70096
70097
70098
70099
70100 class DepthRangeFilterIterator extends FilterIterator
70101 {
70102 private $minDepth = 0;
70103
70104
70105
70106
70107
70108
70109 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
70110 {
70111 $this->minDepth = $minDepth;
70112 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
70113
70114 parent::__construct($iterator);
70115 }
70116
70117
70118
70119
70120
70121
70122 public function accept()
70123 {
70124 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
70125 }
70126 }
70127 <?php
70128
70129
70130
70131
70132
70133
70134
70135
70136
70137
70138 namespace Symfony\Component\Finder\Iterator;
70139
70140
70141
70142
70143
70144
70145 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
70146 {
70147 private $iterator;
70148 private $isRecursive;
70149 private $excludedDirs = array();
70150 private $excludedPattern;
70151
70152
70153
70154
70155
70156 public function __construct(\Iterator $iterator, array $directories)
70157 {
70158 $this->iterator = $iterator;
70159 $this->isRecursive = $iterator instanceof \RecursiveIterator;
70160 $patterns = array();
70161 foreach ($directories as $directory) {
70162 $directory = rtrim($directory, '/');
70163 if (!$this->isRecursive || false !== strpos($directory, '/')) {
70164 $patterns[] = preg_quote($directory, '#');
70165 } else {
70166 $this->excludedDirs[$directory] = true;
70167 }
70168 }
70169 if ($patterns) {
70170 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
70171 }
70172
70173 parent::__construct($iterator);
70174 }
70175
70176
70177
70178
70179
70180
70181 public function accept()
70182 {
70183 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
70184 return false;
70185 }
70186
70187 if ($this->excludedPattern) {
70188 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
70189 $path = str_replace('\\', '/', $path);
70190
70191 return !preg_match($this->excludedPattern, $path);
70192 }
70193
70194 return true;
70195 }
70196
70197 public function hasChildren()
70198 {
70199 return $this->isRecursive && $this->iterator->hasChildren();
70200 }
70201
70202 public function getChildren()
70203 {
70204 $children = new self($this->iterator->getChildren(), array());
70205 $children->excludedDirs = $this->excludedDirs;
70206 $children->excludedPattern = $this->excludedPattern;
70207
70208 return $children;
70209 }
70210 }
70211 <?php
70212
70213
70214
70215
70216
70217
70218
70219
70220
70221
70222 namespace Symfony\Component\Finder\Iterator;
70223
70224 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70225
70226 use Symfony\Component\Finder\SplFileInfo;
70227
70228
70229
70230
70231
70232
70233
70234
70235 class FilePathsIterator extends \ArrayIterator
70236 {
70237
70238
70239
70240 private $baseDir;
70241
70242
70243
70244
70245 private $baseDirLength;
70246
70247
70248
70249
70250 private $subPath;
70251
70252
70253
70254
70255 private $subPathname;
70256
70257
70258
70259
70260 private $current;
70261
70262
70263
70264
70265
70266 public function __construct(array $paths, $baseDir)
70267 {
70268 $this->baseDir = $baseDir;
70269 $this->baseDirLength = \strlen($baseDir);
70270
70271 parent::__construct($paths);
70272 }
70273
70274
70275
70276
70277
70278
70279
70280 public function __call($name, array $arguments)
70281 {
70282 return \call_user_func_array(array($this->current(), $name), $arguments);
70283 }
70284
70285
70286
70287
70288
70289
70290 public function current()
70291 {
70292 return $this->current;
70293 }
70294
70295
70296
70297
70298 public function key()
70299 {
70300 return $this->current->getPathname();
70301 }
70302
70303 public function next()
70304 {
70305 parent::next();
70306 $this->buildProperties();
70307 }
70308
70309 public function rewind()
70310 {
70311 parent::rewind();
70312 $this->buildProperties();
70313 }
70314
70315
70316
70317
70318 public function getSubPath()
70319 {
70320 return $this->subPath;
70321 }
70322
70323
70324
70325
70326 public function getSubPathname()
70327 {
70328 return $this->subPathname;
70329 }
70330
70331 private function buildProperties()
70332 {
70333 $absolutePath = parent::current();
70334
70335 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
70336 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
70337 $dir = \dirname($this->subPathname);
70338 $this->subPath = '.' === $dir ? '' : $dir;
70339 } else {
70340 $this->subPath = $this->subPathname = '';
70341 }
70342
70343 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
70344 }
70345 }
70346 <?php
70347
70348
70349
70350
70351
70352
70353
70354
70355
70356
70357 namespace Symfony\Component\Finder\Iterator;
70358
70359
70360
70361
70362
70363
70364 class FileTypeFilterIterator extends FilterIterator
70365 {
70366 const ONLY_FILES = 1;
70367 const ONLY_DIRECTORIES = 2;
70368
70369 private $mode;
70370
70371
70372
70373
70374
70375 public function __construct(\Iterator $iterator, $mode)
70376 {
70377 $this->mode = $mode;
70378
70379 parent::__construct($iterator);
70380 }
70381
70382
70383
70384
70385
70386
70387 public function accept()
70388 {
70389 $fileinfo = $this->current();
70390 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
70391 return false;
70392 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
70393 return false;
70394 }
70395
70396 return true;
70397 }
70398 }
70399 <?php
70400
70401
70402
70403
70404
70405
70406
70407
70408
70409
70410 namespace Symfony\Component\Finder\Iterator;
70411
70412
70413
70414
70415
70416
70417
70418 class FilecontentFilterIterator extends MultiplePcreFilterIterator
70419 {
70420
70421
70422
70423
70424
70425 public function accept()
70426 {
70427 if (!$this->matchRegexps && !$this->noMatchRegexps) {
70428 return true;
70429 }
70430
70431 $fileinfo = $this->current();
70432
70433 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
70434 return false;
70435 }
70436
70437 $content = $fileinfo->getContents();
70438 if (!$content) {
70439 return false;
70440 }
70441
70442 return $this->isAccepted($content);
70443 }
70444
70445
70446
70447
70448
70449
70450
70451
70452 protected function toRegex($str)
70453 {
70454 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
70455 }
70456 }
70457 <?php
70458
70459
70460
70461
70462
70463
70464
70465
70466
70467
70468 namespace Symfony\Component\Finder\Iterator;
70469
70470 use Symfony\Component\Finder\Glob;
70471
70472
70473
70474
70475
70476
70477 class FilenameFilterIterator extends MultiplePcreFilterIterator
70478 {
70479
70480
70481
70482
70483
70484 public function accept()
70485 {
70486 return $this->isAccepted($this->current()->getFilename());
70487 }
70488
70489
70490
70491
70492
70493
70494
70495
70496
70497
70498
70499 protected function toRegex($str)
70500 {
70501 return $this->isRegex($str) ? $str : Glob::toRegex($str);
70502 }
70503 }
70504 <?php
70505
70506
70507
70508
70509
70510
70511
70512
70513
70514
70515 namespace Symfony\Component\Finder\Iterator;
70516
70517
70518
70519
70520
70521
70522
70523
70524
70525 abstract class FilterIterator extends \FilterIterator
70526 {
70527
70528
70529
70530
70531
70532
70533 public function rewind()
70534 {
70535 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
70536 parent::rewind();
70537
70538 return;
70539 }
70540
70541 $iterator = $this;
70542 while ($iterator instanceof \OuterIterator) {
70543 $innerIterator = $iterator->getInnerIterator();
70544
70545 if ($innerIterator instanceof RecursiveDirectoryIterator) {
70546
70547  if ($innerIterator->isRewindable()) {
70548 $innerIterator->next();
70549 $innerIterator->rewind();
70550 }
70551 } elseif ($innerIterator instanceof \FilesystemIterator) {
70552 $innerIterator->next();
70553 $innerIterator->rewind();
70554 }
70555
70556 $iterator = $innerIterator;
70557 }
70558
70559 parent::rewind();
70560 }
70561 }
70562 <?php
70563
70564
70565
70566
70567
70568
70569
70570
70571
70572
70573 namespace Symfony\Component\Finder\Iterator;
70574
70575
70576
70577
70578
70579
70580 abstract class MultiplePcreFilterIterator extends FilterIterator
70581 {
70582 protected $matchRegexps = array();
70583 protected $noMatchRegexps = array();
70584
70585
70586
70587
70588
70589
70590 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
70591 {
70592 foreach ($matchPatterns as $pattern) {
70593 $this->matchRegexps[] = $this->toRegex($pattern);
70594 }
70595
70596 foreach ($noMatchPatterns as $pattern) {
70597 $this->noMatchRegexps[] = $this->toRegex($pattern);
70598 }
70599
70600 parent::__construct($iterator);
70601 }
70602
70603
70604
70605
70606
70607
70608
70609
70610
70611
70612
70613
70614 protected function isAccepted($string)
70615 {
70616
70617  foreach ($this->noMatchRegexps as $regex) {
70618 if (preg_match($regex, $string)) {
70619 return false;
70620 }
70621 }
70622
70623
70624  if ($this->matchRegexps) {
70625 foreach ($this->matchRegexps as $regex) {
70626 if (preg_match($regex, $string)) {
70627 return true;
70628 }
70629 }
70630
70631 return false;
70632 }
70633
70634
70635  return true;
70636 }
70637
70638
70639
70640
70641
70642
70643
70644
70645 protected function isRegex($str)
70646 {
70647 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
70648 $start = substr($m[1], 0, 1);
70649 $end = substr($m[1], -1);
70650
70651 if ($start === $end) {
70652 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
70653 }
70654
70655 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
70656 if ($start === $delimiters[0] && $end === $delimiters[1]) {
70657 return true;
70658 }
70659 }
70660 }
70661
70662 return false;
70663 }
70664
70665
70666
70667
70668
70669
70670
70671
70672 abstract protected function toRegex($str);
70673 }
70674 <?php
70675
70676
70677
70678
70679
70680
70681
70682
70683
70684
70685 namespace Symfony\Component\Finder\Iterator;
70686
70687
70688
70689
70690
70691
70692
70693 class PathFilterIterator extends MultiplePcreFilterIterator
70694 {
70695
70696
70697
70698
70699
70700 public function accept()
70701 {
70702 $filename = $this->current()->getRelativePathname();
70703
70704 if ('\\' === \DIRECTORY_SEPARATOR) {
70705 $filename = str_replace('\\', '/', $filename);
70706 }
70707
70708 return $this->isAccepted($filename);
70709 }
70710
70711
70712
70713
70714
70715
70716
70717
70718
70719
70720
70721
70722
70723
70724
70725 protected function toRegex($str)
70726 {
70727 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
70728 }
70729 }
70730 <?php
70731
70732
70733
70734
70735
70736
70737
70738
70739
70740
70741 namespace Symfony\Component\Finder\Iterator;
70742
70743 use Symfony\Component\Finder\Exception\AccessDeniedException;
70744 use Symfony\Component\Finder\SplFileInfo;
70745
70746
70747
70748
70749
70750
70751 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
70752 {
70753
70754
70755
70756 private $ignoreUnreadableDirs;
70757
70758
70759
70760
70761 private $rewindable;
70762
70763
70764  private $rootPath;
70765 private $subPath;
70766 private $directorySeparator = '/';
70767
70768
70769
70770
70771
70772
70773
70774
70775 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
70776 {
70777 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
70778 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
70779 }
70780
70781 parent::__construct($path, $flags);
70782 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
70783 $this->rootPath = (string) $path;
70784 if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
70785 $this->directorySeparator = \DIRECTORY_SEPARATOR;
70786 }
70787 }
70788
70789
70790
70791
70792
70793
70794 public function current()
70795 {
70796
70797
70798 if (null === $subPathname = $this->subPath) {
70799 $subPathname = $this->subPath = (string) $this->getSubPath();
70800 }
70801 if ('' !== $subPathname) {
70802 $subPathname .= $this->directorySeparator;
70803 }
70804 $subPathname .= $this->getFilename();
70805
70806 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
70807 }
70808
70809
70810
70811
70812
70813
70814 public function getChildren()
70815 {
70816 try {
70817 $children = parent::getChildren();
70818
70819 if ($children instanceof self) {
70820
70821  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
70822
70823
70824  $children->rewindable = &$this->rewindable;
70825 $children->rootPath = $this->rootPath;
70826 }
70827
70828 return $children;
70829 } catch (\UnexpectedValueException $e) {
70830 if ($this->ignoreUnreadableDirs) {
70831
70832  return new \RecursiveArrayIterator(array());
70833 } else {
70834 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
70835 }
70836 }
70837 }
70838
70839
70840
70841
70842 public function rewind()
70843 {
70844 if (false === $this->isRewindable()) {
70845 return;
70846 }
70847
70848
70849  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
70850 parent::next();
70851 }
70852
70853 parent::rewind();
70854 }
70855
70856
70857
70858
70859
70860
70861 public function isRewindable()
70862 {
70863 if (null !== $this->rewindable) {
70864 return $this->rewindable;
70865 }
70866
70867
70868  if ('' === $this->getPath()) {
70869 return $this->rewindable = false;
70870 }
70871
70872 if (false !== $stream = @opendir($this->getPath())) {
70873 $infos = stream_get_meta_data($stream);
70874 closedir($stream);
70875
70876 if ($infos['seekable']) {
70877 return $this->rewindable = true;
70878 }
70879 }
70880
70881 return $this->rewindable = false;
70882 }
70883 }
70884 <?php
70885
70886
70887
70888
70889
70890
70891
70892
70893
70894
70895 namespace Symfony\Component\Finder\Iterator;
70896
70897 use Symfony\Component\Finder\Comparator\NumberComparator;
70898
70899
70900
70901
70902
70903
70904 class SizeRangeFilterIterator extends FilterIterator
70905 {
70906 private $comparators = array();
70907
70908
70909
70910
70911
70912 public function __construct(\Iterator $iterator, array $comparators)
70913 {
70914 $this->comparators = $comparators;
70915
70916 parent::__construct($iterator);
70917 }
70918
70919
70920
70921
70922
70923
70924 public function accept()
70925 {
70926 $fileinfo = $this->current();
70927 if (!$fileinfo->isFile()) {
70928 return true;
70929 }
70930
70931 $filesize = $fileinfo->getSize();
70932 foreach ($this->comparators as $compare) {
70933 if (!$compare->test($filesize)) {
70934 return false;
70935 }
70936 }
70937
70938 return true;
70939 }
70940 }
70941 <?php
70942
70943
70944
70945
70946
70947
70948
70949
70950
70951
70952 namespace Symfony\Component\Finder\Iterator;
70953
70954
70955
70956
70957
70958
70959 class SortableIterator implements \IteratorAggregate
70960 {
70961 const SORT_BY_NAME = 1;
70962 const SORT_BY_TYPE = 2;
70963 const SORT_BY_ACCESSED_TIME = 3;
70964 const SORT_BY_CHANGED_TIME = 4;
70965 const SORT_BY_MODIFIED_TIME = 5;
70966
70967 private $iterator;
70968 private $sort;
70969
70970
70971
70972
70973
70974
70975
70976 public function __construct(\Traversable $iterator, $sort)
70977 {
70978 $this->iterator = $iterator;
70979
70980 if (self::SORT_BY_NAME === $sort) {
70981 $this->sort = function ($a, $b) {
70982 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
70983 };
70984 } elseif (self::SORT_BY_TYPE === $sort) {
70985 $this->sort = function ($a, $b) {
70986 if ($a->isDir() && $b->isFile()) {
70987 return -1;
70988 } elseif ($a->isFile() && $b->isDir()) {
70989 return 1;
70990 }
70991
70992 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
70993 };
70994 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
70995 $this->sort = function ($a, $b) {
70996 return $a->getATime() - $b->getATime();
70997 };
70998 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
70999 $this->sort = function ($a, $b) {
71000 return $a->getCTime() - $b->getCTime();
71001 };
71002 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
71003 $this->sort = function ($a, $b) {
71004 return $a->getMTime() - $b->getMTime();
71005 };
71006 } elseif (\is_callable($sort)) {
71007 $this->sort = $sort;
71008 } else {
71009 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
71010 }
71011 }
71012
71013 public function getIterator()
71014 {
71015 $array = iterator_to_array($this->iterator, true);
71016 uasort($array, $this->sort);
71017
71018 return new \ArrayIterator($array);
71019 }
71020 }
71021 Copyright (c) 2004-2018 Fabien Potencier
71022
71023 Permission is hereby granted, free of charge, to any person obtaining a copy
71024 of this software and associated documentation files (the "Software"), to deal
71025 in the Software without restriction, including without limitation the rights
71026 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71027 copies of the Software, and to permit persons to whom the Software is furnished
71028 to do so, subject to the following conditions:
71029
71030 The above copyright notice and this permission notice shall be included in all
71031 copies or substantial portions of the Software.
71032
71033 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71034 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71035 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71036 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71037 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71038 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71039 THE SOFTWARE.
71040 <?php
71041
71042
71043
71044
71045
71046
71047
71048
71049
71050
71051 namespace Symfony\Component\Finder\Shell;
71052
71053 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71054
71055
71056
71057
71058
71059
71060 class Command
71061 {
71062 private $parent;
71063 private $bits = array();
71064 private $labels = array();
71065
71066
71067
71068
71069 private $errorHandler;
71070
71071 public function __construct(Command $parent = null)
71072 {
71073 $this->parent = $parent;
71074 }
71075
71076
71077
71078
71079
71080
71081 public function __toString()
71082 {
71083 return $this->join();
71084 }
71085
71086
71087
71088
71089
71090
71091 public static function create(Command $parent = null)
71092 {
71093 return new self($parent);
71094 }
71095
71096
71097
71098
71099
71100
71101
71102
71103 public static function escape($input)
71104 {
71105 return escapeshellcmd($input);
71106 }
71107
71108
71109
71110
71111
71112
71113
71114
71115 public static function quote($input)
71116 {
71117 return escapeshellarg($input);
71118 }
71119
71120
71121
71122
71123
71124
71125
71126
71127 public function add($bit)
71128 {
71129 $this->bits[] = $bit;
71130
71131 return $this;
71132 }
71133
71134
71135
71136
71137
71138
71139
71140
71141 public function top($bit)
71142 {
71143 array_unshift($this->bits, $bit);
71144
71145 foreach ($this->labels as $label => $index) {
71146 ++$this->labels[$label];
71147 }
71148
71149 return $this;
71150 }
71151
71152
71153
71154
71155
71156
71157
71158
71159 public function arg($arg)
71160 {
71161 $this->bits[] = self::quote($arg);
71162
71163 return $this;
71164 }
71165
71166
71167
71168
71169
71170
71171
71172
71173 public function cmd($esc)
71174 {
71175 $this->bits[] = self::escape($esc);
71176
71177 return $this;
71178 }
71179
71180
71181
71182
71183
71184
71185
71186
71187
71188
71189 public function ins($label)
71190 {
71191 if (isset($this->labels[$label])) {
71192 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
71193 }
71194
71195 $this->bits[] = self::create($this);
71196 $this->labels[$label] = \count($this->bits) - 1;
71197
71198 return $this->bits[$this->labels[$label]];
71199 }
71200
71201
71202
71203
71204
71205
71206
71207
71208
71209
71210 public function get($label)
71211 {
71212 if (!isset($this->labels[$label])) {
71213 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
71214 }
71215
71216 return $this->bits[$this->labels[$label]];
71217 }
71218
71219
71220
71221
71222
71223
71224
71225
71226 public function end()
71227 {
71228 if (null === $this->parent) {
71229 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
71230 }
71231
71232 return $this->parent;
71233 }
71234
71235
71236
71237
71238
71239
71240 public function length()
71241 {
71242 return \count($this->bits);
71243 }
71244
71245
71246
71247
71248 public function setErrorHandler(\Closure $errorHandler)
71249 {
71250 $this->errorHandler = $errorHandler;
71251
71252 return $this;
71253 }
71254
71255
71256
71257
71258 public function getErrorHandler()
71259 {
71260 return $this->errorHandler;
71261 }
71262
71263
71264
71265
71266
71267
71268
71269
71270 public function execute()
71271 {
71272 if (null === $errorHandler = $this->errorHandler) {
71273 exec($this->join(), $output);
71274 } else {
71275 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
71276 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
71277
71278 if ($error = stream_get_contents($pipes[2])) {
71279 $errorHandler($error);
71280 }
71281
71282 proc_close($process);
71283 }
71284
71285 return $output ?: array();
71286 }
71287
71288
71289
71290
71291
71292
71293 public function join()
71294 {
71295 return implode(' ', array_filter(
71296 array_map(function ($bit) {
71297 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
71298 }, $this->bits),
71299 function ($bit) { return null !== $bit; }
71300 ));
71301 }
71302
71303
71304
71305
71306
71307
71308
71309
71310
71311 public function addAtIndex($bit, $index)
71312 {
71313 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
71314
71315 return $this;
71316 }
71317 }
71318 <?php
71319
71320
71321
71322
71323
71324
71325
71326
71327
71328
71329 namespace Symfony\Component\Finder\Shell;
71330
71331 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71332
71333
71334
71335
71336
71337
71338 class Shell
71339 {
71340 const TYPE_UNIX = 1;
71341 const TYPE_DARWIN = 2;
71342 const TYPE_CYGWIN = 3;
71343 const TYPE_WINDOWS = 4;
71344 const TYPE_BSD = 5;
71345
71346
71347
71348
71349 private $type;
71350
71351
71352
71353
71354
71355
71356 public function getType()
71357 {
71358 if (null === $this->type) {
71359 $this->type = $this->guessType();
71360 }
71361
71362 return $this->type;
71363 }
71364
71365
71366
71367
71368
71369
71370
71371
71372 public function testCommand($command)
71373 {
71374 if (!\function_exists('exec')) {
71375 return false;
71376 }
71377
71378
71379  $testCommand = 'which ';
71380 if (self::TYPE_WINDOWS === $this->type) {
71381 $testCommand = 'where ';
71382 }
71383
71384 $command = escapeshellcmd($command);
71385
71386 exec($testCommand.$command, $output, $code);
71387
71388 return 0 === $code && \count($output) > 0;
71389 }
71390
71391
71392
71393
71394
71395
71396 private function guessType()
71397 {
71398 $os = strtolower(PHP_OS);
71399
71400 if (false !== strpos($os, 'cygwin')) {
71401 return self::TYPE_CYGWIN;
71402 }
71403
71404 if (false !== strpos($os, 'darwin')) {
71405 return self::TYPE_DARWIN;
71406 }
71407
71408 if (false !== strpos($os, 'bsd')) {
71409 return self::TYPE_BSD;
71410 }
71411
71412 if (0 === strpos($os, 'win')) {
71413 return self::TYPE_WINDOWS;
71414 }
71415
71416 return self::TYPE_UNIX;
71417 }
71418 }
71419 <?php
71420
71421
71422
71423
71424
71425
71426
71427
71428
71429
71430 namespace Symfony\Component\Finder;
71431
71432
71433
71434
71435
71436
71437 class SplFileInfo extends \SplFileInfo
71438 {
71439 private $relativePath;
71440 private $relativePathname;
71441
71442
71443
71444
71445
71446
71447 public function __construct($file, $relativePath, $relativePathname)
71448 {
71449 parent::__construct($file);
71450 $this->relativePath = $relativePath;
71451 $this->relativePathname = $relativePathname;
71452 }
71453
71454
71455
71456
71457
71458
71459
71460
71461 public function getRelativePath()
71462 {
71463 return $this->relativePath;
71464 }
71465
71466
71467
71468
71469
71470
71471
71472
71473 public function getRelativePathname()
71474 {
71475 return $this->relativePathname;
71476 }
71477
71478
71479
71480
71481
71482
71483
71484
71485 public function getContents()
71486 {
71487 set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
71488 $content = file_get_contents($this->getPathname());
71489 restore_error_handler();
71490 if (false === $content) {
71491 throw new \RuntimeException($error);
71492 }
71493
71494 return $content;
71495 }
71496 }
71497 <?php
71498
71499
71500
71501
71502
71503
71504
71505
71506
71507
71508 namespace Symfony\Polyfill\Ctype;
71509
71510
71511
71512
71513
71514
71515
71516
71517 final class Ctype
71518 {
71519
71520
71521
71522
71523
71524
71525
71526
71527
71528 public static function ctype_alnum($text)
71529 {
71530 $text = self::convert_int_to_char_for_ctype($text);
71531
71532 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
71533 }
71534
71535
71536
71537
71538
71539
71540
71541
71542
71543
71544 public static function ctype_alpha($text)
71545 {
71546 $text = self::convert_int_to_char_for_ctype($text);
71547
71548 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
71549 }
71550
71551
71552
71553
71554
71555
71556
71557
71558
71559
71560 public static function ctype_cntrl($text)
71561 {
71562 $text = self::convert_int_to_char_for_ctype($text);
71563
71564 return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
71565 }
71566
71567
71568
71569
71570
71571
71572
71573
71574
71575
71576 public static function ctype_digit($text)
71577 {
71578 $text = self::convert_int_to_char_for_ctype($text);
71579
71580 return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
71581 }
71582
71583
71584
71585
71586
71587
71588
71589
71590
71591
71592 public static function ctype_graph($text)
71593 {
71594 $text = self::convert_int_to_char_for_ctype($text);
71595
71596 return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
71597 }
71598
71599
71600
71601
71602
71603
71604
71605
71606
71607
71608 public static function ctype_lower($text)
71609 {
71610 $text = self::convert_int_to_char_for_ctype($text);
71611
71612 return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
71613 }
71614
71615
71616
71617
71618
71619
71620
71621
71622
71623
71624 public static function ctype_print($text)
71625 {
71626 $text = self::convert_int_to_char_for_ctype($text);
71627
71628 return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
71629 }
71630
71631
71632
71633
71634
71635
71636
71637
71638
71639
71640 public static function ctype_punct($text)
71641 {
71642 $text = self::convert_int_to_char_for_ctype($text);
71643
71644 return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
71645 }
71646
71647
71648
71649
71650
71651
71652
71653
71654
71655
71656 public static function ctype_space($text)
71657 {
71658 $text = self::convert_int_to_char_for_ctype($text);
71659
71660 return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
71661 }
71662
71663
71664
71665
71666
71667
71668
71669
71670
71671
71672 public static function ctype_upper($text)
71673 {
71674 $text = self::convert_int_to_char_for_ctype($text);
71675
71676 return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
71677 }
71678
71679
71680
71681
71682
71683
71684
71685
71686
71687
71688 public static function ctype_xdigit($text)
71689 {
71690 $text = self::convert_int_to_char_for_ctype($text);
71691
71692 return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
71693 }
71694
71695
71696
71697
71698
71699
71700
71701
71702
71703
71704
71705
71706
71707 private static function convert_int_to_char_for_ctype($int)
71708 {
71709 if (!\is_int($int)) {
71710 return $int;
71711 }
71712
71713 if ($int < -128 || $int > 255) {
71714 return (string) $int;
71715 }
71716
71717 if ($int < 0) {
71718 $int += 256;
71719 }
71720
71721 return \chr($int);
71722 }
71723 }
71724 Copyright (c) 2018-2019 Fabien Potencier
71725
71726 Permission is hereby granted, free of charge, to any person obtaining a copy
71727 of this software and associated documentation files (the "Software"), to deal
71728 in the Software without restriction, including without limitation the rights
71729 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71730 copies of the Software, and to permit persons to whom the Software is furnished
71731 to do so, subject to the following conditions:
71732
71733 The above copyright notice and this permission notice shall be included in all
71734 copies or substantial portions of the Software.
71735
71736 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71737 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71738 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71739 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71740 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71741 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71742 THE SOFTWARE.
71743 <?php
71744
71745
71746
71747
71748
71749
71750
71751
71752
71753
71754 use Symfony\Polyfill\Ctype as p;
71755
71756 if (!function_exists('ctype_alnum')) {
71757 function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
71758 function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
71759 function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
71760 function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
71761 function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
71762 function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
71763 function ctype_print($text) { return p\Ctype::ctype_print($text); }
71764 function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
71765 function ctype_space($text) { return p\Ctype::ctype_space($text); }
71766 function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
71767 function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
71768 }
71769 Copyright (c) 2015-2019 Fabien Potencier
71770
71771 Permission is hereby granted, free of charge, to any person obtaining a copy
71772 of this software and associated documentation files (the "Software"), to deal
71773 in the Software without restriction, including without limitation the rights
71774 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71775 copies of the Software, and to permit persons to whom the Software is furnished
71776 to do so, subject to the following conditions:
71777
71778 The above copyright notice and this permission notice shall be included in all
71779 copies or substantial portions of the Software.
71780
71781 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71782 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71783 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71784 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71785 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71786 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71787 THE SOFTWARE.
71788 <?php
71789
71790
71791
71792
71793
71794
71795
71796
71797
71798
71799 namespace Symfony\Polyfill\Mbstring;
71800
71801
71802
71803
71804
71805
71806
71807
71808
71809
71810
71811
71812
71813
71814
71815
71816
71817
71818
71819
71820
71821
71822
71823
71824
71825
71826
71827
71828
71829
71830
71831
71832
71833
71834
71835
71836
71837
71838
71839
71840
71841
71842
71843
71844
71845
71846
71847
71848
71849
71850
71851
71852
71853
71854
71855 final class Mbstring
71856 {
71857 const MB_CASE_FOLD = PHP_INT_MAX;
71858
71859 private static $encodingList = array('ASCII', 'UTF-8');
71860 private static $language = 'neutral';
71861 private static $internalEncoding = 'UTF-8';
71862 private static $caseFold = array(
71863 array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"),
71864 array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'),
71865 );
71866
71867 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
71868 {
71869 if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
71870 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
71871 } else {
71872 $fromEncoding = self::getEncoding($fromEncoding);
71873 }
71874
71875 $toEncoding = self::getEncoding($toEncoding);
71876
71877 if ('BASE64' === $fromEncoding) {
71878 $s = base64_decode($s);
71879 $fromEncoding = $toEncoding;
71880 }
71881
71882 if ('BASE64' === $toEncoding) {
71883 return base64_encode($s);
71884 }
71885
71886 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
71887 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
71888 $fromEncoding = 'Windows-1252';
71889 }
71890 if ('UTF-8' !== $fromEncoding) {
71891 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
71892 }
71893
71894 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
71895 }
71896
71897 if ('HTML-ENTITIES' === $fromEncoding) {
71898 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
71899 $fromEncoding = 'UTF-8';
71900 }
71901
71902 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
71903 }
71904
71905 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
71906 {
71907 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
71908
71909 $ok = true;
71910 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
71911 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
71912 $ok = false;
71913 }
71914 });
71915
71916 return $ok ? $fromEncoding : false;
71917 }
71918
71919 public static function mb_decode_mimeheader($s)
71920 {
71921 return iconv_mime_decode($s, 2, self::$internalEncoding);
71922 }
71923
71924 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
71925 {
71926 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
71927 }
71928
71929 public static function mb_decode_numericentity($s, $convmap, $encoding = null)
71930 {
71931 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
71932 trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
71933
71934 return null;
71935 }
71936
71937 if (!\is_array($convmap) || !$convmap) {
71938 return false;
71939 }
71940
71941 if (null !== $encoding && !\is_scalar($encoding)) {
71942 trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
71943
71944 return ''; 
71945  }
71946
71947 $s = (string) $s;
71948 if ('' === $s) {
71949 return '';
71950 }
71951
71952 $encoding = self::getEncoding($encoding);
71953
71954 if ('UTF-8' === $encoding) {
71955 $encoding = null;
71956 if (!preg_match('//u', $s)) {
71957 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
71958 }
71959 } else {
71960 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
71961 }
71962
71963 $cnt = floor(\count($convmap) / 4) * 4;
71964
71965 for ($i = 0; $i < $cnt; $i += 4) {
71966
71967  $convmap[$i] += $convmap[$i + 2];
71968 $convmap[$i + 1] += $convmap[$i + 2];
71969 }
71970
71971 $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
71972 $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
71973 for ($i = 0; $i < $cnt; $i += 4) {
71974 if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
71975 return Mbstring::mb_chr($c - $convmap[$i + 2]);
71976 }
71977 }
71978
71979 return $m[0];
71980 }, $s);
71981
71982 if (null === $encoding) {
71983 return $s;
71984 }
71985
71986 return iconv('UTF-8', $encoding.'//IGNORE', $s);
71987 }
71988
71989 public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
71990 {
71991 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
71992 trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
71993
71994 return null;
71995 }
71996
71997 if (!\is_array($convmap) || !$convmap) {
71998 return false;
71999 }
72000
72001 if (null !== $encoding && !\is_scalar($encoding)) {
72002 trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
72003
72004 return null; 
72005  }
72006
72007 if (null !== $is_hex && !\is_scalar($is_hex)) {
72008 trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING);
72009
72010 return null;
72011 }
72012
72013 $s = (string) $s;
72014 if ('' === $s) {
72015 return '';
72016 }
72017
72018 $encoding = self::getEncoding($encoding);
72019
72020 if ('UTF-8' === $encoding) {
72021 $encoding = null;
72022 if (!preg_match('//u', $s)) {
72023 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
72024 }
72025 } else {
72026 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
72027 }
72028
72029 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
72030
72031 $cnt = floor(\count($convmap) / 4) * 4;
72032 $i = 0;
72033 $len = \strlen($s);
72034 $result = '';
72035
72036 while ($i < $len) {
72037 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
72038 $uchr = substr($s, $i, $ulen);
72039 $i += $ulen;
72040 $c = self::mb_ord($uchr);
72041
72042 for ($j = 0; $j < $cnt; $j += 4) {
72043 if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
72044 $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
72045 $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
72046 continue 2;
72047 }
72048 }
72049 $result .= $uchr;
72050 }
72051
72052 if (null === $encoding) {
72053 return $result;
72054 }
72055
72056 return iconv('UTF-8', $encoding.'//IGNORE', $result);
72057 }
72058
72059 public static function mb_convert_case($s, $mode, $encoding = null)
72060 {
72061 $s = (string) $s;
72062 if ('' === $s) {
72063 return '';
72064 }
72065
72066 $encoding = self::getEncoding($encoding);
72067
72068 if ('UTF-8' === $encoding) {
72069 $encoding = null;
72070 if (!preg_match('//u', $s)) {
72071 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
72072 }
72073 } else {
72074 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
72075 }
72076
72077 if (MB_CASE_TITLE == $mode) {
72078 static $titleRegexp = null;
72079 if (null === $titleRegexp) {
72080 $titleRegexp = self::getData('titleCaseRegexp');
72081 }
72082 $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s);
72083 } else {
72084 if (MB_CASE_UPPER == $mode) {
72085 static $upper = null;
72086 if (null === $upper) {
72087 $upper = self::getData('upperCase');
72088 }
72089 $map = $upper;
72090 } else {
72091 if (self::MB_CASE_FOLD === $mode) {
72092 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
72093 }
72094
72095 static $lower = null;
72096 if (null === $lower) {
72097 $lower = self::getData('lowerCase');
72098 }
72099 $map = $lower;
72100 }
72101
72102 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
72103
72104 $i = 0;
72105 $len = \strlen($s);
72106
72107 while ($i < $len) {
72108 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
72109 $uchr = substr($s, $i, $ulen);
72110 $i += $ulen;
72111
72112 if (isset($map[$uchr])) {
72113 $uchr = $map[$uchr];
72114 $nlen = \strlen($uchr);
72115
72116 if ($nlen == $ulen) {
72117 $nlen = $i;
72118 do {
72119 $s[--$nlen] = $uchr[--$ulen];
72120 } while ($ulen);
72121 } else {
72122 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
72123 $len += $nlen - $ulen;
72124 $i += $nlen - $ulen;
72125 }
72126 }
72127 }
72128 }
72129
72130 if (null === $encoding) {
72131 return $s;
72132 }
72133
72134 return iconv('UTF-8', $encoding.'//IGNORE', $s);
72135 }
72136
72137 public static function mb_internal_encoding($encoding = null)
72138 {
72139 if (null === $encoding) {
72140 return self::$internalEncoding;
72141 }
72142
72143 $encoding = self::getEncoding($encoding);
72144
72145 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
72146 self::$internalEncoding = $encoding;
72147
72148 return true;
72149 }
72150
72151 return false;
72152 }
72153
72154 public static function mb_language($lang = null)
72155 {
72156 if (null === $lang) {
72157 return self::$language;
72158 }
72159
72160 switch ($lang = strtolower($lang)) {
72161 case 'uni':
72162 case 'neutral':
72163 self::$language = $lang;
72164
72165 return true;
72166 }
72167
72168 return false;
72169 }
72170
72171 public static function mb_list_encodings()
72172 {
72173 return array('UTF-8');
72174 }
72175
72176 public static function mb_encoding_aliases($encoding)
72177 {
72178 switch (strtoupper($encoding)) {
72179 case 'UTF8':
72180 case 'UTF-8':
72181 return array('utf8');
72182 }
72183
72184 return false;
72185 }
72186
72187 public static function mb_check_encoding($var = null, $encoding = null)
72188 {
72189 if (null === $encoding) {
72190 if (null === $var) {
72191 return false;
72192 }
72193 $encoding = self::$internalEncoding;
72194 }
72195
72196 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
72197 }
72198
72199 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
72200 {
72201 if (null === $encodingList) {
72202 $encodingList = self::$encodingList;
72203 } else {
72204 if (!\is_array($encodingList)) {
72205 $encodingList = array_map('trim', explode(',', $encodingList));
72206 }
72207 $encodingList = array_map('strtoupper', $encodingList);
72208 }
72209
72210 foreach ($encodingList as $enc) {
72211 switch ($enc) {
72212 case 'ASCII':
72213 if (!preg_match('/[\x80-\xFF]/', $str)) {
72214 return $enc;
72215 }
72216 break;
72217
72218 case 'UTF8':
72219 case 'UTF-8':
72220 if (preg_match('//u', $str)) {
72221 return 'UTF-8';
72222 }
72223 break;
72224
72225 default:
72226 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
72227 return $enc;
72228 }
72229 }
72230 }
72231
72232 return false;
72233 }
72234
72235 public static function mb_detect_order($encodingList = null)
72236 {
72237 if (null === $encodingList) {
72238 return self::$encodingList;
72239 }
72240
72241 if (!\is_array($encodingList)) {
72242 $encodingList = array_map('trim', explode(',', $encodingList));
72243 }
72244 $encodingList = array_map('strtoupper', $encodingList);
72245
72246 foreach ($encodingList as $enc) {
72247 switch ($enc) {
72248 default:
72249 if (strncmp($enc, 'ISO-8859-', 9)) {
72250 return false;
72251 }
72252
72253  case 'ASCII':
72254 case 'UTF8':
72255 case 'UTF-8':
72256 }
72257 }
72258
72259 self::$encodingList = $encodingList;
72260
72261 return true;
72262 }
72263
72264 public static function mb_strlen($s, $encoding = null)
72265 {
72266 $encoding = self::getEncoding($encoding);
72267 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72268 return \strlen($s);
72269 }
72270
72271 return @iconv_strlen($s, $encoding);
72272 }
72273
72274 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
72275 {
72276 $encoding = self::getEncoding($encoding);
72277 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72278 return strpos($haystack, $needle, $offset);
72279 }
72280
72281 $needle = (string) $needle;
72282 if ('' === $needle) {
72283 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
72284
72285 return false;
72286 }
72287
72288 return iconv_strpos($haystack, $needle, $offset, $encoding);
72289 }
72290
72291 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
72292 {
72293 $encoding = self::getEncoding($encoding);
72294 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72295 return strrpos($haystack, $needle, $offset);
72296 }
72297
72298 if ($offset != (int) $offset) {
72299 $offset = 0;
72300 } elseif ($offset = (int) $offset) {
72301 if ($offset < 0) {
72302 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
72303 $offset = 0;
72304 } else {
72305 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
72306 }
72307 }
72308
72309 $pos = iconv_strrpos($haystack, $needle, $encoding);
72310
72311 return false !== $pos ? $offset + $pos : false;
72312 }
72313
72314 public static function mb_str_split($string, $split_length = 1, $encoding = null)
72315 {
72316 if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
72317 trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING);
72318
72319 return null;
72320 }
72321
72322 if ($split_length < 1) {
72323 trigger_error('The length of each segment must be greater than zero', E_USER_WARNING);
72324
72325 return false;
72326 }
72327
72328 if (null === $encoding) {
72329 $encoding = mb_internal_encoding();
72330 }
72331
72332 $result = array();
72333 $length = mb_strlen($string, $encoding);
72334
72335 for ($i = 0; $i < $length; $i += $split_length) {
72336 $result[] = mb_substr($string, $i, $split_length, $encoding);
72337 }
72338
72339 return $result;
72340 }
72341
72342 public static function mb_strtolower($s, $encoding = null)
72343 {
72344 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
72345 }
72346
72347 public static function mb_strtoupper($s, $encoding = null)
72348 {
72349 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
72350 }
72351
72352 public static function mb_substitute_character($c = null)
72353 {
72354 if (0 === strcasecmp($c, 'none')) {
72355 return true;
72356 }
72357
72358 return null !== $c ? false : 'none';
72359 }
72360
72361 public static function mb_substr($s, $start, $length = null, $encoding = null)
72362 {
72363 $encoding = self::getEncoding($encoding);
72364 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72365 return (string) substr($s, $start, null === $length ? 2147483647 : $length);
72366 }
72367
72368 if ($start < 0) {
72369 $start = iconv_strlen($s, $encoding) + $start;
72370 if ($start < 0) {
72371 $start = 0;
72372 }
72373 }
72374
72375 if (null === $length) {
72376 $length = 2147483647;
72377 } elseif ($length < 0) {
72378 $length = iconv_strlen($s, $encoding) + $length - $start;
72379 if ($length < 0) {
72380 return '';
72381 }
72382 }
72383
72384 return (string) iconv_substr($s, $start, $length, $encoding);
72385 }
72386
72387 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
72388 {
72389 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
72390 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
72391
72392 return self::mb_strpos($haystack, $needle, $offset, $encoding);
72393 }
72394
72395 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
72396 {
72397 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
72398
72399 return self::getSubpart($pos, $part, $haystack, $encoding);
72400 }
72401
72402 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
72403 {
72404 $encoding = self::getEncoding($encoding);
72405 if ('CP850' === $encoding || 'ASCII' === $encoding) {
72406 return strrchr($haystack, $needle, $part);
72407 }
72408 $needle = self::mb_substr($needle, 0, 1, $encoding);
72409 $pos = iconv_strrpos($haystack, $needle, $encoding);
72410
72411 return self::getSubpart($pos, $part, $haystack, $encoding);
72412 }
72413
72414 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
72415 {
72416 $needle = self::mb_substr($needle, 0, 1, $encoding);
72417 $pos = self::mb_strripos($haystack, $needle, $encoding);
72418
72419 return self::getSubpart($pos, $part, $haystack, $encoding);
72420 }
72421
72422 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
72423 {
72424 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
72425 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
72426
72427 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
72428 }
72429
72430 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
72431 {
72432 $pos = strpos($haystack, $needle);
72433 if (false === $pos) {
72434 return false;
72435 }
72436 if ($part) {
72437 return substr($haystack, 0, $pos);
72438 }
72439
72440 return substr($haystack, $pos);
72441 }
72442
72443 public static function mb_get_info($type = 'all')
72444 {
72445 $info = array(
72446 'internal_encoding' => self::$internalEncoding,
72447 'http_output' => 'pass',
72448 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
72449 'func_overload' => 0,
72450 'func_overload_list' => 'no overload',
72451 'mail_charset' => 'UTF-8',
72452 'mail_header_encoding' => 'BASE64',
72453 'mail_body_encoding' => 'BASE64',
72454 'illegal_chars' => 0,
72455 'encoding_translation' => 'Off',
72456 'language' => self::$language,
72457 'detect_order' => self::$encodingList,
72458 'substitute_character' => 'none',
72459 'strict_detection' => 'Off',
72460 );
72461
72462 if ('all' === $type) {
72463 return $info;
72464 }
72465 if (isset($info[$type])) {
72466 return $info[$type];
72467 }
72468
72469 return false;
72470 }
72471
72472 public static function mb_http_input($type = '')
72473 {
72474 return false;
72475 }
72476
72477 public static function mb_http_output($encoding = null)
72478 {
72479 return null !== $encoding ? 'pass' === $encoding : 'pass';
72480 }
72481
72482 public static function mb_strwidth($s, $encoding = null)
72483 {
72484 $encoding = self::getEncoding($encoding);
72485
72486 if ('UTF-8' !== $encoding) {
72487 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
72488 }
72489
72490 $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);
72491
72492 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
72493 }
72494
72495 public static function mb_substr_count($haystack, $needle, $encoding = null)
72496 {
72497 return substr_count($haystack, $needle);
72498 }
72499
72500 public static function mb_output_handler($contents, $status)
72501 {
72502 return $contents;
72503 }
72504
72505 public static function mb_chr($code, $encoding = null)
72506 {
72507 if (0x80 > $code %= 0x200000) {
72508 $s = \chr($code);
72509 } elseif (0x800 > $code) {
72510 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
72511 } elseif (0x10000 > $code) {
72512 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
72513 } else {
72514 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
72515 }
72516
72517 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
72518 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
72519 }
72520
72521 return $s;
72522 }
72523
72524 public static function mb_ord($s, $encoding = null)
72525 {
72526 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
72527 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
72528 }
72529
72530 if (1 === \strlen($s)) {
72531 return \ord($s);
72532 }
72533
72534 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
72535 if (0xF0 <= $code) {
72536 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
72537 }
72538 if (0xE0 <= $code) {
72539 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
72540 }
72541 if (0xC0 <= $code) {
72542 return (($code - 0xC0) << 6) + $s[2] - 0x80;
72543 }
72544
72545 return $code;
72546 }
72547
72548 private static function getSubpart($pos, $part, $haystack, $encoding)
72549 {
72550 if (false === $pos) {
72551 return false;
72552 }
72553 if ($part) {
72554 return self::mb_substr($haystack, 0, $pos, $encoding);
72555 }
72556
72557 return self::mb_substr($haystack, $pos, null, $encoding);
72558 }
72559
72560 private static function html_encoding_callback(array $m)
72561 {
72562 $i = 1;
72563 $entities = '';
72564 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
72565
72566 while (isset($m[$i])) {
72567 if (0x80 > $m[$i]) {
72568 $entities .= \chr($m[$i++]);
72569 continue;
72570 }
72571 if (0xF0 <= $m[$i]) {
72572 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
72573 } elseif (0xE0 <= $m[$i]) {
72574 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
72575 } else {
72576 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
72577 }
72578
72579 $entities .= '&#'.$c.';';
72580 }
72581
72582 return $entities;
72583 }
72584
72585 private static function title_case(array $s)
72586 {
72587 return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8');
72588 }
72589
72590 private static function getData($file)
72591 {
72592 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
72593 return require $file;
72594 }
72595
72596 return false;
72597 }
72598
72599 private static function getEncoding($encoding)
72600 {
72601 if (null === $encoding) {
72602 return self::$internalEncoding;
72603 }
72604
72605 $encoding = strtoupper($encoding);
72606
72607 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
72608 return 'CP850';
72609 }
72610 if ('UTF8' === $encoding) {
72611 return 'UTF-8';
72612 }
72613
72614 return $encoding;
72615 }
72616 }
72617 <?php
72618
72619 return array(
72620 'A' => 'a',
72621 'B' => 'b',
72622 'C' => 'c',
72623 'D' => 'd',
72624 'E' => 'e',
72625 'F' => 'f',
72626 'G' => 'g',
72627 'H' => 'h',
72628 'I' => 'i',
72629 'J' => 'j',
72630 'K' => 'k',
72631 'L' => 'l',
72632 'M' => 'm',
72633 'N' => 'n',
72634 'O' => 'o',
72635 'P' => 'p',
72636 'Q' => 'q',
72637 'R' => 'r',
72638 'S' => 's',
72639 'T' => 't',
72640 'U' => 'u',
72641 'V' => 'v',
72642 'W' => 'w',
72643 'X' => 'x',
72644 'Y' => 'y',
72645 'Z' => 'z',
72646 'À' => 'à',
72647 'Á' => 'á',
72648 'Â' => 'â',
72649 'Ã' => 'ã',
72650 'Ä' => 'ä',
72651 'Å' => 'å',
72652 'Æ' => 'æ',
72653 'Ç' => 'ç',
72654 'È' => 'è',
72655 'É' => 'é',
72656 'Ê' => 'ê',
72657 'Ë' => 'ë',
72658 'Ì' => 'ì',
72659 'Í' => 'í',
72660 'Î' => 'î',
72661 'Ï' => 'ï',
72662 'Ð' => 'ð',
72663 'Ñ' => 'ñ',
72664 'Ò' => 'ò',
72665 'Ó' => 'ó',
72666 'Ô' => 'ô',
72667 'Õ' => 'õ',
72668 'Ö' => 'ö',
72669 'Ø' => 'ø',
72670 'Ù' => 'ù',
72671 'Ú' => 'ú',
72672 'Û' => 'û',
72673 'Ü' => 'ü',
72674 'Ý' => 'ý',
72675 'Þ' => 'þ',
72676 'Ā' => 'ā',
72677 'Ă' => 'ă',
72678 'Ą' => 'ą',
72679 'Ć' => 'ć',
72680 'Ĉ' => 'ĉ',
72681 'Ċ' => 'ċ',
72682 'Č' => 'č',
72683 'Ď' => 'ď',
72684 'Đ' => 'đ',
72685 'Ē' => 'ē',
72686 'Ĕ' => 'ĕ',
72687 'Ė' => 'ė',
72688 'Ę' => 'ę',
72689 'Ě' => 'ě',
72690 'Ĝ' => 'ĝ',
72691 'Ğ' => 'ğ',
72692 'Ġ' => 'ġ',
72693 'Ģ' => 'ģ',
72694 'Ĥ' => 'ĥ',
72695 'Ħ' => 'ħ',
72696 'Ĩ' => 'ĩ',
72697 'Ī' => 'ī',
72698 'Ĭ' => 'ĭ',
72699 'Į' => 'į',
72700 'İ' => 'i',
72701 'IJ' => 'ij',
72702 'Ĵ' => 'ĵ',
72703 'Ķ' => 'ķ',
72704 'Ĺ' => 'ĺ',
72705 'Ļ' => 'ļ',
72706 'Ľ' => 'ľ',
72707 'Ŀ' => 'ŀ',
72708 'Ł' => 'ł',
72709 'Ń' => 'ń',
72710 'Ņ' => 'ņ',
72711 'Ň' => 'ň',
72712 'Ŋ' => 'ŋ',
72713 'Ō' => 'ō',
72714 'Ŏ' => 'ŏ',
72715 'Ő' => 'ő',
72716 'Œ' => 'œ',
72717 'Ŕ' => 'ŕ',
72718 'Ŗ' => 'ŗ',
72719 'Ř' => 'ř',
72720 'Ś' => 'ś',
72721 'Ŝ' => 'ŝ',
72722 'Ş' => 'ş',
72723 'Š' => 'š',
72724 'Ţ' => 'ţ',
72725 'Ť' => 'ť',
72726 'Ŧ' => 'ŧ',
72727 'Ũ' => 'ũ',
72728 'Ū' => 'ū',
72729 'Ŭ' => 'ŭ',
72730 'Ů' => 'ů',
72731 'Ű' => 'ű',
72732 'Ų' => 'ų',
72733 'Ŵ' => 'ŵ',
72734 'Ŷ' => 'ŷ',
72735 'Ÿ' => 'ÿ',
72736 'Ź' => 'ź',
72737 'Ż' => 'ż',
72738 'Ž' => 'ž',
72739 'Ɓ' => 'ɓ',
72740 'Ƃ' => 'ƃ',
72741 'Ƅ' => 'ƅ',
72742 'Ɔ' => 'ɔ',
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 'DŽ' => 'dž',
72776 'Dž' => 'dž',
72777 'LJ' => 'lj',
72778 'Lj' => 'lj',
72779 'NJ' => 'nj',
72780 'Nj' => 'nj',
72781 'Ǎ' => 'ǎ',
72782 'Ǐ' => 'ǐ',
72783 'Ǒ' => 'ǒ',
72784 'Ǔ' => 'ǔ',
72785 'Ǖ' => 'ǖ',
72786 'Ǘ' => 'ǘ',
72787 'Ǚ' => 'ǚ',
72788 'Ǜ' => 'ǜ',
72789 'Ǟ' => 'ǟ',
72790 'Ǡ' => 'ǡ',
72791 'Ǣ' => 'ǣ',
72792 'Ǥ' => 'ǥ',
72793 'Ǧ' => 'ǧ',
72794 'Ǩ' => 'ǩ',
72795 'Ǫ' => 'ǫ',
72796 'Ǭ' => 'ǭ',
72797 'Ǯ' => 'ǯ',
72798 'DZ' => 'dz',
72799 'Dz' => 'dz',
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 'Π' => 'π',
72873 'Ρ' => 'ρ',
72874 'Σ' => 'σ',
72875 'Τ' => 'τ',
72876 'Υ' => 'υ',
72877 'Φ' => 'φ',
72878 'Χ' => 'χ',
72879 'Ψ' => 'ψ',
72880 'Ω' => 'ω',
72881 'Ϊ' => 'ϊ',
72882 'Ϋ' => 'ϋ',
72883 'Ϗ' => 'ϗ',
72884 'Ϙ' => 'ϙ',
72885 'Ϛ' => 'ϛ',
72886 'Ϝ' => 'ϝ',
72887 'Ϟ' => 'ϟ',
72888 'Ϡ' => 'ϡ',
72889 'Ϣ' => 'ϣ',
72890 'Ϥ' => 'ϥ',
72891 'Ϧ' => 'ϧ',
72892 'Ϩ' => 'ϩ',
72893 'Ϫ' => 'ϫ',
72894 'Ϭ' => 'ϭ',
72895 'Ϯ' => 'ϯ',
72896 'ϴ' => 'θ',
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 'K' => 'k',
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 'Ⱨ' => 'ⱨ',
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 'A' => 'a',
73615 'B' => 'b',
73616 'C' => 'c',
73617 'D' => 'd',
73618 'E' => 'e',
73619 'F' => 'f',
73620 'G' => 'g',
73621 'H' => 'h',
73622 'I' => 'i',
73623 'J' => 'j',
73624 'K' => 'k',
73625 'L' => 'l',
73626 'M' => 'm',
73627 'N' => 'n',
73628 'O' => 'o',
73629 'P' => 'p',
73630 'Q' => 'q',
73631 'R' => 'r',
73632 'S' => 's',
73633 'T' => 't',
73634 'U' => 'u',
73635 'V' => 'v',
73636 'W' => 'w',
73637 'X' => 'x',
73638 'Y' => 'y',
73639 'Z' => 'z',
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 '𑢿' => '𑣟',
73712 );
73713 <?php
73714
73715
73716
73717 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';
73718 <?php
73719
73720 return array(
73721 'a' => 'A',
73722 'b' => 'B',
73723 'c' => 'C',
73724 'd' => 'D',
73725 'e' => 'E',
73726 'f' => 'F',
73727 'g' => 'G',
73728 'h' => 'H',
73729 'i' => 'I',
73730 'j' => 'J',
73731 'k' => 'K',
73732 'l' => 'L',
73733 'm' => 'M',
73734 'n' => 'N',
73735 'o' => 'O',
73736 'p' => 'P',
73737 'q' => 'Q',
73738 'r' => 'R',
73739 's' => 'S',
73740 't' => 'T',
73741 'u' => 'U',
73742 'v' => 'V',
73743 'w' => 'W',
73744 'x' => 'X',
73745 'y' => 'Y',
73746 'z' => 'Z',
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 'ı' => 'I',
73804 'ij' => 'IJ',
73805 'ĵ' => 'Ĵ',
73806 'ķ' => 'Ķ',
73807 'ĺ' => 'Ĺ',
73808 'ļ' => 'Ļ',
73809 'ľ' => 'Ľ',
73810 'ŀ' => 'Ŀ',
73811 'ł' => 'Ł',
73812 'ń' => 'Ń',
73813 'ņ' => 'Ņ',
73814 'ň' => 'Ň',
73815 'ŋ' => 'Ŋ',
73816 'ō' => 'Ō',
73817 'ŏ' => 'Ŏ',
73818 'ő' => 'Ő',
73819 'œ' => 'Œ',
73820 'ŕ' => 'Ŕ',
73821 'ŗ' => 'Ŗ',
73822 'ř' => 'Ř',
73823 'ś' => 'Ś',
73824 'ŝ' => 'Ŝ',
73825 'ş' => 'Ş',
73826 'š' => 'Š',
73827 'ţ' => 'Ţ',
73828 'ť' => 'Ť',
73829 'ŧ' => 'Ŧ',
73830 'ũ' => 'Ũ',
73831 'ū' => 'Ū',
73832 'ŭ' => 'Ŭ',
73833 'ů' => 'Ů',
73834 'ű' => 'Ű',
73835 'ų' => 'Ų',
73836 'ŵ' => 'Ŵ',
73837 'ŷ' => 'Ŷ',
73838 'ź' => 'Ź',
73839 'ż' => 'Ż',
73840 'ž' => 'Ž',
73841 'ſ' => 'S',
73842 'ƀ' => 'Ƀ',
73843 'ƃ' => 'Ƃ',
73844 'ƅ' => 'Ƅ',
73845 'ƈ' => 'Ƈ',
73846 'ƌ' => 'Ƌ',
73847 'ƒ' => 'Ƒ',
73848 'ƕ' => 'Ƕ',
73849 'ƙ' => 'Ƙ',
73850 'ƚ' => 'Ƚ',
73851 'ƞ' => 'Ƞ',
73852 'ơ' => 'Ơ',
73853 'ƣ' => 'Ƣ',
73854 'ƥ' => 'Ƥ',
73855 'ƨ' => 'Ƨ',
73856 'ƭ' => 'Ƭ',
73857 'ư' => 'Ư',
73858 'ƴ' => 'Ƴ',
73859 'ƶ' => 'Ƶ',
73860 'ƹ' => 'Ƹ',
73861 'ƽ' => 'Ƽ',
73862 'ƿ' => 'Ƿ',
73863 'Dž' => 'DŽ',
73864 'dž' => 'DŽ',
73865 'Lj' => 'LJ',
73866 'lj' => 'LJ',
73867 'Nj' => 'NJ',
73868 'nj' => 'NJ',
73869 'ǎ' => 'Ǎ',
73870 'ǐ' => 'Ǐ',
73871 'ǒ' => 'Ǒ',
73872 'ǔ' => 'Ǔ',
73873 'ǖ' => 'Ǖ',
73874 'ǘ' => 'Ǘ',
73875 'ǚ' => 'Ǚ',
73876 'ǜ' => 'Ǜ',
73877 'ǝ' => 'Ǝ',
73878 'ǟ' => 'Ǟ',
73879 'ǡ' => 'Ǡ',
73880 'ǣ' => 'Ǣ',
73881 'ǥ' => 'Ǥ',
73882 'ǧ' => 'Ǧ',
73883 'ǩ' => 'Ǩ',
73884 'ǫ' => 'Ǫ',
73885 'ǭ' => 'Ǭ',
73886 'ǯ' => 'Ǯ',
73887 'Dz' => 'DZ',
73888 'dz' => 'DZ',
73889 'ǵ' => 'Ǵ',
73890 'ǹ' => 'Ǹ',
73891 'ǻ' => 'Ǻ',
73892 'ǽ' => 'Ǽ',
73893 'ǿ' => 'Ǿ',
73894 'ȁ' => 'Ȁ',
73895 'ȃ' => 'Ȃ',
73896 'ȅ' => 'Ȅ',
73897 'ȇ' => 'Ȇ',
73898 'ȉ' => 'Ȉ',
73899 'ȋ' => 'Ȋ',
73900 'ȍ' => 'Ȍ',
73901 'ȏ' => 'Ȏ',
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 'ɠ' => 'Ɠ',
73939 'ɡ' => 'Ɡ',
73940 'ɣ' => 'Ɣ',
73941 'ɥ' => 'Ɥ',
73942 'ɦ' => 'Ɦ',
73943 'ɨ' => 'Ɨ',
73944 'ɩ' => 'Ɩ',
73945 'ɫ' => 'Ɫ',
73946 'ɬ' => 'Ɬ',
73947 'ɯ' => 'Ɯ',
73948 'ɱ' => 'Ɱ',
73949 'ɲ' => 'Ɲ',
73950 'ɵ' => 'Ɵ',
73951 'ɽ' => 'Ɽ',
73952 'ʀ' => 'Ʀ',
73953 'ʃ' => 'Ʃ',
73954 'ʇ' => 'Ʇ',
73955 'ʈ' => 'Ʈ',
73956 'ʉ' => 'Ʉ',
73957 'ʊ' => 'Ʊ',
73958 'ʋ' => 'Ʋ',
73959 'ʌ' => 'Ʌ',
73960 'ʒ' => 'Ʒ',
73961 'ʞ' => 'Ʞ',
73962 'ͅ' => 'Ι',
73963 'ͱ' => 'Ͱ',
73964 'ͳ' => 'Ͳ',
73965 'ͷ' => 'Ͷ',
73966 'ͻ' => 'Ͻ',
73967 'ͼ' => 'Ͼ',
73968 'ͽ' => 'Ͽ',
73969 'ά' => 'Ά',
73970 'έ' => 'Έ',
73971 'ή' => 'Ή',
73972 'ί' => 'Ί',
73973 'α' => 'Α',
73974 'β' => 'Β',
73975 'γ' => 'Γ',
73976 'δ' => 'Δ',
73977 'ε' => 'Ε',
73978 'ζ' => 'Ζ',
73979 'η' => 'Η',
73980 'θ' => 'Θ',
73981 'ι' => 'Ι',
73982 'κ' => 'Κ',
73983 'λ' => 'Λ',
73984 'μ' => 'Μ',
73985 'ν' => 'Ν',
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 'a' => 'A',
74724 'b' => 'B',
74725 'c' => 'C',
74726 'd' => 'D',
74727 'e' => 'E',
74728 'f' => 'F',
74729 'g' => 'G',
74730 'h' => 'H',
74731 'i' => 'I',
74732 'j' => 'J',
74733 'k' => 'K',
74734 'l' => 'L',
74735 'm' => 'M',
74736 'n' => 'N',
74737 'o' => 'O',
74738 'p' => 'P',
74739 'q' => 'Q',
74740 'r' => 'R',
74741 's' => 'S',
74742 't' => 'T',
74743 'u' => 'U',
74744 'v' => 'V',
74745 'w' => 'W',
74746 'x' => 'X',
74747 'y' => 'Y',
74748 'z' => 'Z',
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 '𑣟' => '𑢿',
74821 );
74822 <?php
74823
74824
74825
74826
74827
74828
74829
74830
74831
74832
74833 use Symfony\Polyfill\Mbstring as p;
74834
74835 if (!function_exists('mb_strlen')) {
74836 define('MB_CASE_UPPER', 0);
74837 define('MB_CASE_LOWER', 1);
74838 define('MB_CASE_TITLE', 2);
74839
74840 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
74841 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
74842 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
74843 function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
74844 function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
74845 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
74846 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
74847 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
74848 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
74849 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
74850 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
74851 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
74852 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
74853 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
74854 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
74855 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
74856 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
74857 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
74858 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
74859 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
74860 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
74861 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
74862 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
74863 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
74864 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
74865 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
74866 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
74867 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
74868 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
74869 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
74870 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
74871 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
74872 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
74873 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); }
74874 }
74875 if (!function_exists('mb_chr')) {
74876 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
74877 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
74878 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
74879 }
74880
74881 if (!function_exists('mb_str_split')) {
74882 function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
74883 }
74884 <?php
74885
74886
74887
74888
74889
74890
74891
74892
74893
74894
74895 namespace Symfony\Component\Process\Exception;
74896
74897
74898
74899
74900
74901
74902 interface ExceptionInterface
74903 {
74904 }
74905 <?php
74906
74907
74908
74909
74910
74911
74912
74913
74914
74915
74916 namespace Symfony\Component\Process\Exception;
74917
74918
74919
74920
74921
74922
74923 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
74924 {
74925 }
74926 <?php
74927
74928
74929
74930
74931
74932
74933
74934
74935
74936
74937 namespace Symfony\Component\Process\Exception;
74938
74939
74940
74941
74942
74943
74944 class LogicException extends \LogicException implements ExceptionInterface
74945 {
74946 }
74947 <?php
74948
74949
74950
74951
74952
74953
74954
74955
74956
74957
74958 namespace Symfony\Component\Process\Exception;
74959
74960 use Symfony\Component\Process\Process;
74961
74962
74963
74964
74965
74966
74967 class ProcessFailedException extends RuntimeException
74968 {
74969 private $process;
74970
74971 public function __construct(Process $process)
74972 {
74973 if ($process->isSuccessful()) {
74974 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
74975 }
74976
74977 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
74978 $process->getCommandLine(),
74979 $process->getExitCode(),
74980 $process->getExitCodeText(),
74981 $process->getWorkingDirectory()
74982 );
74983
74984 if (!$process->isOutputDisabled()) {
74985 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
74986 $process->getOutput(),
74987 $process->getErrorOutput()
74988 );
74989 }
74990
74991 parent::__construct($error);
74992
74993 $this->process = $process;
74994 }
74995
74996 public function getProcess()
74997 {
74998 return $this->process;
74999 }
75000 }
75001 <?php
75002
75003
75004
75005
75006
75007
75008
75009
75010
75011
75012 namespace Symfony\Component\Process\Exception;
75013
75014 use Symfony\Component\Process\Process;
75015
75016
75017
75018
75019
75020
75021 class ProcessTimedOutException extends RuntimeException
75022 {
75023 const TYPE_GENERAL = 1;
75024 const TYPE_IDLE = 2;
75025
75026 private $process;
75027 private $timeoutType;
75028
75029 public function __construct(Process $process, $timeoutType)
75030 {
75031 $this->process = $process;
75032 $this->timeoutType = $timeoutType;
75033
75034 parent::__construct(sprintf(
75035 'The process "%s" exceeded the timeout of %s seconds.',
75036 $process->getCommandLine(),
75037 $this->getExceededTimeout()
75038 ));
75039 }
75040
75041 public function getProcess()
75042 {
75043 return $this->process;
75044 }
75045
75046 public function isGeneralTimeout()
75047 {
75048 return self::TYPE_GENERAL === $this->timeoutType;
75049 }
75050
75051 public function isIdleTimeout()
75052 {
75053 return self::TYPE_IDLE === $this->timeoutType;
75054 }
75055
75056 public function getExceededTimeout()
75057 {
75058 switch ($this->timeoutType) {
75059 case self::TYPE_GENERAL:
75060 return $this->process->getTimeout();
75061
75062 case self::TYPE_IDLE:
75063 return $this->process->getIdleTimeout();
75064
75065 default:
75066 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
75067 }
75068 }
75069 }
75070 <?php
75071
75072
75073
75074
75075
75076
75077
75078
75079
75080
75081 namespace Symfony\Component\Process\Exception;
75082
75083
75084
75085
75086
75087
75088 class RuntimeException extends \RuntimeException implements ExceptionInterface
75089 {
75090 }
75091 <?php
75092
75093
75094
75095
75096
75097
75098
75099
75100
75101
75102 namespace Symfony\Component\Process;
75103
75104
75105
75106
75107
75108
75109
75110 class ExecutableFinder
75111 {
75112 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
75113
75114
75115
75116
75117 public function setSuffixes(array $suffixes)
75118 {
75119 $this->suffixes = $suffixes;
75120 }
75121
75122
75123
75124
75125
75126
75127 public function addSuffix($suffix)
75128 {
75129 $this->suffixes[] = $suffix;
75130 }
75131
75132
75133
75134
75135
75136
75137
75138
75139
75140
75141 public function find($name, $default = null, array $extraDirs = array())
75142 {
75143 if (ini_get('open_basedir')) {
75144 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
75145 $dirs = array();
75146 foreach ($searchPath as $path) {
75147
75148  if (@is_dir($path)) {
75149 $dirs[] = $path;
75150 } else {
75151 if (basename($path) == $name && @is_executable($path)) {
75152 return $path;
75153 }
75154 }
75155 }
75156 } else {
75157 $dirs = array_merge(
75158 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
75159 $extraDirs
75160 );
75161 }
75162
75163 $suffixes = array('');
75164 if ('\\' === \DIRECTORY_SEPARATOR) {
75165 $pathExt = getenv('PATHEXT');
75166 $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
75167 }
75168 foreach ($suffixes as $suffix) {
75169 foreach ($dirs as $dir) {
75170 if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
75171 return $file;
75172 }
75173 }
75174 }
75175
75176 return $default;
75177 }
75178 }
75179 Copyright (c) 2004-2018 Fabien Potencier
75180
75181 Permission is hereby granted, free of charge, to any person obtaining a copy
75182 of this software and associated documentation files (the "Software"), to deal
75183 in the Software without restriction, including without limitation the rights
75184 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75185 copies of the Software, and to permit persons to whom the Software is furnished
75186 to do so, subject to the following conditions:
75187
75188 The above copyright notice and this permission notice shall be included in all
75189 copies or substantial portions of the Software.
75190
75191 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75192 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75193 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75194 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75195 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75196 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75197 THE SOFTWARE.
75198 <?php
75199
75200
75201
75202
75203
75204
75205
75206
75207
75208
75209 namespace Symfony\Component\Process;
75210
75211
75212
75213
75214
75215
75216
75217 class PhpExecutableFinder
75218 {
75219 private $executableFinder;
75220
75221 public function __construct()
75222 {
75223 $this->executableFinder = new ExecutableFinder();
75224 }
75225
75226
75227
75228
75229
75230
75231
75232
75233 public function find($includeArgs = true)
75234 {
75235 $args = $this->findArguments();
75236 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
75237
75238
75239  if (\defined('HHVM_VERSION')) {
75240 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
75241 }
75242
75243
75244  if (\defined('PHP_BINARY') && PHP_BINARY && \in_array(\PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) {
75245 return PHP_BINARY.$args;
75246 }
75247
75248 if ($php = getenv('PHP_PATH')) {
75249 if (!@is_executable($php)) {
75250 return false;
75251 }
75252
75253 return $php;
75254 }
75255
75256 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
75257 if (@is_executable($php)) {
75258 return $php;
75259 }
75260 }
75261
75262 if (@is_executable($php = PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
75263 return $php;
75264 }
75265
75266 $dirs = array(PHP_BINDIR);
75267 if ('\\' === \DIRECTORY_SEPARATOR) {
75268 $dirs[] = 'C:\xampp\php\\';
75269 }
75270
75271 return $this->executableFinder->find('php', false, $dirs);
75272 }
75273
75274
75275
75276
75277
75278
75279 public function findArguments()
75280 {
75281 $arguments = array();
75282
75283 if (\defined('HHVM_VERSION')) {
75284 $arguments[] = '--php';
75285 } elseif ('phpdbg' === \PHP_SAPI) {
75286 $arguments[] = '-qrr';
75287 }
75288
75289 return $arguments;
75290 }
75291 }
75292 <?php
75293
75294
75295
75296
75297
75298
75299
75300
75301
75302
75303 namespace Symfony\Component\Process;
75304
75305 use Symfony\Component\Process\Exception\RuntimeException;
75306
75307
75308
75309
75310
75311
75312
75313
75314
75315
75316 class PhpProcess extends Process
75317 {
75318
75319
75320
75321
75322
75323
75324
75325 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
75326 {
75327 $executableFinder = new PhpExecutableFinder();
75328 if (false === $php = $executableFinder->find()) {
75329 $php = null;
75330 }
75331 if ('phpdbg' === \PHP_SAPI) {
75332 $file = tempnam(sys_get_temp_dir(), 'dbg');
75333 file_put_contents($file, $script);
75334 register_shutdown_function('unlink', $file);
75335 $php .= ' '.ProcessUtils::escapeArgument($file);
75336 $script = null;
75337 }
75338 if ('\\' !== \DIRECTORY_SEPARATOR && null !== $php) {
75339
75340  
75341  
75342  $php = 'exec '.$php;
75343 }
75344
75345 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
75346 }
75347
75348
75349
75350
75351 public function setPhpBinary($php)
75352 {
75353 $this->setCommandLine($php);
75354 }
75355
75356
75357
75358
75359 public function start($callback = null)
75360 {
75361 if (null === $this->getCommandLine()) {
75362 throw new RuntimeException('Unable to find the PHP executable.');
75363 }
75364
75365 parent::start($callback);
75366 }
75367 }
75368 <?php
75369
75370
75371
75372
75373
75374
75375
75376
75377
75378
75379 namespace Symfony\Component\Process\Pipes;
75380
75381
75382
75383
75384
75385
75386 abstract class AbstractPipes implements PipesInterface
75387 {
75388 public $pipes = array();
75389
75390 private $inputBuffer = '';
75391 private $input;
75392 private $blocked = true;
75393 private $lastError;
75394
75395
75396
75397
75398 public function __construct($input)
75399 {
75400 if (\is_resource($input)) {
75401 $this->input = $input;
75402 } elseif (\is_string($input)) {
75403 $this->inputBuffer = $input;
75404 } else {
75405 $this->inputBuffer = (string) $input;
75406 }
75407 }
75408
75409
75410
75411
75412 public function close()
75413 {
75414 foreach ($this->pipes as $pipe) {
75415 fclose($pipe);
75416 }
75417 $this->pipes = array();
75418 }
75419
75420
75421
75422
75423
75424
75425 protected function hasSystemCallBeenInterrupted()
75426 {
75427 $lastError = $this->lastError;
75428 $this->lastError = null;
75429
75430
75431  return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
75432 }
75433
75434
75435
75436
75437 protected function unblock()
75438 {
75439 if (!$this->blocked) {
75440 return;
75441 }
75442
75443 foreach ($this->pipes as $pipe) {
75444 stream_set_blocking($pipe, 0);
75445 }
75446 if (null !== $this->input) {
75447 stream_set_blocking($this->input, 0);
75448 }
75449
75450 $this->blocked = false;
75451 }
75452
75453
75454
75455
75456 protected function write()
75457 {
75458 if (!isset($this->pipes[0])) {
75459 return;
75460 }
75461 $input = $this->input;
75462 $r = $e = array();
75463 $w = array($this->pipes[0]);
75464
75465
75466  if (false === @stream_select($r, $w, $e, 0, 0)) {
75467 return;
75468 }
75469
75470 foreach ($w as $stdin) {
75471 if (isset($this->inputBuffer[0])) {
75472 $written = fwrite($stdin, $this->inputBuffer);
75473 $this->inputBuffer = substr($this->inputBuffer, $written);
75474 if (isset($this->inputBuffer[0])) {
75475 return array($this->pipes[0]);
75476 }
75477 }
75478
75479 if ($input) {
75480 for (;;) {
75481 $data = fread($input, self::CHUNK_SIZE);
75482 if (!isset($data[0])) {
75483 break;
75484 }
75485 $written = fwrite($stdin, $data);
75486 $data = substr($data, $written);
75487 if (isset($data[0])) {
75488 $this->inputBuffer = $data;
75489
75490 return array($this->pipes[0]);
75491 }
75492 }
75493 if (feof($input)) {
75494
75495  
75496  $this->input = null;
75497 }
75498 }
75499 }
75500
75501
75502  if (null === $this->input && !isset($this->inputBuffer[0])) {
75503 fclose($this->pipes[0]);
75504 unset($this->pipes[0]);
75505 } elseif (!$w) {
75506 return array($this->pipes[0]);
75507 }
75508 }
75509
75510
75511
75512
75513 public function handleError($type, $msg)
75514 {
75515 $this->lastError = $msg;
75516 }
75517 }
75518 <?php
75519
75520
75521
75522
75523
75524
75525
75526
75527
75528
75529 namespace Symfony\Component\Process\Pipes;
75530
75531
75532
75533
75534
75535
75536
75537
75538 interface PipesInterface
75539 {
75540 const CHUNK_SIZE = 16384;
75541
75542
75543
75544
75545
75546
75547 public function getDescriptors();
75548
75549
75550
75551
75552
75553
75554 public function getFiles();
75555
75556
75557
75558
75559
75560
75561
75562
75563
75564 public function readAndWrite($blocking, $close = false);
75565
75566
75567
75568
75569
75570
75571 public function areOpen();
75572
75573
75574
75575
75576 public function close();
75577 }
75578 <?php
75579
75580
75581
75582
75583
75584
75585
75586
75587
75588
75589 namespace Symfony\Component\Process\Pipes;
75590
75591 use Symfony\Component\Process\Process;
75592
75593
75594
75595
75596
75597
75598
75599
75600 class UnixPipes extends AbstractPipes
75601 {
75602 private $ttyMode;
75603 private $ptyMode;
75604 private $disableOutput;
75605
75606 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
75607 {
75608 $this->ttyMode = (bool) $ttyMode;
75609 $this->ptyMode = (bool) $ptyMode;
75610 $this->disableOutput = (bool) $disableOutput;
75611
75612 parent::__construct($input);
75613 }
75614
75615 public function __destruct()
75616 {
75617 $this->close();
75618 }
75619
75620
75621
75622
75623 public function getDescriptors()
75624 {
75625 if ($this->disableOutput) {
75626 $nullstream = fopen('/dev/null', 'c');
75627
75628 return array(
75629 array('pipe', 'r'),
75630 $nullstream,
75631 $nullstream,
75632 );
75633 }
75634
75635 if ($this->ttyMode) {
75636 return array(
75637 array('file', '/dev/tty', 'r'),
75638 array('file', '/dev/tty', 'w'),
75639 array('file', '/dev/tty', 'w'),
75640 );
75641 }
75642
75643 if ($this->ptyMode && Process::isPtySupported()) {
75644 return array(
75645 array('pty'),
75646 array('pty'),
75647 array('pty'),
75648 );
75649 }
75650
75651 return array(
75652 array('pipe', 'r'),
75653 array('pipe', 'w'), 
75654  array('pipe', 'w'), 
75655  );
75656 }
75657
75658
75659
75660
75661 public function getFiles()
75662 {
75663 return array();
75664 }
75665
75666
75667
75668
75669 public function readAndWrite($blocking, $close = false)
75670 {
75671 $this->unblock();
75672 $w = $this->write();
75673
75674 $read = $e = array();
75675 $r = $this->pipes;
75676 unset($r[0]);
75677
75678
75679  set_error_handler(array($this, 'handleError'));
75680 if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
75681 restore_error_handler();
75682
75683  
75684  if (!$this->hasSystemCallBeenInterrupted()) {
75685 $this->pipes = array();
75686 }
75687
75688 return $read;
75689 }
75690 restore_error_handler();
75691
75692 foreach ($r as $pipe) {
75693
75694  
75695  $read[$type = array_search($pipe, $this->pipes, true)] = '';
75696
75697 do {
75698 $data = fread($pipe, self::CHUNK_SIZE);
75699 $read[$type] .= $data;
75700 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
75701
75702 if (!isset($read[$type][0])) {
75703 unset($read[$type]);
75704 }
75705
75706 if ($close && feof($pipe)) {
75707 fclose($pipe);
75708 unset($this->pipes[$type]);
75709 }
75710 }
75711
75712 return $read;
75713 }
75714
75715
75716
75717
75718 public function areOpen()
75719 {
75720 return (bool) $this->pipes;
75721 }
75722
75723
75724
75725
75726
75727
75728
75729
75730
75731 public static function create(Process $process, $input)
75732 {
75733 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
75734 }
75735 }
75736 <?php
75737
75738
75739
75740
75741
75742
75743
75744
75745
75746
75747 namespace Symfony\Component\Process\Pipes;
75748
75749 use Symfony\Component\Process\Exception\RuntimeException;
75750 use Symfony\Component\Process\Process;
75751
75752
75753
75754
75755
75756
75757
75758
75759
75760
75761
75762 class WindowsPipes extends AbstractPipes
75763 {
75764 private $files = array();
75765 private $fileHandles = array();
75766 private $lockHandles = array();
75767 private $readBytes = array(
75768 Process::STDOUT => 0,
75769 Process::STDERR => 0,
75770 );
75771 private $disableOutput;
75772
75773 public function __construct($disableOutput, $input)
75774 {
75775 $this->disableOutput = (bool) $disableOutput;
75776
75777 if (!$this->disableOutput) {
75778
75779  
75780  
75781  
75782  $pipes = array(
75783 Process::STDOUT => Process::OUT,
75784 Process::STDERR => Process::ERR,
75785 );
75786 $tmpDir = sys_get_temp_dir();
75787 $lastError = 'unknown reason';
75788 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
75789 for ($i = 0;; ++$i) {
75790 foreach ($pipes as $pipe => $name) {
75791 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
75792
75793 if (!$h = fopen($file.'.lock', 'w')) {
75794 restore_error_handler();
75795 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $lastError));
75796 }
75797 if (!flock($h, LOCK_EX | LOCK_NB)) {
75798 continue 2;
75799 }
75800 if (isset($this->lockHandles[$pipe])) {
75801 flock($this->lockHandles[$pipe], LOCK_UN);
75802 fclose($this->lockHandles[$pipe]);
75803 }
75804 $this->lockHandles[$pipe] = $h;
75805
75806 if (!fclose(fopen($file, 'w')) || !$h = fopen($file, 'r')) {
75807 flock($this->lockHandles[$pipe], LOCK_UN);
75808 fclose($this->lockHandles[$pipe]);
75809 unset($this->lockHandles[$pipe]);
75810 continue 2;
75811 }
75812 $this->fileHandles[$pipe] = $h;
75813 $this->files[$pipe] = $file;
75814 }
75815 break;
75816 }
75817 restore_error_handler();
75818 }
75819
75820 parent::__construct($input);
75821 }
75822
75823 public function __destruct()
75824 {
75825 $this->close();
75826 }
75827
75828
75829
75830
75831 public function getDescriptors()
75832 {
75833 if ($this->disableOutput) {
75834 $nullstream = fopen('NUL', 'c');
75835
75836 return array(
75837 array('pipe', 'r'),
75838 $nullstream,
75839 $nullstream,
75840 );
75841 }
75842
75843
75844  
75845  
75846  return array(
75847 array('pipe', 'r'),
75848 array('file', 'NUL', 'w'),
75849 array('file', 'NUL', 'w'),
75850 );
75851 }
75852
75853
75854
75855
75856 public function getFiles()
75857 {
75858 return $this->files;
75859 }
75860
75861
75862
75863
75864 public function readAndWrite($blocking, $close = false)
75865 {
75866 $this->unblock();
75867 $w = $this->write();
75868 $read = $r = $e = array();
75869
75870 if ($blocking) {
75871 if ($w) {
75872 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
75873 } elseif ($this->fileHandles) {
75874 usleep(Process::TIMEOUT_PRECISION * 1E6);
75875 }
75876 }
75877 foreach ($this->fileHandles as $type => $fileHandle) {
75878 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
75879
75880 if (isset($data[0])) {
75881 $this->readBytes[$type] += \strlen($data);
75882 $read[$type] = $data;
75883 }
75884 if ($close) {
75885 ftruncate($fileHandle, 0);
75886 fclose($fileHandle);
75887 flock($this->lockHandles[$type], LOCK_UN);
75888 fclose($this->lockHandles[$type]);
75889 unset($this->fileHandles[$type], $this->lockHandles[$type]);
75890 }
75891 }
75892
75893 return $read;
75894 }
75895
75896
75897
75898
75899 public function areOpen()
75900 {
75901 return $this->pipes && $this->fileHandles;
75902 }
75903
75904
75905
75906
75907 public function close()
75908 {
75909 parent::close();
75910 foreach ($this->fileHandles as $type => $handle) {
75911 ftruncate($handle, 0);
75912 fclose($handle);
75913 flock($this->lockHandles[$type], LOCK_UN);
75914 fclose($this->lockHandles[$type]);
75915 }
75916 $this->fileHandles = $this->lockHandles = array();
75917 }
75918
75919
75920
75921
75922
75923
75924
75925
75926
75927 public static function create(Process $process, $input)
75928 {
75929 return new static($process->isOutputDisabled(), $input);
75930 }
75931 }
75932 <?php
75933
75934
75935
75936
75937
75938
75939
75940
75941
75942
75943 namespace Symfony\Component\Process;
75944
75945 use Symfony\Component\Process\Exception\InvalidArgumentException;
75946 use Symfony\Component\Process\Exception\LogicException;
75947 use Symfony\Component\Process\Exception\ProcessFailedException;
75948 use Symfony\Component\Process\Exception\ProcessTimedOutException;
75949 use Symfony\Component\Process\Exception\RuntimeException;
75950 use Symfony\Component\Process\Pipes\PipesInterface;
75951 use Symfony\Component\Process\Pipes\UnixPipes;
75952 use Symfony\Component\Process\Pipes\WindowsPipes;
75953
75954
75955
75956
75957
75958
75959
75960
75961 class Process
75962 {
75963 const ERR = 'err';
75964 const OUT = 'out';
75965
75966 const STATUS_READY = 'ready';
75967 const STATUS_STARTED = 'started';
75968 const STATUS_TERMINATED = 'terminated';
75969
75970 const STDIN = 0;
75971 const STDOUT = 1;
75972 const STDERR = 2;
75973
75974
75975  const TIMEOUT_PRECISION = 0.2;
75976
75977 private $callback;
75978 private $commandline;
75979 private $cwd;
75980 private $env;
75981 private $input;
75982 private $starttime;
75983 private $lastOutputTime;
75984 private $timeout;
75985 private $idleTimeout;
75986 private $options;
75987 private $exitcode;
75988 private $fallbackStatus = array();
75989 private $processInformation;
75990 private $outputDisabled = false;
75991 private $stdout;
75992 private $stderr;
75993 private $enhanceWindowsCompatibility = true;
75994 private $enhanceSigchildCompatibility;
75995 private $process;
75996 private $status = self::STATUS_READY;
75997 private $incrementalOutputOffset = 0;
75998 private $incrementalErrorOutputOffset = 0;
75999 private $tty;
76000 private $pty;
76001
76002 private $useFileHandles = false;
76003
76004 private $processPipes;
76005
76006 private $latestSignal;
76007
76008 private static $sigchild;
76009
76010
76011
76012
76013
76014
76015 public static $exitCodes = array(
76016 0 => 'OK',
76017 1 => 'General error',
76018 2 => 'Misuse of shell builtins',
76019
76020 126 => 'Invoked command cannot execute',
76021 127 => 'Command not found',
76022 128 => 'Invalid exit argument',
76023
76024
76025  129 => 'Hangup',
76026 130 => 'Interrupt',
76027 131 => 'Quit and dump core',
76028 132 => 'Illegal instruction',
76029 133 => 'Trace/breakpoint trap',
76030 134 => 'Process aborted',
76031 135 => 'Bus error: "access to undefined portion of memory object"',
76032 136 => 'Floating point exception: "erroneous arithmetic operation"',
76033 137 => 'Kill (terminate immediately)',
76034 138 => 'User-defined 1',
76035 139 => 'Segmentation violation',
76036 140 => 'User-defined 2',
76037 141 => 'Write to pipe with no one reading',
76038 142 => 'Signal raised by alarm',
76039 143 => 'Termination (request to terminate)',
76040
76041  145 => 'Child process terminated, stopped (or continued*)',
76042 146 => 'Continue if stopped',
76043 147 => 'Stop executing temporarily',
76044 148 => 'Terminal stop signal',
76045 149 => 'Background process attempting to read from tty ("in")',
76046 150 => 'Background process attempting to write to tty ("out")',
76047 151 => 'Urgent data available on socket',
76048 152 => 'CPU time limit exceeded',
76049 153 => 'File size limit exceeded',
76050 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
76051 155 => 'Profiling timer expired',
76052
76053  157 => 'Pollable event',
76054
76055  159 => 'Bad syscall',
76056 );
76057
76058
76059
76060
76061
76062
76063
76064
76065
76066
76067
76068 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
76069 {
76070 if (!\function_exists('proc_open')) {
76071 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
76072 }
76073
76074 $this->commandline = $commandline;
76075 $this->cwd = $cwd;
76076
76077
76078  
76079  
76080  
76081  if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
76082 $this->cwd = getcwd();
76083 }
76084 if (null !== $env) {
76085 $this->setEnv($env);
76086 }
76087
76088 $this->setInput($input);
76089 $this->setTimeout($timeout);
76090 $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR;
76091 $this->pty = false;
76092 $this->enhanceSigchildCompatibility = '\\' !== \DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
76093 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
76094 }
76095
76096 public function __destruct()
76097 {
76098 $this->stop(0);
76099 }
76100
76101 public function __clone()
76102 {
76103 $this->resetProcessData();
76104 }
76105
76106
76107
76108
76109
76110
76111
76112
76113
76114
76115
76116
76117
76118
76119
76120
76121
76122
76123
76124
76125 public function run($callback = null)
76126 {
76127 $this->start($callback);
76128
76129 return $this->wait();
76130 }
76131
76132
76133
76134
76135
76136
76137
76138
76139
76140
76141
76142
76143
76144
76145 public function mustRun($callback = null)
76146 {
76147 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76148 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
76149 }
76150
76151 if (0 !== $this->run($callback)) {
76152 throw new ProcessFailedException($this);
76153 }
76154
76155 return $this;
76156 }
76157
76158
76159
76160
76161
76162
76163
76164
76165
76166
76167
76168
76169
76170
76171
76172
76173
76174
76175
76176
76177 public function start($callback = null)
76178 {
76179 if ($this->isRunning()) {
76180 throw new RuntimeException('Process is already running');
76181 }
76182 if ($this->outputDisabled && null !== $callback) {
76183 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
76184 }
76185
76186 $this->resetProcessData();
76187 $this->starttime = $this->lastOutputTime = microtime(true);
76188 $this->callback = $this->buildCallback($callback);
76189 $descriptors = $this->getDescriptors();
76190
76191 $commandline = $this->commandline;
76192
76193 if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
76194 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
76195 foreach ($this->processPipes->getFiles() as $offset => $filename) {
76196 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
76197 }
76198 $commandline .= '"';
76199
76200 if (!isset($this->options['bypass_shell'])) {
76201 $this->options['bypass_shell'] = true;
76202 }
76203 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76204
76205  $descriptors[3] = array('pipe', 'w');
76206
76207
76208  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
76209 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
76210
76211
76212  
76213  $ptsWorkaround = fopen(__FILE__, 'r');
76214 }
76215
76216 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
76217
76218 if (!\is_resource($this->process)) {
76219 throw new RuntimeException('Unable to launch a new process.');
76220 }
76221 $this->status = self::STATUS_STARTED;
76222
76223 if (isset($descriptors[3])) {
76224 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
76225 }
76226
76227 if ($this->tty) {
76228 return;
76229 }
76230
76231 $this->updateStatus(false);
76232 $this->checkTimeout();
76233 }
76234
76235
76236
76237
76238
76239
76240
76241
76242
76243
76244
76245
76246
76247
76248
76249
76250 public function restart($callback = null)
76251 {
76252 if ($this->isRunning()) {
76253 throw new RuntimeException('Process is already running');
76254 }
76255
76256 $process = clone $this;
76257 $process->start($callback);
76258
76259 return $process;
76260 }
76261
76262
76263
76264
76265
76266
76267
76268
76269
76270
76271
76272
76273
76274
76275
76276
76277 public function wait($callback = null)
76278 {
76279 $this->requireProcessIsStarted(__FUNCTION__);
76280
76281 $this->updateStatus(false);
76282 if (null !== $callback) {
76283 $this->callback = $this->buildCallback($callback);
76284 }
76285
76286 do {
76287 $this->checkTimeout();
76288 $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
76289 $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
76290 } while ($running);
76291
76292 while ($this->isRunning()) {
76293 usleep(1000);
76294 }
76295
76296 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
76297 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
76298 }
76299
76300 return $this->exitcode;
76301 }
76302
76303
76304
76305
76306
76307
76308 public function getPid()
76309 {
76310 return $this->isRunning() ? $this->processInformation['pid'] : null;
76311 }
76312
76313
76314
76315
76316
76317
76318
76319
76320
76321
76322
76323
76324 public function signal($signal)
76325 {
76326 $this->doSignal($signal, true);
76327
76328 return $this;
76329 }
76330
76331
76332
76333
76334
76335
76336
76337
76338
76339 public function disableOutput()
76340 {
76341 if ($this->isRunning()) {
76342 throw new RuntimeException('Disabling output while the process is running is not possible.');
76343 }
76344 if (null !== $this->idleTimeout) {
76345 throw new LogicException('Output can not be disabled while an idle timeout is set.');
76346 }
76347
76348 $this->outputDisabled = true;
76349
76350 return $this;
76351 }
76352
76353
76354
76355
76356
76357
76358
76359
76360 public function enableOutput()
76361 {
76362 if ($this->isRunning()) {
76363 throw new RuntimeException('Enabling output while the process is running is not possible.');
76364 }
76365
76366 $this->outputDisabled = false;
76367
76368 return $this;
76369 }
76370
76371
76372
76373
76374
76375
76376 public function isOutputDisabled()
76377 {
76378 return $this->outputDisabled;
76379 }
76380
76381
76382
76383
76384
76385
76386
76387
76388
76389 public function getOutput()
76390 {
76391 $this->readPipesForOutput(__FUNCTION__);
76392
76393 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
76394 return '';
76395 }
76396
76397 return $ret;
76398 }
76399
76400
76401
76402
76403
76404
76405
76406
76407
76408
76409
76410
76411 public function getIncrementalOutput()
76412 {
76413 $this->readPipesForOutput(__FUNCTION__);
76414
76415 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
76416 $this->incrementalOutputOffset = ftell($this->stdout);
76417
76418 if (false === $latest) {
76419 return '';
76420 }
76421
76422 return $latest;
76423 }
76424
76425
76426
76427
76428
76429
76430 public function clearOutput()
76431 {
76432 ftruncate($this->stdout, 0);
76433 fseek($this->stdout, 0);
76434 $this->incrementalOutputOffset = 0;
76435
76436 return $this;
76437 }
76438
76439
76440
76441
76442
76443
76444
76445
76446
76447 public function getErrorOutput()
76448 {
76449 $this->readPipesForOutput(__FUNCTION__);
76450
76451 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
76452 return '';
76453 }
76454
76455 return $ret;
76456 }
76457
76458
76459
76460
76461
76462
76463
76464
76465
76466
76467
76468
76469
76470 public function getIncrementalErrorOutput()
76471 {
76472 $this->readPipesForOutput(__FUNCTION__);
76473
76474 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
76475 $this->incrementalErrorOutputOffset = ftell($this->stderr);
76476
76477 if (false === $latest) {
76478 return '';
76479 }
76480
76481 return $latest;
76482 }
76483
76484
76485
76486
76487
76488
76489 public function clearErrorOutput()
76490 {
76491 ftruncate($this->stderr, 0);
76492 fseek($this->stderr, 0);
76493 $this->incrementalErrorOutputOffset = 0;
76494
76495 return $this;
76496 }
76497
76498
76499
76500
76501
76502
76503
76504
76505 public function getExitCode()
76506 {
76507 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76508 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
76509 }
76510
76511 $this->updateStatus(false);
76512
76513 return $this->exitcode;
76514 }
76515
76516
76517
76518
76519
76520
76521
76522
76523
76524
76525
76526
76527 public function getExitCodeText()
76528 {
76529 if (null === $exitcode = $this->getExitCode()) {
76530 return;
76531 }
76532
76533 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
76534 }
76535
76536
76537
76538
76539
76540
76541 public function isSuccessful()
76542 {
76543 return 0 === $this->getExitCode();
76544 }
76545
76546
76547
76548
76549
76550
76551
76552
76553
76554
76555
76556 public function hasBeenSignaled()
76557 {
76558 $this->requireProcessIsTerminated(__FUNCTION__);
76559
76560 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
76561 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
76562 }
76563
76564 return $this->processInformation['signaled'];
76565 }
76566
76567
76568
76569
76570
76571
76572
76573
76574
76575
76576
76577 public function getTermSignal()
76578 {
76579 $this->requireProcessIsTerminated(__FUNCTION__);
76580
76581 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
76582 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
76583 }
76584
76585 return $this->processInformation['termsig'];
76586 }
76587
76588
76589
76590
76591
76592
76593
76594
76595
76596
76597 public function hasBeenStopped()
76598 {
76599 $this->requireProcessIsTerminated(__FUNCTION__);
76600
76601 return $this->processInformation['stopped'];
76602 }
76603
76604
76605
76606
76607
76608
76609
76610
76611
76612
76613 public function getStopSignal()
76614 {
76615 $this->requireProcessIsTerminated(__FUNCTION__);
76616
76617 return $this->processInformation['stopsig'];
76618 }
76619
76620
76621
76622
76623
76624
76625 public function isRunning()
76626 {
76627 if (self::STATUS_STARTED !== $this->status) {
76628 return false;
76629 }
76630
76631 $this->updateStatus(false);
76632
76633 return $this->processInformation['running'];
76634 }
76635
76636
76637
76638
76639
76640
76641 public function isStarted()
76642 {
76643 return self::STATUS_READY != $this->status;
76644 }
76645
76646
76647
76648
76649
76650
76651 public function isTerminated()
76652 {
76653 $this->updateStatus(false);
76654
76655 return self::STATUS_TERMINATED == $this->status;
76656 }
76657
76658
76659
76660
76661
76662
76663
76664
76665 public function getStatus()
76666 {
76667 $this->updateStatus(false);
76668
76669 return $this->status;
76670 }
76671
76672
76673
76674
76675
76676
76677
76678
76679
76680 public function stop($timeout = 10, $signal = null)
76681 {
76682 $timeoutMicro = microtime(true) + $timeout;
76683 if ($this->isRunning()) {
76684
76685  $this->doSignal(15, false);
76686 do {
76687 usleep(1000);
76688 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
76689
76690 if ($this->isRunning()) {
76691
76692  
76693  $this->doSignal($signal ?: 9, false);
76694 }
76695 }
76696
76697 if ($this->isRunning()) {
76698 if (isset($this->fallbackStatus['pid'])) {
76699 unset($this->fallbackStatus['pid']);
76700
76701 return $this->stop(0, $signal);
76702 }
76703 $this->close();
76704 }
76705
76706 return $this->exitcode;
76707 }
76708
76709
76710
76711
76712
76713
76714
76715
76716 public function addOutput($line)
76717 {
76718 $this->lastOutputTime = microtime(true);
76719
76720 fseek($this->stdout, 0, SEEK_END);
76721 fwrite($this->stdout, $line);
76722 fseek($this->stdout, $this->incrementalOutputOffset);
76723 }
76724
76725
76726
76727
76728
76729
76730
76731
76732 public function addErrorOutput($line)
76733 {
76734 $this->lastOutputTime = microtime(true);
76735
76736 fseek($this->stderr, 0, SEEK_END);
76737 fwrite($this->stderr, $line);
76738 fseek($this->stderr, $this->incrementalErrorOutputOffset);
76739 }
76740
76741
76742
76743
76744
76745
76746 public function getCommandLine()
76747 {
76748 return $this->commandline;
76749 }
76750
76751
76752
76753
76754
76755
76756
76757
76758 public function setCommandLine($commandline)
76759 {
76760 $this->commandline = $commandline;
76761
76762 return $this;
76763 }
76764
76765
76766
76767
76768
76769
76770 public function getTimeout()
76771 {
76772 return $this->timeout;
76773 }
76774
76775
76776
76777
76778
76779
76780 public function getIdleTimeout()
76781 {
76782 return $this->idleTimeout;
76783 }
76784
76785
76786
76787
76788
76789
76790
76791
76792
76793
76794
76795
76796 public function setTimeout($timeout)
76797 {
76798 $this->timeout = $this->validateTimeout($timeout);
76799
76800 return $this;
76801 }
76802
76803
76804
76805
76806
76807
76808
76809
76810
76811
76812
76813
76814
76815 public function setIdleTimeout($timeout)
76816 {
76817 if (null !== $timeout && $this->outputDisabled) {
76818 throw new LogicException('Idle timeout can not be set while the output is disabled.');
76819 }
76820
76821 $this->idleTimeout = $this->validateTimeout($timeout);
76822
76823 return $this;
76824 }
76825
76826
76827
76828
76829
76830
76831
76832
76833
76834
76835 public function setTty($tty)
76836 {
76837 if ('\\' === \DIRECTORY_SEPARATOR && $tty) {
76838 throw new RuntimeException('TTY mode is not supported on Windows platform.');
76839 }
76840 if ($tty) {
76841 static $isTtySupported;
76842
76843 if (null === $isTtySupported) {
76844 $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);
76845 }
76846
76847 if (!$isTtySupported) {
76848 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
76849 }
76850 }
76851
76852 $this->tty = (bool) $tty;
76853
76854 return $this;
76855 }
76856
76857
76858
76859
76860
76861
76862 public function isTty()
76863 {
76864 return $this->tty;
76865 }
76866
76867
76868
76869
76870
76871
76872
76873
76874 public function setPty($bool)
76875 {
76876 $this->pty = (bool) $bool;
76877
76878 return $this;
76879 }
76880
76881
76882
76883
76884
76885
76886 public function isPty()
76887 {
76888 return $this->pty;
76889 }
76890
76891
76892
76893
76894
76895
76896 public function getWorkingDirectory()
76897 {
76898 if (null === $this->cwd) {
76899
76900  
76901  return getcwd() ?: null;
76902 }
76903
76904 return $this->cwd;
76905 }
76906
76907
76908
76909
76910
76911
76912
76913
76914 public function setWorkingDirectory($cwd)
76915 {
76916 $this->cwd = $cwd;
76917
76918 return $this;
76919 }
76920
76921
76922
76923
76924
76925
76926 public function getEnv()
76927 {
76928 return $this->env;
76929 }
76930
76931
76932
76933
76934
76935
76936
76937
76938
76939
76940
76941
76942
76943
76944 public function setEnv(array $env)
76945 {
76946
76947  $env = array_filter($env, function ($value) {
76948 return !\is_array($value);
76949 });
76950
76951 $this->env = array();
76952 foreach ($env as $key => $value) {
76953 $this->env[$key] = (string) $value;
76954 }
76955
76956 return $this;
76957 }
76958
76959
76960
76961
76962
76963
76964
76965
76966
76967
76968 public function getStdin()
76969 {
76970 @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);
76971
76972 return $this->getInput();
76973 }
76974
76975
76976
76977
76978
76979
76980 public function getInput()
76981 {
76982 return $this->input;
76983 }
76984
76985
76986
76987
76988
76989
76990
76991
76992
76993
76994
76995
76996
76997
76998 public function setStdin($stdin)
76999 {
77000 @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);
77001
77002 return $this->setInput($stdin);
77003 }
77004
77005
77006
77007
77008
77009
77010
77011
77012
77013
77014
77015
77016
77017
77018 public function setInput($input)
77019 {
77020 if ($this->isRunning()) {
77021 throw new LogicException('Input can not be set while the process is running.');
77022 }
77023
77024 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
77025
77026 return $this;
77027 }
77028
77029
77030
77031
77032
77033
77034 public function getOptions()
77035 {
77036 return $this->options;
77037 }
77038
77039
77040
77041
77042
77043
77044
77045
77046 public function setOptions(array $options)
77047 {
77048 $this->options = $options;
77049
77050 return $this;
77051 }
77052
77053
77054
77055
77056
77057
77058
77059
77060 public function getEnhanceWindowsCompatibility()
77061 {
77062 return $this->enhanceWindowsCompatibility;
77063 }
77064
77065
77066
77067
77068
77069
77070
77071
77072 public function setEnhanceWindowsCompatibility($enhance)
77073 {
77074 $this->enhanceWindowsCompatibility = (bool) $enhance;
77075
77076 return $this;
77077 }
77078
77079
77080
77081
77082
77083
77084 public function getEnhanceSigchildCompatibility()
77085 {
77086 return $this->enhanceSigchildCompatibility;
77087 }
77088
77089
77090
77091
77092
77093
77094
77095
77096
77097
77098
77099
77100 public function setEnhanceSigchildCompatibility($enhance)
77101 {
77102 $this->enhanceSigchildCompatibility = (bool) $enhance;
77103
77104 return $this;
77105 }
77106
77107
77108
77109
77110
77111
77112
77113
77114
77115 public function checkTimeout()
77116 {
77117 if (self::STATUS_STARTED !== $this->status) {
77118 return;
77119 }
77120
77121 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
77122 $this->stop(0);
77123
77124 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
77125 }
77126
77127 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
77128 $this->stop(0);
77129
77130 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
77131 }
77132 }
77133
77134
77135
77136
77137
77138
77139 public static function isPtySupported()
77140 {
77141 static $result;
77142
77143 if (null !== $result) {
77144 return $result;
77145 }
77146
77147 if ('\\' === \DIRECTORY_SEPARATOR) {
77148 return $result = false;
77149 }
77150
77151 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
77152 }
77153
77154
77155
77156
77157
77158
77159 private function getDescriptors()
77160 {
77161 if ('\\' === \DIRECTORY_SEPARATOR) {
77162 $this->processPipes = WindowsPipes::create($this, $this->input);
77163 } else {
77164 $this->processPipes = UnixPipes::create($this, $this->input);
77165 }
77166
77167 return $this->processPipes->getDescriptors();
77168 }
77169
77170
77171
77172
77173
77174
77175
77176
77177
77178
77179
77180 protected function buildCallback($callback)
77181 {
77182 $that = $this;
77183 $out = self::OUT;
77184 $callback = function ($type, $data) use ($that, $callback, $out) {
77185 if ($out == $type) {
77186 $that->addOutput($data);
77187 } else {
77188 $that->addErrorOutput($data);
77189 }
77190
77191 if (null !== $callback) {
77192 \call_user_func($callback, $type, $data);
77193 }
77194 };
77195
77196 return $callback;
77197 }
77198
77199
77200
77201
77202
77203
77204 protected function updateStatus($blocking)
77205 {
77206 if (self::STATUS_STARTED !== $this->status) {
77207 return;
77208 }
77209
77210 $this->processInformation = proc_get_status($this->process);
77211 $running = $this->processInformation['running'];
77212
77213 $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);
77214
77215 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
77216 $this->processInformation = $this->fallbackStatus + $this->processInformation;
77217 }
77218
77219 if (!$running) {
77220 $this->close();
77221 }
77222 }
77223
77224
77225
77226
77227
77228
77229 protected function isSigchildEnabled()
77230 {
77231 if (null !== self::$sigchild) {
77232 return self::$sigchild;
77233 }
77234
77235 if (!\function_exists('phpinfo') || \defined('HHVM_VERSION')) {
77236 return self::$sigchild = false;
77237 }
77238
77239 ob_start();
77240 phpinfo(INFO_GENERAL);
77241
77242 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
77243 }
77244
77245
77246
77247
77248
77249
77250
77251
77252 private function readPipesForOutput($caller)
77253 {
77254 if ($this->outputDisabled) {
77255 throw new LogicException('Output has been disabled.');
77256 }
77257
77258 $this->requireProcessIsStarted($caller);
77259
77260 $this->updateStatus(false);
77261 }
77262
77263
77264
77265
77266
77267
77268
77269
77270
77271
77272 private function validateTimeout($timeout)
77273 {
77274 $timeout = (float) $timeout;
77275
77276 if (0.0 === $timeout) {
77277 $timeout = null;
77278 } elseif ($timeout < 0) {
77279 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
77280 }
77281
77282 return $timeout;
77283 }
77284
77285
77286
77287
77288
77289
77290
77291 private function readPipes($blocking, $close)
77292 {
77293 $result = $this->processPipes->readAndWrite($blocking, $close);
77294
77295 $callback = $this->callback;
77296 foreach ($result as $type => $data) {
77297 if (3 !== $type) {
77298 $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
77299 } elseif (!isset($this->fallbackStatus['signaled'])) {
77300 $this->fallbackStatus['exitcode'] = (int) $data;
77301 }
77302 }
77303 }
77304
77305
77306
77307
77308
77309
77310 private function close()
77311 {
77312 $this->processPipes->close();
77313 if (\is_resource($this->process)) {
77314 proc_close($this->process);
77315 }
77316 $this->exitcode = $this->processInformation['exitcode'];
77317 $this->status = self::STATUS_TERMINATED;
77318
77319 if (-1 === $this->exitcode) {
77320 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
77321
77322  $this->exitcode = 128 + $this->processInformation['termsig'];
77323 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
77324 $this->processInformation['signaled'] = true;
77325 $this->processInformation['termsig'] = -1;
77326 }
77327 }
77328
77329
77330  
77331  
77332  $this->callback = null;
77333
77334 return $this->exitcode;
77335 }
77336
77337
77338
77339
77340 private function resetProcessData()
77341 {
77342 $this->starttime = null;
77343 $this->callback = null;
77344 $this->exitcode = null;
77345 $this->fallbackStatus = array();
77346 $this->processInformation = null;
77347 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
77348 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
77349 $this->process = null;
77350 $this->latestSignal = null;
77351 $this->status = self::STATUS_READY;
77352 $this->incrementalOutputOffset = 0;
77353 $this->incrementalErrorOutputOffset = 0;
77354 }
77355
77356
77357
77358
77359
77360
77361
77362
77363
77364
77365
77366
77367
77368 private function doSignal($signal, $throwException)
77369 {
77370 if (null === $pid = $this->getPid()) {
77371 if ($throwException) {
77372 throw new LogicException('Can not send signal on a non running process.');
77373 }
77374
77375 return false;
77376 }
77377
77378 if ('\\' === \DIRECTORY_SEPARATOR) {
77379 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
77380 if ($exitCode && $this->isRunning()) {
77381 if ($throwException) {
77382 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
77383 }
77384
77385 return false;
77386 }
77387 } else {
77388 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
77389 $ok = @proc_terminate($this->process, $signal);
77390 } elseif (\function_exists('posix_kill')) {
77391 $ok = @posix_kill($pid, $signal);
77392 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
77393 $ok = false === fgets($pipes[2]);
77394 }
77395 if (!$ok) {
77396 if ($throwException) {
77397 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
77398 }
77399
77400 return false;
77401 }
77402 }
77403
77404 $this->latestSignal = (int) $signal;
77405 $this->fallbackStatus['signaled'] = true;
77406 $this->fallbackStatus['exitcode'] = -1;
77407 $this->fallbackStatus['termsig'] = $this->latestSignal;
77408
77409 return true;
77410 }
77411
77412
77413
77414
77415
77416
77417
77418
77419 private function requireProcessIsStarted($functionName)
77420 {
77421 if (!$this->isStarted()) {
77422 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
77423 }
77424 }
77425
77426
77427
77428
77429
77430
77431
77432
77433 private function requireProcessIsTerminated($functionName)
77434 {
77435 if (!$this->isTerminated()) {
77436 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
77437 }
77438 }
77439 }
77440 <?php
77441
77442
77443
77444
77445
77446
77447
77448
77449
77450
77451 namespace Symfony\Component\Process;
77452
77453 use Symfony\Component\Process\Exception\InvalidArgumentException;
77454 use Symfony\Component\Process\Exception\LogicException;
77455
77456
77457
77458
77459 class ProcessBuilder
77460 {
77461 private $arguments;
77462 private $cwd;
77463 private $env = array();
77464 private $input;
77465 private $timeout = 60;
77466 private $options = array();
77467 private $inheritEnv = true;
77468 private $prefix = array();
77469 private $outputDisabled = false;
77470
77471
77472
77473
77474 public function __construct(array $arguments = array())
77475 {
77476 $this->arguments = $arguments;
77477 }
77478
77479
77480
77481
77482
77483
77484
77485
77486 public static function create(array $arguments = array())
77487 {
77488 return new static($arguments);
77489 }
77490
77491
77492
77493
77494
77495
77496
77497
77498 public function add($argument)
77499 {
77500 $this->arguments[] = $argument;
77501
77502 return $this;
77503 }
77504
77505
77506
77507
77508
77509
77510
77511
77512
77513
77514 public function setPrefix($prefix)
77515 {
77516 $this->prefix = \is_array($prefix) ? $prefix : array($prefix);
77517
77518 return $this;
77519 }
77520
77521
77522
77523
77524
77525
77526
77527
77528
77529
77530
77531 public function setArguments(array $arguments)
77532 {
77533 $this->arguments = $arguments;
77534
77535 return $this;
77536 }
77537
77538
77539
77540
77541
77542
77543
77544
77545 public function setWorkingDirectory($cwd)
77546 {
77547 $this->cwd = $cwd;
77548
77549 return $this;
77550 }
77551
77552
77553
77554
77555
77556
77557
77558
77559 public function inheritEnvironmentVariables($inheritEnv = true)
77560 {
77561 $this->inheritEnv = $inheritEnv;
77562
77563 return $this;
77564 }
77565
77566
77567
77568
77569
77570
77571
77572
77573
77574
77575
77576
77577 public function setEnv($name, $value)
77578 {
77579 $this->env[$name] = $value;
77580
77581 return $this;
77582 }
77583
77584
77585
77586
77587
77588
77589
77590
77591
77592
77593
77594
77595 public function addEnvironmentVariables(array $variables)
77596 {
77597 $this->env = array_replace($this->env, $variables);
77598
77599 return $this;
77600 }
77601
77602
77603
77604
77605
77606
77607
77608
77609
77610
77611
77612
77613 public function setInput($input)
77614 {
77615 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
77616
77617 return $this;
77618 }
77619
77620
77621
77622
77623
77624
77625
77626
77627
77628
77629
77630
77631 public function setTimeout($timeout)
77632 {
77633 if (null === $timeout) {
77634 $this->timeout = null;
77635
77636 return $this;
77637 }
77638
77639 $timeout = (float) $timeout;
77640
77641 if ($timeout < 0) {
77642 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
77643 }
77644
77645 $this->timeout = $timeout;
77646
77647 return $this;
77648 }
77649
77650
77651
77652
77653
77654
77655
77656
77657
77658 public function setOption($name, $value)
77659 {
77660 $this->options[$name] = $value;
77661
77662 return $this;
77663 }
77664
77665
77666
77667
77668
77669
77670 public function disableOutput()
77671 {
77672 $this->outputDisabled = true;
77673
77674 return $this;
77675 }
77676
77677
77678
77679
77680
77681
77682 public function enableOutput()
77683 {
77684 $this->outputDisabled = false;
77685
77686 return $this;
77687 }
77688
77689
77690
77691
77692
77693
77694
77695
77696 public function getProcess()
77697 {
77698 if (0 === \count($this->prefix) && 0 === \count($this->arguments)) {
77699 throw new LogicException('You must add() command arguments before calling getProcess().');
77700 }
77701
77702 $options = $this->options;
77703
77704 $arguments = array_merge($this->prefix, $this->arguments);
77705 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
77706
77707 if ($this->inheritEnv) {
77708
77709  $env = array_replace($_ENV, $_SERVER, $this->env);
77710 } else {
77711 $env = $this->env;
77712 }
77713
77714 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
77715
77716 if ($this->outputDisabled) {
77717 $process->disableOutput();
77718 }
77719
77720 return $process;
77721 }
77722 }
77723 <?php
77724
77725
77726
77727
77728
77729
77730
77731
77732
77733
77734 namespace Symfony\Component\Process;
77735
77736 use Symfony\Component\Process\Exception\InvalidArgumentException;
77737
77738
77739
77740
77741
77742
77743
77744
77745 class ProcessUtils
77746 {
77747
77748
77749
77750 private function __construct()
77751 {
77752 }
77753
77754
77755
77756
77757
77758
77759
77760
77761 public static function escapeArgument($argument)
77762 {
77763
77764  
77765  
77766  
77767  if ('\\' === \DIRECTORY_SEPARATOR) {
77768 if ('' === $argument) {
77769 return escapeshellarg($argument);
77770 }
77771
77772 $escapedArgument = '';
77773 $quote = false;
77774 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
77775 if ('"' === $part) {
77776 $escapedArgument .= '\\"';
77777 } elseif (self::isSurroundedBy($part, '%')) {
77778
77779  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
77780 } else {
77781
77782  if ('\\' === substr($part, -1)) {
77783 $part .= '\\';
77784 }
77785 $quote = true;
77786 $escapedArgument .= $part;
77787 }
77788 }
77789 if ($quote) {
77790 $escapedArgument = '"'.$escapedArgument.'"';
77791 }
77792
77793 return $escapedArgument;
77794 }
77795
77796 return "'".str_replace("'", "'\\''", $argument)."'";
77797 }
77798
77799
77800
77801
77802
77803
77804
77805
77806
77807
77808
77809
77810
77811 public static function validateInput($caller, $input)
77812 {
77813 if (null !== $input) {
77814 if (\is_resource($input)) {
77815 return $input;
77816 }
77817 if (\is_string($input)) {
77818 return $input;
77819 }
77820 if (is_scalar($input)) {
77821 return (string) $input;
77822 }
77823
77824  if (\is_object($input) && method_exists($input, '__toString')) {
77825 @trigger_error('Passing an object as an input is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
77826
77827 return (string) $input;
77828 }
77829
77830 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
77831 }
77832
77833 return $input;
77834 }
77835
77836 private static function isSurroundedBy($arg, $char)
77837 {
77838 return 2 < \strlen($arg) && $char === $arg[0] && $char === $arg[\strlen($arg) - 1];
77839 }
77840 }
77841 Copyright (c) 2011 Jordi Boggiano
77842
77843 Permission is hereby granted, free of charge, to any person obtaining a copy
77844 of this software and associated documentation files (the "Software"), to deal
77845 in the Software without restriction, including without limitation the rights
77846 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
77847 copies of the Software, and to permit persons to whom the Software is furnished
77848 to do so, subject to the following conditions:
77849
77850 The above copyright notice and this permission notice shall be included in all
77851 copies or substantial portions of the Software.
77852
77853 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
77854 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77855 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
77856 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
77857 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77858 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
77859 THE SOFTWARE.
77860 <?php
77861
77862
77863
77864
77865
77866
77867
77868
77869
77870
77871 namespace Seld\JsonLint;
77872
77873 class DuplicateKeyException extends ParsingException
77874 {
77875 public function __construct($message, $key, array $details = array())
77876 {
77877 $details['key'] = $key;
77878 parent::__construct($message, $details);
77879 }
77880
77881 public function getKey()
77882 {
77883 return $this->details['key'];
77884 }
77885 }
77886 <?php
77887
77888
77889
77890
77891
77892
77893
77894
77895
77896
77897 namespace Seld\JsonLint;
77898 use stdClass;
77899
77900
77901
77902
77903
77904
77905
77906
77907
77908
77909
77910
77911
77912
77913 class JsonParser
77914 {
77915 const DETECT_KEY_CONFLICTS = 1;
77916 const ALLOW_DUPLICATE_KEYS = 2;
77917 const PARSE_TO_ASSOC = 4;
77918
77919 private $lexer;
77920
77921 private $flags;
77922 private $stack;
77923 private $vstack; 
77924  private $lstack; 
77925
77926 private $symbols = array(
77927 'error' => 2,
77928 'JSONString' => 3,
77929 'STRING' => 4,
77930 'JSONNumber' => 5,
77931 'NUMBER' => 6,
77932 'JSONNullLiteral' => 7,
77933 'NULL' => 8,
77934 'JSONBooleanLiteral' => 9,
77935 'TRUE' => 10,
77936 'FALSE' => 11,
77937 'JSONText' => 12,
77938 'JSONValue' => 13,
77939 'EOF' => 14,
77940 'JSONObject' => 15,
77941 'JSONArray' => 16,
77942 '{' => 17,
77943 '}' => 18,
77944 'JSONMemberList' => 19,
77945 'JSONMember' => 20,
77946 ':' => 21,
77947 ',' => 22,
77948 '[' => 23,
77949 ']' => 24,
77950 'JSONElementList' => 25,
77951 '$accept' => 0,
77952 '$end' => 1,
77953 );
77954
77955 private $terminals_ = array(
77956 2 => "error",
77957 4 => "STRING",
77958 6 => "NUMBER",
77959 8 => "NULL",
77960 10 => "TRUE",
77961 11 => "FALSE",
77962 14 => "EOF",
77963 17 => "{",
77964 18 => "}",
77965 21 => ":",
77966 22 => ",",
77967 23 => "[",
77968 24 => "]",
77969 );
77970
77971 private $productions_ = array(
77972 0,
77973 array(3, 1),
77974 array(5, 1),
77975 array(7, 1),
77976 array(9, 1),
77977 array(9, 1),
77978 array(12, 2),
77979 array(13, 1),
77980 array(13, 1),
77981 array(13, 1),
77982 array(13, 1),
77983 array(13, 1),
77984 array(13, 1),
77985 array(15, 2),
77986 array(15, 3),
77987 array(20, 3),
77988 array(19, 1),
77989 array(19, 3),
77990 array(16, 2),
77991 array(16, 3),
77992 array(25, 1),
77993 array(25, 3)
77994 );
77995
77996 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)),
77997 );
77998
77999 private $defaultActions = array(
78000 16 => array(2, 6)
78001 );
78002
78003
78004
78005
78006
78007
78008 public function lint($input, $flags = 0)
78009 {
78010 try {
78011 $this->parse($input, $flags);
78012 } catch (ParsingException $e) {
78013 return $e;
78014 }
78015 }
78016
78017
78018
78019
78020
78021
78022
78023 public function parse($input, $flags = 0)
78024 {
78025 $this->failOnBOM($input);
78026
78027 $this->flags = $flags;
78028
78029 $this->stack = array(0);
78030 $this->vstack = array(null);
78031 $this->lstack = array();
78032
78033 $yytext = '';
78034 $yylineno = 0;
78035 $yyleng = 0;
78036 $recovering = 0;
78037 $TERROR = 2;
78038 $EOF = 1;
78039
78040 $this->lexer = new Lexer();
78041 $this->lexer->setInput($input);
78042
78043 $yyloc = $this->lexer->yylloc;
78044 $this->lstack[] = $yyloc;
78045
78046 $symbol = null;
78047 $preErrorSymbol = null;
78048 $state = null;
78049 $action = null;
78050 $a = null;
78051 $r = null;
78052 $yyval = new stdClass;
78053 $p = null;
78054 $len = null;
78055 $newState = null;
78056 $expected = null;
78057 $errStr = null;
78058
78059 while (true) {
78060
78061  $state = $this->stack[count($this->stack)-1];
78062
78063
78064  if (isset($this->defaultActions[$state])) {
78065 $action = $this->defaultActions[$state];
78066 } else {
78067 if ($symbol == null) {
78068 $symbol = $this->lex();
78069 }
78070
78071  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
78072 }
78073
78074
78075  if (!$action || !$action[0]) {
78076 if (!$recovering) {
78077
78078  $expected = array();
78079 foreach ($this->table[$state] as $p => $ignore) {
78080 if (isset($this->terminals_[$p]) && $p > 2) {
78081 $expected[] = "'" . $this->terminals_[$p] . "'";
78082 }
78083 }
78084
78085 $message = null;
78086 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
78087 $message = "Invalid string";
78088 if ("'" === substr($this->lexer->match, 0, 1)) {
78089 $message .= ", it appears you used single quotes instead of double quotes";
78090 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
78091 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
78092 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
78093 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
78094 }
78095 }
78096
78097 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
78098 $errStr .= $this->lexer->showPosition() . "\n";
78099 if ($message) {
78100 $errStr .= $message;
78101 } else {
78102 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
78103 $errStr .= implode(', ', $expected);
78104 }
78105
78106 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
78107 $errStr .= " - It appears you have an extra trailing comma";
78108 }
78109
78110 $this->parseError($errStr, array(
78111 'text' => $this->lexer->match,
78112 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
78113 'line' => $this->lexer->yylineno,
78114 'loc' => $yyloc,
78115 'expected' => $expected,
78116 ));
78117 }
78118
78119
78120  if ($recovering == 3) {
78121 if ($symbol == $EOF) {
78122 throw new ParsingException($errStr ?: 'Parsing halted.');
78123 }
78124
78125
78126  $yyleng = $this->lexer->yyleng;
78127 $yytext = $this->lexer->yytext;
78128 $yylineno = $this->lexer->yylineno;
78129 $yyloc = $this->lexer->yylloc;
78130 $symbol = $this->lex();
78131 }
78132
78133
78134  while (true) {
78135
78136  if (array_key_exists($TERROR, $this->table[$state])) {
78137 break;
78138 }
78139 if ($state == 0) {
78140 throw new ParsingException($errStr ?: 'Parsing halted.');
78141 }
78142 $this->popStack(1);
78143 $state = $this->stack[count($this->stack)-1];
78144 }
78145
78146 $preErrorSymbol = $symbol; 
78147  $symbol = $TERROR; 
78148  $state = $this->stack[count($this->stack)-1];
78149 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
78150 $recovering = 3; 
78151  }
78152
78153
78154  if (is_array($action[0]) && count($action) > 1) {
78155 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
78156 }
78157
78158 switch ($action[0]) {
78159 case 1: 
78160  $this->stack[] = $symbol;
78161 $this->vstack[] = $this->lexer->yytext;
78162 $this->lstack[] = $this->lexer->yylloc;
78163 $this->stack[] = $action[1]; 
78164  $symbol = null;
78165 if (!$preErrorSymbol) { 
78166  $yyleng = $this->lexer->yyleng;
78167 $yytext = $this->lexer->yytext;
78168 $yylineno = $this->lexer->yylineno;
78169 $yyloc = $this->lexer->yylloc;
78170 if ($recovering > 0) {
78171 $recovering--;
78172 }
78173 } else { 
78174  $symbol = $preErrorSymbol;
78175 $preErrorSymbol = null;
78176 }
78177 break;
78178
78179 case 2: 
78180  $len = $this->productions_[$action[1]][1];
78181
78182
78183  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
78184  
78185  $yyval->store = array( 
78186  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
78187 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
78188 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
78189 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
78190 );
78191 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
78192
78193 if (!$r instanceof Undefined) {
78194 return $r;
78195 }
78196
78197 if ($len) {
78198 $this->popStack($len);
78199 }
78200
78201 $this->stack[] = $this->productions_[$action[1]][0]; 
78202  $this->vstack[] = $yyval->token;
78203 $this->lstack[] = $yyval->store;
78204 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
78205 $this->stack[] = $newState;
78206 break;
78207
78208 case 3: 
78209
78210 return true;
78211 }
78212 }
78213
78214 return true;
78215 }
78216
78217 protected function parseError($str, $hash)
78218 {
78219 throw new ParsingException($str, $hash);
78220 }
78221
78222
78223  
78224  
78225  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
78226 {
78227
78228  $len = count($tokens) - 1;
78229 switch ($yystate) {
78230 case 1:
78231 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
78232 $yyval->token = $yytext;
78233 break;
78234 case 2:
78235 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
78236 $yyval->token = floatval($yytext);
78237 } else {
78238 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
78239 }
78240 break;
78241 case 3:
78242 $yyval->token = null;
78243 break;
78244 case 4:
78245 $yyval->token = true;
78246 break;
78247 case 5:
78248 $yyval->token = false;
78249 break;
78250 case 6:
78251 return $yyval->token = $tokens[$len-1];
78252 case 13:
78253 if ($this->flags & self::PARSE_TO_ASSOC) {
78254 $yyval->token = array();
78255 } else {
78256 $yyval->token = new stdClass;
78257 }
78258 break;
78259 case 14:
78260 $yyval->token = $tokens[$len-1];
78261 break;
78262 case 15:
78263 $yyval->token = array($tokens[$len-2], $tokens[$len]);
78264 break;
78265 case 16:
78266 if (PHP_VERSION_ID < 70100) {
78267 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
78268 } else {
78269 $property = $tokens[$len][0];
78270 }
78271 if ($this->flags & self::PARSE_TO_ASSOC) {
78272 $yyval->token = array();
78273 $yyval->token[$property] = $tokens[$len][1];
78274 } else {
78275 $yyval->token = new stdClass;
78276 $yyval->token->$property = $tokens[$len][1];
78277 }
78278 break;
78279 case 17:
78280 if ($this->flags & self::PARSE_TO_ASSOC) {
78281 $yyval->token =& $tokens[$len-2];
78282 $key = $tokens[$len][0];
78283 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
78284 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
78285 $errStr .= $this->lexer->showPosition() . "\n";
78286 $errStr .= "Duplicate key: ".$tokens[$len][0];
78287 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
78288 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
78289 $duplicateCount = 1;
78290 do {
78291 $duplicateKey = $key . '.' . $duplicateCount++;
78292 } while (isset($tokens[$len-2][$duplicateKey]));
78293 $key = $duplicateKey;
78294 }
78295 $tokens[$len-2][$key] = $tokens[$len][1];
78296 } else {
78297 $yyval->token = $tokens[$len-2];
78298 if (PHP_VERSION_ID < 70100) {
78299 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
78300 } else {
78301 $key = $tokens[$len][0];
78302 }
78303 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
78304 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
78305 $errStr .= $this->lexer->showPosition() . "\n";
78306 $errStr .= "Duplicate key: ".$tokens[$len][0];
78307 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
78308 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
78309 $duplicateCount = 1;
78310 do {
78311 $duplicateKey = $key . '.' . $duplicateCount++;
78312 } while (isset($tokens[$len-2]->$duplicateKey));
78313 $key = $duplicateKey;
78314 }
78315 $tokens[$len-2]->$key = $tokens[$len][1];
78316 }
78317 break;
78318 case 18:
78319 $yyval->token = array();
78320 break;
78321 case 19:
78322 $yyval->token = $tokens[$len-1];
78323 break;
78324 case 20:
78325 $yyval->token = array($tokens[$len]);
78326 break;
78327 case 21:
78328 $tokens[$len-2][] = $tokens[$len];
78329 $yyval->token = $tokens[$len-2];
78330 break;
78331 }
78332
78333 return new Undefined();
78334 }
78335
78336 private function stringInterpolation($match)
78337 {
78338 switch ($match[0]) {
78339 case '\\\\':
78340 return '\\';
78341 case '\"':
78342 return '"';
78343 case '\b':
78344 return chr(8);
78345 case '\f':
78346 return chr(12);
78347 case '\n':
78348 return "\n";
78349 case '\r':
78350 return "\r";
78351 case '\t':
78352 return "\t";
78353 case '\/':
78354 return "/";
78355 default:
78356 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', ENT_QUOTES, 'UTF-8');
78357 }
78358 }
78359
78360 private function popStack($n)
78361 {
78362 $this->stack = array_slice($this->stack, 0, - (2 * $n));
78363 $this->vstack = array_slice($this->vstack, 0, - $n);
78364 $this->lstack = array_slice($this->lstack, 0, - $n);
78365 }
78366
78367 private function lex()
78368 {
78369 $token = $this->lexer->lex() ?: 1; 
78370  
78371  if (!is_numeric($token)) {
78372 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
78373 }
78374
78375 return $token;
78376 }
78377
78378 private function failOnBOM($input)
78379 {
78380
78381  $bom = "\xEF\xBB\xBF";
78382
78383 if (substr($input, 0, 3) === $bom) {
78384 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
78385 }
78386 }
78387 }
78388 <?php
78389
78390
78391
78392
78393
78394
78395
78396
78397
78398
78399 namespace Seld\JsonLint;
78400
78401
78402
78403
78404
78405
78406 class Lexer
78407 {
78408 private $EOF = 1;
78409 private $rules = array(
78410 0 => '/^\s+/',
78411 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
78412 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
78413 3 => '/^\{/',
78414 4 => '/^\}/',
78415 5 => '/^\[/',
78416 6 => '/^\]/',
78417 7 => '/^,/',
78418 8 => '/^:/',
78419 9 => '/^true\b/',
78420 10 => '/^false\b/',
78421 11 => '/^null\b/',
78422 12 => '/^$/',
78423 13 => '/^./',
78424 );
78425
78426 private $conditions = array(
78427 "INITIAL" => array(
78428 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
78429 "inclusive" => true,
78430 ),
78431 );
78432
78433 private $conditionStack;
78434 private $input;
78435 private $more;
78436 private $done;
78437 private $matched;
78438
78439 public $match;
78440 public $yylineno;
78441 public $yyleng;
78442 public $yytext;
78443 public $yylloc;
78444
78445 public function lex()
78446 {
78447 $r = $this->next();
78448 if (!$r instanceof Undefined) {
78449 return $r;
78450 }
78451
78452 return $this->lex();
78453 }
78454
78455 public function setInput($input)
78456 {
78457 $this->input = $input;
78458 $this->more = false;
78459 $this->done = false;
78460 $this->yylineno = $this->yyleng = 0;
78461 $this->yytext = $this->matched = $this->match = '';
78462 $this->conditionStack = array('INITIAL');
78463 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
78464
78465 return $this;
78466 }
78467
78468 public function showPosition()
78469 {
78470 $pre = str_replace("\n", '', $this->getPastInput());
78471 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
78472
78473 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
78474 }
78475
78476 public function getPastInput()
78477 {
78478 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
78479
78480 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
78481 }
78482
78483 public function getUpcomingInput()
78484 {
78485 $next = $this->match;
78486 if (strlen($next) < 20) {
78487 $next .= substr($this->input, 0, 20 - strlen($next));
78488 }
78489
78490 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
78491 }
78492
78493 protected function parseError($str, $hash)
78494 {
78495 throw new \Exception($str);
78496 }
78497
78498 private function next()
78499 {
78500 if ($this->done) {
78501 return $this->EOF;
78502 }
78503 if ($this->input === '') {
78504 $this->done = true;
78505 }
78506
78507 $token = null;
78508 $match = null;
78509 $col = null;
78510 $lines = null;
78511
78512 if (!$this->more) {
78513 $this->yytext = '';
78514 $this->match = '';
78515 }
78516
78517 $rules = $this->getCurrentRules();
78518 $rulesLen = count($rules);
78519
78520 for ($i=0; $i < $rulesLen; $i++) {
78521 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
78522 preg_match_all('/\n.*/', $match[0], $lines);
78523 $lines = $lines[0];
78524 if ($lines) {
78525 $this->yylineno += count($lines);
78526 }
78527
78528 $this->yylloc = array(
78529 'first_line' => $this->yylloc['last_line'],
78530 'last_line' => $this->yylineno+1,
78531 'first_column' => $this->yylloc['last_column'],
78532 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
78533 );
78534 $this->yytext .= $match[0];
78535 $this->match .= $match[0];
78536 $this->yyleng = strlen($this->yytext);
78537 $this->more = false;
78538 $this->input = substr($this->input, strlen($match[0]));
78539 $this->matched .= $match[0];
78540 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
78541 if ($token) {
78542 return $token;
78543 }
78544
78545 return new Undefined();
78546 }
78547 }
78548
78549 if ($this->input === "") {
78550 return $this->EOF;
78551 }
78552
78553 $this->parseError(
78554 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
78555 array(
78556 'text' => "",
78557 'token' => null,
78558 'line' => $this->yylineno,
78559 )
78560 );
78561 }
78562
78563 private function getCurrentRules()
78564 {
78565 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
78566 }
78567
78568 private function performAction($avoiding_name_collisions, $YY_START)
78569 {
78570 switch ($avoiding_name_collisions) {
78571 case 0:
78572 break;
78573 case 1:
78574 return 6;
78575 break;
78576 case 2:
78577 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
78578
78579 return 4;
78580 case 3:
78581 return 17;
78582 case 4:
78583 return 18;
78584 case 5:
78585 return 23;
78586 case 6:
78587 return 24;
78588 case 7:
78589 return 22;
78590 case 8:
78591 return 21;
78592 case 9:
78593 return 10;
78594 case 10:
78595 return 11;
78596 case 11:
78597 return 8;
78598 case 12:
78599 return 14;
78600 case 13:
78601 return 'INVALID';
78602 }
78603 }
78604 }
78605 <?php
78606
78607
78608
78609
78610
78611
78612
78613
78614
78615
78616 namespace Seld\JsonLint;
78617
78618 class ParsingException extends \Exception
78619 {
78620 protected $details;
78621
78622 public function __construct($message, $details = array())
78623 {
78624 $this->details = $details;
78625 parent::__construct($message);
78626 }
78627
78628 public function getDetails()
78629 {
78630 return $this->details;
78631 }
78632 }
78633 <?php
78634
78635
78636
78637
78638
78639
78640
78641
78642
78643
78644 namespace Seld\JsonLint;
78645
78646 class Undefined
78647 {
78648 }
78649 MIT License
78650
78651 Copyright (c) 2016
78652
78653 Permission is hereby granted, free of charge, to any person obtaining a copy
78654 of this software and associated documentation files (the "Software"), to deal
78655 in the Software without restriction, including without limitation the rights
78656 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
78657 copies of the Software, and to permit persons to whom the Software is
78658 furnished to do so, subject to the following conditions:
78659
78660 The above copyright notice and this permission notice shall be included in all
78661 copies or substantial portions of the Software.
78662
78663 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
78664 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
78665 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
78666 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
78667 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
78668 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
78669 SOFTWARE.
78670 <?php
78671
78672 require __DIR__ . '/../vendor/autoload.php';
78673
78674 $data = json_decode(file_get_contents('data.json'));
78675
78676
78677 $validator = new JsonSchema\Validator();
78678 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
78679
78680 if ($validator->isValid()) {
78681 echo "The supplied JSON validates against the schema.\n";
78682 } else {
78683 echo "JSON does not validate. Violations:\n";
78684 foreach ($validator->getErrors() as $error) {
78685 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
78686 }
78687 }
78688 <?php
78689
78690
78691
78692
78693
78694
78695
78696
78697 namespace JsonSchema\Constraints;
78698
78699 use JsonSchema\Entity\JsonPointer;
78700 use JsonSchema\Exception\InvalidArgumentException;
78701 use JsonSchema\Exception\ValidationException;
78702 use JsonSchema\Validator;
78703
78704
78705
78706
78707
78708 class BaseConstraint
78709 {
78710
78711
78712
78713 protected $errors = array();
78714
78715
78716
78717
78718 protected $errorMask = Validator::ERROR_NONE;
78719
78720
78721
78722
78723 protected $factory;
78724
78725
78726
78727
78728 public function __construct(Factory $factory = null)
78729 {
78730 $this->factory = $factory ?: new Factory();
78731 }
78732
78733 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
78734 {
78735 $error = array(
78736 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
78737 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
78738 'message' => $message,
78739 'constraint' => $constraint,
78740 'context' => $this->factory->getErrorContext(),
78741 );
78742
78743 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
78744 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
78745 }
78746
78747 if (is_array($more) && count($more) > 0) {
78748 $error += $more;
78749 }
78750
78751 $this->errors[] = $error;
78752 $this->errorMask |= $error['context'];
78753 }
78754
78755 public function addErrors(array $errors)
78756 {
78757 if ($errors) {
78758 $this->errors = array_merge($this->errors, $errors);
78759 $errorMask = &$this->errorMask;
78760 array_walk($errors, function ($error) use (&$errorMask) {
78761 if (isset($error['context'])) {
78762 $errorMask |= $error['context'];
78763 }
78764 });
78765 }
78766 }
78767
78768 public function getErrors($errorContext = Validator::ERROR_ALL)
78769 {
78770 if ($errorContext === Validator::ERROR_ALL) {
78771 return $this->errors;
78772 }
78773
78774 return array_filter($this->errors, function ($error) use ($errorContext) {
78775 if ($errorContext & $error['context']) {
78776 return true;
78777 }
78778 });
78779 }
78780
78781 public function numErrors($errorContext = Validator::ERROR_ALL)
78782 {
78783 if ($errorContext === Validator::ERROR_ALL) {
78784 return count($this->errors);
78785 }
78786
78787 return count($this->getErrors($errorContext));
78788 }
78789
78790 public function isValid()
78791 {
78792 return !$this->getErrors();
78793 }
78794
78795
78796
78797
78798
78799 public function reset()
78800 {
78801 $this->errors = array();
78802 $this->errorMask = Validator::ERROR_NONE;
78803 }
78804
78805
78806
78807
78808
78809
78810 public function getErrorMask()
78811 {
78812 return $this->errorMask;
78813 }
78814
78815
78816
78817
78818
78819
78820
78821
78822 public static function arrayToObjectRecursive($array)
78823 {
78824 $json = json_encode($array);
78825 if (json_last_error() !== \JSON_ERROR_NONE) {
78826 $message = 'Unable to encode schema array as JSON';
78827 if (function_exists('json_last_error_msg')) {
78828 $message .= ': ' . json_last_error_msg();
78829 }
78830 throw new InvalidArgumentException($message);
78831 }
78832
78833 return (object) json_decode($json);
78834 }
78835 }
78836 <?php
78837
78838
78839
78840
78841
78842
78843
78844
78845 namespace JsonSchema\Constraints;
78846
78847 use JsonSchema\Entity\JsonPointer;
78848
78849
78850
78851
78852
78853
78854
78855 class CollectionConstraint extends Constraint
78856 {
78857
78858
78859
78860 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
78861 {
78862
78863  if (isset($schema->minItems) && count($value) < $schema->minItems) {
78864 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
78865 }
78866
78867
78868  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
78869 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
78870 }
78871
78872
78873  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
78874 $unique = $value;
78875 if (is_array($value) && count($value)) {
78876 $unique = array_map(function ($e) {
78877 return var_export($e, true);
78878 }, $value);
78879 }
78880 if (count(array_unique($unique)) != count($value)) {
78881 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
78882 }
78883 }
78884
78885
78886  if (isset($schema->items)) {
78887 $this->validateItems($value, $schema, $path, $i);
78888 }
78889 }
78890
78891
78892
78893
78894
78895
78896
78897
78898
78899 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
78900 {
78901 if (is_object($schema->items)) {
78902
78903  foreach ($value as $k => &$v) {
78904 $initErrors = $this->getErrors();
78905
78906
78907  $this->checkUndefined($v, $schema->items, $path, $k);
78908
78909
78910  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
78911 $secondErrors = $this->getErrors();
78912 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
78913 }
78914
78915
78916  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
78917 $this->errors = $secondErrors;
78918 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
78919 $this->errors = $initErrors;
78920 }
78921 }
78922 unset($v); 
78923
78924 } else {
78925
78926  foreach ($value as $k => &$v) {
78927 if (array_key_exists($k, $schema->items)) {
78928 $this->checkUndefined($v, $schema->items[$k], $path, $k);
78929 } else {
78930
78931  if (property_exists($schema, 'additionalItems')) {
78932 if ($schema->additionalItems !== false) {
78933 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
78934 } else {
78935 $this->addError(
78936 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
78937 }
78938 } else {
78939
78940  $this->checkUndefined($v, new \stdClass(), $path, $k);
78941 }
78942 }
78943 }
78944 unset($v); 
78945
78946
78947
78948  if (count($value) > 0) {
78949 for ($k = count($value); $k < count($schema->items); $k++) {
78950 $undefinedInstance = $this->factory->createInstanceFor('undefined');
78951 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
78952 }
78953 }
78954 }
78955 }
78956 }
78957 <?php
78958
78959
78960
78961
78962
78963
78964
78965
78966 namespace JsonSchema\Constraints;
78967
78968 use JsonSchema\Entity\JsonPointer;
78969
78970
78971
78972
78973
78974
78975
78976 abstract class Constraint extends BaseConstraint implements ConstraintInterface
78977 {
78978 protected $inlineSchemaProperty = '$schema';
78979
78980 const CHECK_MODE_NONE = 0x00000000;
78981 const CHECK_MODE_NORMAL = 0x00000001;
78982 const CHECK_MODE_TYPE_CAST = 0x00000002;
78983 const CHECK_MODE_COERCE_TYPES = 0x00000004;
78984 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
78985 const CHECK_MODE_EXCEPTIONS = 0x00000010;
78986 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
78987 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
78988 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
78989
78990
78991
78992
78993
78994
78995
78996
78997
78998 protected function incrementPath(JsonPointer $path = null, $i)
78999 {
79000 $path = $path ?: new JsonPointer('');
79001 $path = $path->withPropertyPaths(
79002 array_merge(
79003 $path->getPropertyPaths(),
79004 array_filter(array($i), 'strlen')
79005 )
79006 );
79007
79008 return $path;
79009 }
79010
79011
79012
79013
79014
79015
79016
79017
79018
79019 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
79020 {
79021 $validator = $this->factory->createInstanceFor('collection');
79022 $validator->check($value, $schema, $path, $i);
79023
79024 $this->addErrors($validator->getErrors());
79025 }
79026
79027
79028
79029
79030
79031
79032
79033
79034
79035
79036
79037 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
79038 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
79039 {
79040 $validator = $this->factory->createInstanceFor('object');
79041 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
79042
79043 $this->addErrors($validator->getErrors());
79044 }
79045
79046
79047
79048
79049
79050
79051
79052
79053
79054 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
79055 {
79056 $validator = $this->factory->createInstanceFor('type');
79057 $validator->check($value, $schema, $path, $i);
79058
79059 $this->addErrors($validator->getErrors());
79060 }
79061
79062
79063
79064
79065
79066
79067
79068
79069
79070 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
79071 {
79072 $validator = $this->factory->createInstanceFor('undefined');
79073
79074 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
79075
79076 $this->addErrors($validator->getErrors());
79077 }
79078
79079
79080
79081
79082
79083
79084
79085
79086
79087 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
79088 {
79089 $validator = $this->factory->createInstanceFor('string');
79090 $validator->check($value, $schema, $path, $i);
79091
79092 $this->addErrors($validator->getErrors());
79093 }
79094
79095
79096
79097
79098
79099
79100
79101
79102
79103 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
79104 {
79105 $validator = $this->factory->createInstanceFor('number');
79106 $validator->check($value, $schema, $path, $i);
79107
79108 $this->addErrors($validator->getErrors());
79109 }
79110
79111
79112
79113
79114
79115
79116
79117
79118
79119 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
79120 {
79121 $validator = $this->factory->createInstanceFor('enum');
79122 $validator->check($value, $schema, $path, $i);
79123
79124 $this->addErrors($validator->getErrors());
79125 }
79126
79127
79128
79129
79130
79131
79132
79133
79134
79135 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
79136 {
79137 $validator = $this->factory->createInstanceFor('format');
79138 $validator->check($value, $schema, $path, $i);
79139
79140 $this->addErrors($validator->getErrors());
79141 }
79142
79143
79144
79145
79146
79147
79148 protected function getTypeCheck()
79149 {
79150 return $this->factory->getTypeCheck();
79151 }
79152
79153
79154
79155
79156
79157
79158 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
79159 {
79160 $result = array_map(
79161 function ($path) {
79162 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
79163 },
79164 $pointer->getPropertyPaths()
79165 );
79166
79167 return trim(implode('', $result), '.');
79168 }
79169 }
79170 <?php
79171
79172
79173
79174
79175
79176
79177
79178
79179 namespace JsonSchema\Constraints;
79180
79181 use JsonSchema\Entity\JsonPointer;
79182
79183
79184
79185
79186
79187
79188 interface ConstraintInterface
79189 {
79190
79191
79192
79193
79194
79195 public function getErrors();
79196
79197
79198
79199
79200
79201
79202 public function addErrors(array $errors);
79203
79204
79205
79206
79207
79208
79209
79210
79211
79212 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
79213
79214
79215
79216
79217
79218
79219 public function isValid();
79220
79221
79222
79223
79224
79225
79226
79227
79228
79229
79230
79231
79232
79233 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
79234 }
79235 <?php
79236
79237
79238
79239
79240
79241
79242
79243
79244 namespace JsonSchema\Constraints;
79245
79246 use JsonSchema\Entity\JsonPointer;
79247
79248
79249
79250
79251
79252
79253
79254 class EnumConstraint extends Constraint
79255 {
79256
79257
79258
79259 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
79260 {
79261
79262  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
79263 return;
79264 }
79265 $type = gettype($element);
79266
79267 foreach ($schema->enum as $enum) {
79268 $enumType = gettype($enum);
79269 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
79270 if ((object) $element == $enum) {
79271 return;
79272 }
79273 }
79274
79275 if ($type === gettype($enum)) {
79276 if ($type == 'object') {
79277 if ($element == $enum) {
79278 return;
79279 }
79280 } elseif ($element === $enum) {
79281 return;
79282 }
79283 }
79284 }
79285
79286 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
79287 }
79288 }
79289 <?php
79290
79291
79292
79293
79294
79295
79296
79297
79298 namespace JsonSchema\Constraints;
79299
79300 use JsonSchema\Exception\InvalidArgumentException;
79301 use JsonSchema\SchemaStorage;
79302 use JsonSchema\SchemaStorageInterface;
79303 use JsonSchema\Uri\UriRetriever;
79304 use JsonSchema\UriRetrieverInterface;
79305 use JsonSchema\Validator;
79306
79307
79308
79309
79310 class Factory
79311 {
79312
79313
79314
79315 protected $schemaStorage;
79316
79317
79318
79319
79320 protected $uriRetriever;
79321
79322
79323
79324
79325 private $checkMode = Constraint::CHECK_MODE_NORMAL;
79326
79327
79328
79329
79330 private $typeCheck = array();
79331
79332
79333
79334
79335 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
79336
79337
79338
79339
79340 protected $constraintMap = array(
79341 'array' => 'JsonSchema\Constraints\CollectionConstraint',
79342 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
79343 'object' => 'JsonSchema\Constraints\ObjectConstraint',
79344 'type' => 'JsonSchema\Constraints\TypeConstraint',
79345 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
79346 'string' => 'JsonSchema\Constraints\StringConstraint',
79347 'number' => 'JsonSchema\Constraints\NumberConstraint',
79348 'enum' => 'JsonSchema\Constraints\EnumConstraint',
79349 'format' => 'JsonSchema\Constraints\FormatConstraint',
79350 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
79351 'validator' => 'JsonSchema\Validator'
79352 );
79353
79354
79355
79356
79357 private $instanceCache = array();
79358
79359
79360
79361
79362
79363
79364 public function __construct(
79365 SchemaStorageInterface $schemaStorage = null,
79366 UriRetrieverInterface $uriRetriever = null,
79367 $checkMode = Constraint::CHECK_MODE_NORMAL
79368 ) {
79369
79370  $this->setConfig($checkMode);
79371
79372 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
79373 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
79374 }
79375
79376
79377
79378
79379
79380
79381 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
79382 {
79383 $this->checkMode = $checkMode;
79384 }
79385
79386
79387
79388
79389
79390
79391 public function addConfig($options)
79392 {
79393 $this->checkMode |= $options;
79394 }
79395
79396
79397
79398
79399
79400
79401 public function removeConfig($options)
79402 {
79403 $this->checkMode &= ~$options;
79404 }
79405
79406
79407
79408
79409
79410
79411
79412
79413 public function getConfig($options = null)
79414 {
79415 if ($options === null) {
79416 return $this->checkMode;
79417 }
79418
79419 return $this->checkMode & $options;
79420 }
79421
79422
79423
79424
79425 public function getUriRetriever()
79426 {
79427 return $this->uriRetriever;
79428 }
79429
79430 public function getSchemaStorage()
79431 {
79432 return $this->schemaStorage;
79433 }
79434
79435 public function getTypeCheck()
79436 {
79437 if (!isset($this->typeCheck[$this->checkMode])) {
79438 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
79439 ? new TypeCheck\LooseTypeCheck()
79440 : new TypeCheck\StrictTypeCheck();
79441 }
79442
79443 return $this->typeCheck[$this->checkMode];
79444 }
79445
79446
79447
79448
79449
79450
79451
79452 public function setConstraintClass($name, $class)
79453 {
79454
79455  if (!class_exists($class)) {
79456 throw new InvalidArgumentException('Unknown constraint ' . $name);
79457 }
79458
79459  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
79460 throw new InvalidArgumentException('Invalid class ' . $name);
79461 }
79462 $this->constraintMap[$name] = $class;
79463
79464 return $this;
79465 }
79466
79467
79468
79469
79470
79471
79472
79473
79474
79475
79476 public function createInstanceFor($constraintName)
79477 {
79478 if (!isset($this->constraintMap[$constraintName])) {
79479 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
79480 }
79481
79482 if (!isset($this->instanceCache[$constraintName])) {
79483 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
79484 }
79485
79486 return clone $this->instanceCache[$constraintName];
79487 }
79488
79489
79490
79491
79492
79493
79494 public function getErrorContext()
79495 {
79496 return $this->errorContext;
79497 }
79498
79499
79500
79501
79502
79503
79504 public function setErrorContext($errorContext)
79505 {
79506 $this->errorContext = $errorContext;
79507 }
79508 }
79509 <?php
79510
79511
79512
79513
79514
79515
79516
79517
79518 namespace JsonSchema\Constraints;
79519
79520 use JsonSchema\Entity\JsonPointer;
79521 use JsonSchema\Rfc3339;
79522
79523
79524
79525
79526
79527
79528
79529
79530 class FormatConstraint extends Constraint
79531 {
79532
79533
79534
79535 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
79536 {
79537 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
79538 return;
79539 }
79540
79541 switch ($schema->format) {
79542 case 'date':
79543 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
79544 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
79545 }
79546 break;
79547
79548 case 'time':
79549 if (!$this->validateDateTime($element, 'H:i:s')) {
79550 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
79551 }
79552 break;
79553
79554 case 'date-time':
79555 if (null === Rfc3339::createFromString($element)) {
79556 $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));
79557 }
79558 break;
79559
79560 case 'utc-millisec':
79561 if (!$this->validateDateTime($element, 'U')) {
79562 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
79563 }
79564 break;
79565
79566 case 'regex':
79567 if (!$this->validateRegex($element)) {
79568 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
79569 }
79570 break;
79571
79572 case 'color':
79573 if (!$this->validateColor($element)) {
79574 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
79575 }
79576 break;
79577
79578 case 'style':
79579 if (!$this->validateStyle($element)) {
79580 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
79581 }
79582 break;
79583
79584 case 'phone':
79585 if (!$this->validatePhone($element)) {
79586 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
79587 }
79588 break;
79589
79590 case 'uri':
79591 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
79592 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
79593 }
79594 break;
79595
79596 case 'uriref':
79597 case 'uri-reference':
79598 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
79599
79600  
79601  
79602  if (substr($element, 0, 2) === '//') { 
79603  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
79604 } elseif (substr($element, 0, 1) === '/') { 
79605  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
79606 } elseif (strlen($element)) { 
79607  $pathParts = explode('/', $element, 2);
79608 if (strpos($pathParts[0], ':') !== false) {
79609 $validURL = null;
79610 } else {
79611 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
79612 }
79613 } else {
79614 $validURL = null;
79615 }
79616 if ($validURL === null) {
79617 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
79618 }
79619 }
79620 break;
79621
79622 case 'email':
79623 $filterFlags = FILTER_NULL_ON_FAILURE;
79624 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
79625
79626  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
79627  }
79628 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
79629 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
79630 }
79631 break;
79632
79633 case 'ip-address':
79634 case 'ipv4':
79635 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
79636 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
79637 }
79638 break;
79639
79640 case 'ipv6':
79641 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
79642 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
79643 }
79644 break;
79645
79646 case 'host-name':
79647 case 'hostname':
79648 if (!$this->validateHostname($element)) {
79649 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
79650 }
79651 break;
79652
79653 default:
79654
79655  
79656  
79657  
79658  
79659  
79660  break;
79661 }
79662 }
79663
79664 protected function validateDateTime($datetime, $format)
79665 {
79666 $dt = \DateTime::createFromFormat($format, $datetime);
79667
79668 if (!$dt) {
79669 return false;
79670 }
79671
79672 if ($datetime === $dt->format($format)) {
79673 return true;
79674 }
79675
79676
79677  
79678  
79679  
79680  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
79681 return true;
79682 }
79683
79684 return false;
79685 }
79686
79687 protected function validateRegex($regex)
79688 {
79689 return false !== @preg_match('/' . $regex . '/u', '');
79690 }
79691
79692 protected function validateColor($color)
79693 {
79694 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
79695 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
79696 'red', 'silver', 'teal', 'white', 'yellow'))) {
79697 return true;
79698 }
79699
79700 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
79701 }
79702
79703 protected function validateStyle($style)
79704 {
79705 $properties = explode(';', rtrim($style, ';'));
79706 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
79707
79708 return empty($invalidEntries);
79709 }
79710
79711 protected function validatePhone($phone)
79712 {
79713 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
79714 }
79715
79716 protected function validateHostname($host)
79717 {
79718 $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';
79719
79720 return preg_match($hostnameRegex, $host);
79721 }
79722 }
79723 <?php
79724
79725
79726
79727
79728
79729
79730
79731
79732 namespace JsonSchema\Constraints;
79733
79734 use JsonSchema\Entity\JsonPointer;
79735
79736
79737
79738
79739
79740
79741
79742 class NumberConstraint extends Constraint
79743 {
79744
79745
79746
79747 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
79748 {
79749
79750  if (isset($schema->exclusiveMinimum)) {
79751 if (isset($schema->minimum)) {
79752 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
79753 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
79754 } elseif ($element < $schema->minimum) {
79755 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
79756 }
79757 } else {
79758 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
79759 }
79760 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
79761 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
79762 }
79763
79764
79765  if (isset($schema->exclusiveMaximum)) {
79766 if (isset($schema->maximum)) {
79767 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
79768 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
79769 } elseif ($element > $schema->maximum) {
79770 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
79771 }
79772 } else {
79773 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
79774 }
79775 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
79776 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
79777 }
79778
79779
79780  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
79781 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
79782 }
79783
79784
79785  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
79786 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
79787 }
79788
79789 $this->checkFormat($element, $schema, $path, $i);
79790 }
79791
79792 private function fmod($number1, $number2)
79793 {
79794 $modulus = ($number1 - round($number1 / $number2) * $number2);
79795 $precision = 0.0000000001;
79796
79797 if (-$precision < $modulus && $modulus < $precision) {
79798 return 0.0;
79799 }
79800
79801 return $modulus;
79802 }
79803 }
79804 <?php
79805
79806
79807
79808
79809
79810
79811
79812
79813 namespace JsonSchema\Constraints;
79814
79815 use JsonSchema\Entity\JsonPointer;
79816
79817
79818
79819
79820
79821
79822
79823 class ObjectConstraint extends Constraint
79824 {
79825
79826
79827
79828 protected $appliedDefaults = array();
79829
79830
79831
79832
79833 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
79834 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
79835 {
79836 if ($element instanceof UndefinedConstraint) {
79837 return;
79838 }
79839
79840 $this->appliedDefaults = $appliedDefaults;
79841
79842 $matches = array();
79843 if ($patternProperties) {
79844
79845  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
79846 }
79847
79848 if ($properties) {
79849
79850  $this->validateProperties($element, $properties, $path);
79851 }
79852
79853
79854  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
79855 }
79856
79857 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
79858 {
79859 $try = array('/', '#', '+', '~', '%');
79860 $matches = array();
79861 foreach ($patternProperties as $pregex => $schema) {
79862 $delimiter = '/';
79863
79864  foreach ($try as $delimiter) {
79865 if (strpos($pregex, $delimiter) === false) { 
79866  break;
79867 }
79868 }
79869
79870
79871  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
79872 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
79873 continue;
79874 }
79875 foreach ($element as $i => $value) {
79876 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
79877 $matches[] = $i;
79878 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
79879 }
79880 }
79881 }
79882
79883 return $matches;
79884 }
79885
79886
79887
79888
79889
79890
79891
79892
79893
79894
79895
79896 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
79897 $properties = null, $additionalProp = null)
79898 {
79899 $this->validateMinMaxConstraint($element, $schema, $path);
79900
79901 foreach ($element as $i => $value) {
79902 $definition = $this->getProperty($properties, $i);
79903
79904
79905  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
79906 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
79907 }
79908
79909
79910  if (!in_array($i, $matches) && $additionalProp && !$definition) {
79911 if ($additionalProp === true) {
79912 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
79913 } else {
79914 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
79915 }
79916 }
79917
79918
79919  $require = $this->getProperty($definition, 'requires');
79920 if ($require && !$this->getProperty($element, $require)) {
79921 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
79922 }
79923
79924 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
79925 if (is_object($property)) {
79926 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
79927 }
79928 }
79929 }
79930
79931
79932
79933
79934
79935
79936
79937
79938 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
79939 {
79940 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
79941
79942 foreach ($properties as $i => $value) {
79943 $property = &$this->getProperty($element, $i, $undefinedConstraint);
79944 $definition = $this->getProperty($properties, $i);
79945
79946 if (is_object($definition)) {
79947
79948  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
79949 }
79950 }
79951 }
79952
79953
79954
79955
79956
79957
79958
79959
79960
79961
79962 protected function &getProperty(&$element, $property, $fallback = null)
79963 {
79964 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
79965 return $element[$property];
79966 } elseif (is_object($element) && property_exists($element, $property)) {
79967 return $element->$property;
79968 }
79969
79970 return $fallback;
79971 }
79972
79973
79974
79975
79976
79977
79978
79979
79980 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
79981 {
79982
79983  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
79984 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
79985 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
79986 }
79987 }
79988
79989  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
79990 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
79991 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
79992 }
79993 }
79994 }
79995 }
79996 <?php
79997
79998
79999
80000
80001
80002
80003
80004
80005 namespace JsonSchema\Constraints;
80006
80007 use JsonSchema\Entity\JsonPointer;
80008 use JsonSchema\Exception\InvalidArgumentException;
80009 use JsonSchema\Exception\InvalidSchemaException;
80010 use JsonSchema\Exception\RuntimeException;
80011 use JsonSchema\Validator;
80012
80013
80014
80015
80016
80017
80018
80019 class SchemaConstraint extends Constraint
80020 {
80021 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
80022
80023
80024
80025
80026 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
80027 {
80028 if ($schema !== null) {
80029
80030  $validationSchema = $schema;
80031 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
80032
80033  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
80034 } else {
80035 throw new InvalidArgumentException('no schema found to verify against');
80036 }
80037
80038
80039  if (is_array($validationSchema)) {
80040 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
80041 }
80042
80043
80044  
80045  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
80046 if (!$this->getTypeCheck()->isObject($validationSchema)) {
80047 throw new RuntimeException('Cannot validate the schema of a non-object');
80048 }
80049 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
80050 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
80051 } else {
80052 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
80053 }
80054
80055
80056  $schemaStorage = $this->factory->getSchemaStorage();
80057 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
80058 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
80059 }
80060
80061
80062  $initialErrorCount = $this->numErrors();
80063 $initialConfig = $this->factory->getConfig();
80064 $initialContext = $this->factory->getErrorContext();
80065 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
80066 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
80067 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
80068
80069
80070  try {
80071 $this->check($validationSchema, $schemaSpec);
80072 } catch (\Exception $e) {
80073 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
80074 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
80075 }
80076 }
80077 if ($this->numErrors() > $initialErrorCount) {
80078 $this->addError($path, 'Schema is not valid', 'schema');
80079 }
80080
80081
80082  $this->factory->setConfig($initialConfig);
80083 $this->factory->setErrorContext($initialContext);
80084 }
80085
80086
80087  $this->checkUndefined($element, $validationSchema, $path, $i);
80088 }
80089 }
80090 <?php
80091
80092
80093
80094
80095
80096
80097
80098
80099 namespace JsonSchema\Constraints;
80100
80101 use JsonSchema\Entity\JsonPointer;
80102
80103
80104
80105
80106
80107
80108
80109 class StringConstraint extends Constraint
80110 {
80111
80112
80113
80114 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
80115 {
80116
80117  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
80118 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
80119 'maxLength' => $schema->maxLength,
80120 ));
80121 }
80122
80123
80124  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
80125 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
80126 'minLength' => $schema->minLength,
80127 ));
80128 }
80129
80130
80131  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
80132 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
80133 'pattern' => $schema->pattern,
80134 ));
80135 }
80136
80137 $this->checkFormat($element, $schema, $path, $i);
80138 }
80139
80140 private function strlen($string)
80141 {
80142 if (extension_loaded('mbstring')) {
80143 return mb_strlen($string, mb_detect_encoding($string));
80144 }
80145
80146
80147  return strlen($string); 
80148  }
80149 }
80150 <?php
80151
80152 namespace JsonSchema\Constraints\TypeCheck;
80153
80154 class LooseTypeCheck implements TypeCheckInterface
80155 {
80156 public static function isObject($value)
80157 {
80158 return
80159 is_object($value) ||
80160 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
80161 }
80162
80163 public static function isArray($value)
80164 {
80165 return
80166 is_array($value) &&
80167 (count($value) == 0 || !self::isAssociativeArray($value));
80168 }
80169
80170 public static function propertyGet($value, $property)
80171 {
80172 if (is_object($value)) {
80173 return $value->{$property};
80174 }
80175
80176 return $value[$property];
80177 }
80178
80179 public static function propertySet(&$value, $property, $data)
80180 {
80181 if (is_object($value)) {
80182 $value->{$property} = $data;
80183 } else {
80184 $value[$property] = $data;
80185 }
80186 }
80187
80188 public static function propertyExists($value, $property)
80189 {
80190 if (is_object($value)) {
80191 return property_exists($value, $property);
80192 }
80193
80194 return array_key_exists($property, $value);
80195 }
80196
80197 public static function propertyCount($value)
80198 {
80199 if (is_object($value)) {
80200 return count(get_object_vars($value));
80201 }
80202
80203 return count($value);
80204 }
80205
80206
80207
80208
80209
80210
80211
80212
80213 private static function isAssociativeArray($arr)
80214 {
80215 return array_keys($arr) !== range(0, count($arr) - 1);
80216 }
80217 }
80218 <?php
80219
80220 namespace JsonSchema\Constraints\TypeCheck;
80221
80222 class StrictTypeCheck implements TypeCheckInterface
80223 {
80224 public static function isObject($value)
80225 {
80226 return is_object($value);
80227 }
80228
80229 public static function isArray($value)
80230 {
80231 return is_array($value);
80232 }
80233
80234 public static function propertyGet($value, $property)
80235 {
80236 return $value->{$property};
80237 }
80238
80239 public static function propertySet(&$value, $property, $data)
80240 {
80241 $value->{$property} = $data;
80242 }
80243
80244 public static function propertyExists($value, $property)
80245 {
80246 return property_exists($value, $property);
80247 }
80248
80249 public static function propertyCount($value)
80250 {
80251 if (!is_object($value)) {
80252 return 0;
80253 }
80254
80255 return count(get_object_vars($value));
80256 }
80257 }
80258 <?php
80259
80260 namespace JsonSchema\Constraints\TypeCheck;
80261
80262 interface TypeCheckInterface
80263 {
80264 public static function isObject($value);
80265
80266 public static function isArray($value);
80267
80268 public static function propertyGet($value, $property);
80269
80270 public static function propertySet(&$value, $property, $data);
80271
80272 public static function propertyExists($value, $property);
80273
80274 public static function propertyCount($value);
80275 }
80276 <?php
80277
80278
80279
80280
80281
80282
80283
80284
80285 namespace JsonSchema\Constraints;
80286
80287 use JsonSchema\Entity\JsonPointer;
80288 use JsonSchema\Exception\InvalidArgumentException;
80289 use UnexpectedValueException as StandardUnexpectedValueException;
80290
80291
80292
80293
80294
80295
80296
80297 class TypeConstraint extends Constraint
80298 {
80299
80300
80301
80302 public static $wording = array(
80303 'integer' => 'an integer',
80304 'number' => 'a number',
80305 'boolean' => 'a boolean',
80306 'object' => 'an object',
80307 'array' => 'an array',
80308 'string' => 'a string',
80309 'null' => 'a null',
80310 'any' => null, 
80311  0 => null, 
80312  );
80313
80314
80315
80316
80317 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
80318 {
80319 $type = isset($schema->type) ? $schema->type : null;
80320 $isValid = false;
80321 $wording = array();
80322
80323 if (is_array($type)) {
80324 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
80325 } elseif (is_object($type)) {
80326 $this->checkUndefined($value, $type, $path);
80327
80328 return;
80329 } else {
80330 $isValid = $this->validateType($value, $type);
80331 }
80332
80333 if ($isValid === false) {
80334 if (!is_array($type)) {
80335 $this->validateTypeNameWording($type);
80336 $wording[] = self::$wording[$type];
80337 }
80338 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
80339 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
80340 }
80341 }
80342
80343
80344
80345
80346
80347
80348
80349
80350
80351
80352
80353
80354 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
80355 {
80356 foreach ($type as $tp) {
80357
80358  
80359  if (is_object($tp)) {
80360 if (!$isValid) {
80361 $validator = $this->factory->createInstanceFor('type');
80362 $subSchema = new \stdClass();
80363 $subSchema->type = $tp;
80364 $validator->check($value, $subSchema, $path, null);
80365 $error = $validator->getErrors();
80366 $isValid = !(bool) $error;
80367 $validTypesWording[] = self::$wording['object'];
80368 }
80369 } else {
80370 $this->validateTypeNameWording($tp);
80371 $validTypesWording[] = self::$wording[$tp];
80372 if (!$isValid) {
80373 $isValid = $this->validateType($value, $tp);
80374 }
80375 }
80376 }
80377 }
80378
80379
80380
80381
80382
80383
80384
80385
80386
80387
80388
80389
80390 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
80391 {
80392 if ($listEnd === false || !isset($elements[1])) {
80393 return implode($delimiter, $elements);
80394 }
80395 $lastElement = array_slice($elements, -1);
80396 $firsElements = join($delimiter, array_slice($elements, 0, -1));
80397 $implodedElements = array_merge(array($firsElements), $lastElement);
80398
80399 return join(" $listEnd ", $implodedElements);
80400 }
80401
80402
80403
80404
80405
80406
80407
80408
80409
80410 protected function validateTypeNameWording($type)
80411 {
80412 if (!isset(self::$wording[$type])) {
80413 throw new StandardUnexpectedValueException(
80414 sprintf(
80415 'No wording for %s available, expected wordings are: [%s]',
80416 var_export($type, true),
80417 implode(', ', array_filter(self::$wording)))
80418 );
80419 }
80420 }
80421
80422
80423
80424
80425
80426
80427
80428
80429
80430
80431
80432 protected function validateType(&$value, $type)
80433 {
80434
80435  if (!$type) {
80436 return true;
80437 }
80438
80439 if ('any' === $type) {
80440 return true;
80441 }
80442
80443 if ('object' === $type) {
80444 return $this->getTypeCheck()->isObject($value);
80445 }
80446
80447 if ('array' === $type) {
80448 return $this->getTypeCheck()->isArray($value);
80449 }
80450
80451 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
80452
80453 if ('integer' === $type) {
80454 if ($coerce) {
80455 $value = $this->toInteger($value);
80456 }
80457
80458 return is_int($value);
80459 }
80460
80461 if ('number' === $type) {
80462 if ($coerce) {
80463 $value = $this->toNumber($value);
80464 }
80465
80466 return is_numeric($value) && !is_string($value);
80467 }
80468
80469 if ('boolean' === $type) {
80470 if ($coerce) {
80471 $value = $this->toBoolean($value);
80472 }
80473
80474 return is_bool($value);
80475 }
80476
80477 if ('string' === $type) {
80478 return is_string($value);
80479 }
80480
80481 if ('email' === $type) {
80482 return is_string($value);
80483 }
80484
80485 if ('null' === $type) {
80486 return is_null($value);
80487 }
80488
80489 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
80490 }
80491
80492
80493
80494
80495
80496
80497
80498
80499 protected function toBoolean($value)
80500 {
80501 if ($value === 'true') {
80502 return true;
80503 }
80504
80505 if ($value === 'false') {
80506 return false;
80507 }
80508
80509 return $value;
80510 }
80511
80512
80513
80514
80515
80516
80517
80518
80519 protected function toNumber($value)
80520 {
80521 if (is_numeric($value)) {
80522 return $value + 0; 
80523  }
80524
80525 return $value;
80526 }
80527
80528 protected function toInteger($value)
80529 {
80530 if (is_numeric($value) && (int) $value == $value) {
80531 return (int) $value; 
80532  }
80533
80534 return $value;
80535 }
80536 }
80537 <?php
80538
80539
80540
80541
80542
80543
80544
80545
80546 namespace JsonSchema\Constraints;
80547
80548 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
80549 use JsonSchema\Entity\JsonPointer;
80550 use JsonSchema\Exception\ValidationException;
80551 use JsonSchema\Uri\UriResolver;
80552
80553
80554
80555
80556
80557
80558
80559 class UndefinedConstraint extends Constraint
80560 {
80561
80562
80563
80564 protected $appliedDefaults = array();
80565
80566
80567
80568
80569 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
80570 {
80571 if (is_null($schema) || !is_object($schema)) {
80572 return;
80573 }
80574
80575 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
80576 if ($fromDefault) {
80577 $path->setFromDefault();
80578 }
80579
80580
80581  $this->validateCommonProperties($value, $schema, $path, $i);
80582
80583
80584  $this->validateOfProperties($value, $schema, $path, '');
80585
80586
80587  $this->validateTypes($value, $schema, $path, $i);
80588 }
80589
80590
80591
80592
80593
80594
80595
80596
80597
80598 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
80599 {
80600
80601  if ($this->getTypeCheck()->isArray($value)) {
80602 $this->checkArray($value, $schema, $path, $i);
80603 }
80604
80605
80606  if (LooseTypeCheck::isObject($value)) { 
80607  
80608  
80609  $this->checkObject(
80610 $value,
80611 $schema,
80612 $path,
80613 isset($schema->properties) ? $schema->properties : null,
80614 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
80615 isset($schema->patternProperties) ? $schema->patternProperties : null,
80616 $this->appliedDefaults
80617 );
80618 }
80619
80620
80621  if (is_string($value)) {
80622 $this->checkString($value, $schema, $path, $i);
80623 }
80624
80625
80626  if (is_numeric($value)) {
80627 $this->checkNumber($value, $schema, $path, $i);
80628 }
80629
80630
80631  if (isset($schema->enum)) {
80632 $this->checkEnum($value, $schema, $path, $i);
80633 }
80634 }
80635
80636
80637
80638
80639
80640
80641
80642
80643
80644 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
80645 {
80646
80647  if (isset($schema->extends)) {
80648 if (is_string($schema->extends)) {
80649 $schema->extends = $this->validateUri($schema, $schema->extends);
80650 }
80651 if (is_array($schema->extends)) {
80652 foreach ($schema->extends as $extends) {
80653 $this->checkUndefined($value, $extends, $path, $i);
80654 }
80655 } else {
80656 $this->checkUndefined($value, $schema->extends, $path, $i);
80657 }
80658 }
80659
80660
80661  if (!$path->fromDefault()) {
80662 $this->applyDefaultValues($value, $schema, $path);
80663 }
80664
80665
80666  if ($this->getTypeCheck()->isObject($value)) {
80667 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
80668
80669  foreach ($schema->required as $required) {
80670 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
80671 $this->addError(
80672 $this->incrementPath($path ?: new JsonPointer(''), $required),
80673 'The property ' . $required . ' is required',
80674 'required'
80675 );
80676 }
80677 }
80678 } elseif (isset($schema->required) && !is_array($schema->required)) {
80679
80680  if ($schema->required && $value instanceof self) {
80681 $propertyPaths = $path->getPropertyPaths();
80682 $propertyName = end($propertyPaths);
80683 $this->addError(
80684 $path,
80685 'The property ' . $propertyName . ' is required',
80686 'required'
80687 );
80688 }
80689 } else {
80690
80691  
80692  if ($value instanceof self) {
80693 return;
80694 }
80695 }
80696 }
80697
80698
80699  if (!($value instanceof self)) {
80700 $this->checkType($value, $schema, $path, $i);
80701 }
80702
80703
80704  if (isset($schema->disallow)) {
80705 $initErrors = $this->getErrors();
80706
80707 $typeSchema = new \stdClass();
80708 $typeSchema->type = $schema->disallow;
80709 $this->checkType($value, $typeSchema, $path);
80710
80711
80712  if (count($this->getErrors()) == count($initErrors)) {
80713 $this->addError($path, 'Disallowed value was matched', 'disallow');
80714 } else {
80715 $this->errors = $initErrors;
80716 }
80717 }
80718
80719 if (isset($schema->not)) {
80720 $initErrors = $this->getErrors();
80721 $this->checkUndefined($value, $schema->not, $path, $i);
80722
80723
80724  if (count($this->getErrors()) == count($initErrors)) {
80725 $this->addError($path, 'Matched a schema which it should not', 'not');
80726 } else {
80727 $this->errors = $initErrors;
80728 }
80729 }
80730
80731
80732  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
80733 $this->validateDependencies($value, $schema->dependencies, $path);
80734 }
80735 }
80736
80737
80738
80739
80740
80741
80742
80743
80744
80745
80746 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
80747 {
80748
80749  if (!$requiredOnly) {
80750 return true;
80751 }
80752
80753  if (
80754 $name !== null
80755 && isset($parentSchema->required)
80756 && is_array($parentSchema->required)
80757 && in_array($name, $parentSchema->required)
80758 ) {
80759 return true;
80760 }
80761
80762  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
80763 return true;
80764 }
80765
80766  return false;
80767 }
80768
80769
80770
80771
80772
80773
80774
80775
80776 protected function applyDefaultValues(&$value, $schema, $path)
80777 {
80778
80779  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
80780 return;
80781 }
80782
80783
80784  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
80785 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
80786
80787  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
80788 $propertyDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($propertyDefinition);
80789 if (
80790 !LooseTypeCheck::propertyExists($value, $currentProperty)
80791 && property_exists($propertyDefinition, 'default')
80792 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
80793 ) {
80794
80795  if (is_object($propertyDefinition->default)) {
80796 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
80797 } else {
80798 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
80799 }
80800 $this->appliedDefaults[] = $currentProperty;
80801 }
80802 }
80803 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
80804 $items = array();
80805 if (LooseTypeCheck::isArray($schema->items)) {
80806 $items = $schema->items;
80807 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
80808 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
80809 }
80810
80811  foreach ($items as $currentItem => $itemDefinition) {
80812 $itemDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($itemDefinition);
80813 if (
80814 !array_key_exists($currentItem, $value)
80815 && property_exists($itemDefinition, 'default')
80816 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
80817 if (is_object($itemDefinition->default)) {
80818 $value[$currentItem] = clone $itemDefinition->default;
80819 } else {
80820 $value[$currentItem] = $itemDefinition->default;
80821 }
80822 }
80823 $path->setFromDefault();
80824 }
80825 } elseif (
80826 $value instanceof self
80827 && property_exists($schema, 'default')
80828 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
80829
80830  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
80831 $path->setFromDefault();
80832 }
80833 }
80834
80835
80836
80837
80838
80839
80840
80841
80842
80843 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
80844 {
80845
80846  if ($value instanceof self) {
80847 return;
80848 }
80849
80850 if (isset($schema->allOf)) {
80851 $isValid = true;
80852 foreach ($schema->allOf as $allOf) {
80853 $initErrors = $this->getErrors();
80854 $this->checkUndefined($value, $allOf, $path, $i);
80855 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
80856 }
80857 if (!$isValid) {
80858 $this->addError($path, 'Failed to match all schemas', 'allOf');
80859 }
80860 }
80861
80862 if (isset($schema->anyOf)) {
80863 $isValid = false;
80864 $startErrors = $this->getErrors();
80865 $caughtException = null;
80866 foreach ($schema->anyOf as $anyOf) {
80867 $initErrors = $this->getErrors();
80868 try {
80869 $this->checkUndefined($value, $anyOf, $path, $i);
80870 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
80871 break;
80872 }
80873 } catch (ValidationException $e) {
80874 $isValid = false;
80875 }
80876 }
80877 if (!$isValid) {
80878 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
80879 } else {
80880 $this->errors = $startErrors;
80881 }
80882 }
80883
80884 if (isset($schema->oneOf)) {
80885 $allErrors = array();
80886 $matchedSchemas = 0;
80887 $startErrors = $this->getErrors();
80888 foreach ($schema->oneOf as $oneOf) {
80889 try {
80890 $this->errors = array();
80891 $this->checkUndefined($value, $oneOf, $path, $i);
80892 if (count($this->getErrors()) == 0) {
80893 $matchedSchemas++;
80894 }
80895 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
80896 } catch (ValidationException $e) {
80897
80898  
80899  }
80900 }
80901 if ($matchedSchemas !== 1) {
80902 $this->addErrors(array_merge($allErrors, $startErrors));
80903 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
80904 } else {
80905 $this->errors = $startErrors;
80906 }
80907 }
80908 }
80909
80910
80911
80912
80913
80914
80915
80916
80917
80918 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
80919 {
80920 foreach ($dependencies as $key => $dependency) {
80921 if ($this->getTypeCheck()->propertyExists($value, $key)) {
80922 if (is_string($dependency)) {
80923
80924  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
80925 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
80926 }
80927 } elseif (is_array($dependency)) {
80928
80929  foreach ($dependency as $d) {
80930 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
80931 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
80932 }
80933 }
80934 } elseif (is_object($dependency)) {
80935
80936  $this->checkUndefined($value, $dependency, $path, $i);
80937 }
80938 }
80939 }
80940 }
80941
80942 protected function validateUri($schema, $schemaUri = null)
80943 {
80944 $resolver = new UriResolver();
80945 $retriever = $this->factory->getUriRetriever();
80946
80947 $jsonSchema = null;
80948 if ($resolver->isValid($schemaUri)) {
80949 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
80950 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
80951 }
80952
80953 return $jsonSchema;
80954 }
80955 }
80956 <?php
80957
80958
80959
80960
80961
80962
80963
80964
80965 namespace JsonSchema\Entity;
80966
80967 use JsonSchema\Exception\InvalidArgumentException;
80968
80969
80970
80971
80972
80973
80974 class JsonPointer
80975 {
80976
80977 private $filename;
80978
80979
80980 private $propertyPaths = array();
80981
80982
80983
80984
80985 private $fromDefault = false;
80986
80987
80988
80989
80990
80991
80992 public function __construct($value)
80993 {
80994 if (!is_string($value)) {
80995 throw new InvalidArgumentException('Ref value must be a string');
80996 }
80997
80998 $splitRef = explode('#', $value, 2);
80999 $this->filename = $splitRef[0];
81000 if (array_key_exists(1, $splitRef)) {
81001 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
81002 }
81003 }
81004
81005
81006
81007
81008
81009
81010 private function decodePropertyPaths($propertyPathString)
81011 {
81012 $paths = array();
81013 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
81014 $path = $this->decodePath($path);
81015 if (is_string($path) && '' !== $path) {
81016 $paths[] = $path;
81017 }
81018 }
81019
81020 return $paths;
81021 }
81022
81023
81024
81025
81026 private function encodePropertyPaths()
81027 {
81028 return array_map(
81029 array($this, 'encodePath'),
81030 $this->getPropertyPaths()
81031 );
81032 }
81033
81034
81035
81036
81037
81038
81039 private function decodePath($path)
81040 {
81041 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
81042 }
81043
81044
81045
81046
81047
81048
81049 private function encodePath($path)
81050 {
81051 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
81052 }
81053
81054
81055
81056
81057 public function getFilename()
81058 {
81059 return $this->filename;
81060 }
81061
81062
81063
81064
81065 public function getPropertyPaths()
81066 {
81067 return $this->propertyPaths;
81068 }
81069
81070
81071
81072
81073
81074
81075 public function withPropertyPaths(array $propertyPaths)
81076 {
81077 $new = clone $this;
81078 $new->propertyPaths = $propertyPaths;
81079
81080 return $new;
81081 }
81082
81083
81084
81085
81086 public function getPropertyPathAsString()
81087 {
81088 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
81089 }
81090
81091
81092
81093
81094 public function __toString()
81095 {
81096 return $this->getFilename() . $this->getPropertyPathAsString();
81097 }
81098
81099
81100
81101
81102 public function setFromDefault()
81103 {
81104 $this->fromDefault = true;
81105 }
81106
81107
81108
81109
81110
81111
81112 public function fromDefault()
81113 {
81114 return $this->fromDefault;
81115 }
81116 }
81117 <?php
81118
81119 namespace JsonSchema\Exception;
81120
81121 interface ExceptionInterface
81122 {
81123 }
81124 <?php
81125
81126
81127
81128
81129
81130
81131
81132
81133 namespace JsonSchema\Exception;
81134
81135
81136
81137
81138 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
81139 {
81140 }
81141 <?php
81142
81143
81144
81145
81146
81147
81148
81149
81150 namespace JsonSchema\Exception;
81151
81152
81153
81154
81155 class InvalidConfigException extends RuntimeException
81156 {
81157 }
81158 <?php
81159
81160
81161
81162
81163
81164
81165
81166
81167 namespace JsonSchema\Exception;
81168
81169
81170
81171
81172 class InvalidSchemaException extends RuntimeException
81173 {
81174 }
81175 <?php
81176
81177
81178
81179
81180
81181
81182
81183
81184 namespace JsonSchema\Exception;
81185
81186
81187
81188
81189 class InvalidSchemaMediaTypeException extends RuntimeException
81190 {
81191 }
81192 <?php
81193
81194
81195
81196
81197
81198
81199
81200
81201 namespace JsonSchema\Exception;
81202
81203
81204
81205
81206 class InvalidSourceUriException extends InvalidArgumentException
81207 {
81208 }
81209 <?php
81210
81211
81212
81213
81214
81215
81216
81217
81218 namespace JsonSchema\Exception;
81219
81220
81221
81222
81223 class JsonDecodingException extends RuntimeException
81224 {
81225 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
81226 {
81227 switch ($code) {
81228 case JSON_ERROR_DEPTH:
81229 $message = 'The maximum stack depth has been exceeded';
81230 break;
81231 case JSON_ERROR_STATE_MISMATCH:
81232 $message = 'Invalid or malformed JSON';
81233 break;
81234 case JSON_ERROR_CTRL_CHAR:
81235 $message = 'Control character error, possibly incorrectly encoded';
81236 break;
81237 case JSON_ERROR_UTF8:
81238 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
81239 break;
81240 case JSON_ERROR_SYNTAX:
81241 $message = 'JSON syntax is malformed';
81242 break;
81243 default:
81244 $message = 'Syntax error';
81245 }
81246 parent::__construct($message, $code, $previous);
81247 }
81248 }
81249 <?php
81250
81251
81252
81253
81254
81255
81256
81257
81258 namespace JsonSchema\Exception;
81259
81260
81261
81262
81263 class ResourceNotFoundException extends RuntimeException
81264 {
81265 }
81266 <?php
81267
81268
81269
81270
81271
81272
81273
81274
81275 namespace JsonSchema\Exception;
81276
81277
81278
81279
81280 class RuntimeException extends \RuntimeException implements ExceptionInterface
81281 {
81282 }
81283 <?php
81284
81285
81286
81287
81288
81289
81290
81291
81292 namespace JsonSchema\Exception;
81293
81294
81295
81296
81297
81298
81299 class UnresolvableJsonPointerException extends InvalidArgumentException
81300 {
81301 }
81302 <?php
81303
81304
81305
81306
81307
81308
81309
81310
81311 namespace JsonSchema\Exception;
81312
81313
81314
81315
81316 class UriResolverException extends RuntimeException
81317 {
81318 }
81319 <?php
81320
81321
81322
81323
81324
81325
81326
81327
81328 namespace JsonSchema\Exception;
81329
81330 class ValidationException extends RuntimeException
81331 {
81332 }
81333 <?php
81334
81335
81336
81337
81338
81339
81340
81341
81342 namespace JsonSchema\Iterator;
81343
81344
81345
81346
81347
81348
81349 class ObjectIterator implements \Iterator, \Countable
81350 {
81351
81352 private $object;
81353
81354
81355 private $position = 0;
81356
81357
81358 private $data = array();
81359
81360
81361 private $initialized = false;
81362
81363
81364
81365
81366 public function __construct($object)
81367 {
81368 $this->object = $object;
81369 }
81370
81371
81372
81373
81374 public function current()
81375 {
81376 $this->initialize();
81377
81378 return $this->data[$this->position];
81379 }
81380
81381
81382
81383
81384 public function next()
81385 {
81386 $this->initialize();
81387 $this->position++;
81388 }
81389
81390
81391
81392
81393 public function key()
81394 {
81395 $this->initialize();
81396
81397 return $this->position;
81398 }
81399
81400
81401
81402
81403 public function valid()
81404 {
81405 $this->initialize();
81406
81407 return isset($this->data[$this->position]);
81408 }
81409
81410
81411
81412
81413 public function rewind()
81414 {
81415 $this->initialize();
81416 $this->position = 0;
81417 }
81418
81419
81420
81421
81422 public function count()
81423 {
81424 $this->initialize();
81425
81426 return count($this->data);
81427 }
81428
81429
81430
81431
81432 private function initialize()
81433 {
81434 if (!$this->initialized) {
81435 $this->data = $this->buildDataFromObject($this->object);
81436 $this->initialized = true;
81437 }
81438 }
81439
81440
81441
81442
81443
81444
81445 private function buildDataFromObject($object)
81446 {
81447 $result = array();
81448
81449 $stack = new \SplStack();
81450 $stack->push($object);
81451
81452 while (!$stack->isEmpty()) {
81453 $current = $stack->pop();
81454 if (is_object($current)) {
81455 array_push($result, $current);
81456 }
81457
81458 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
81459 if (is_object($propertyValue) || is_array($propertyValue)) {
81460 $stack->push($propertyValue);
81461 }
81462 }
81463 }
81464
81465 return $result;
81466 }
81467
81468
81469
81470
81471
81472
81473 private function getDataFromItem($item)
81474 {
81475 if (!is_object($item) && !is_array($item)) {
81476 return array();
81477 }
81478
81479 return is_object($item) ? get_object_vars($item) : $item;
81480 }
81481 }
81482 <?php
81483
81484 namespace JsonSchema;
81485
81486 class Rfc3339
81487 {
81488 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
81489
81490
81491
81492
81493
81494
81495
81496
81497 public static function createFromString($string)
81498 {
81499 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
81500 return null;
81501 }
81502
81503 $dateAndTime = $matches[1];
81504 $microseconds = $matches[2] ?: '.000000';
81505 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
81506 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
81507 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
81508
81509 return $dateTime ?: null;
81510 }
81511 }
81512 <?php
81513
81514 namespace JsonSchema;
81515
81516 use JsonSchema\Constraints\BaseConstraint;
81517 use JsonSchema\Entity\JsonPointer;
81518 use JsonSchema\Exception\UnresolvableJsonPointerException;
81519 use JsonSchema\Uri\UriResolver;
81520 use JsonSchema\Uri\UriRetriever;
81521
81522 class SchemaStorage implements SchemaStorageInterface
81523 {
81524 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
81525
81526 protected $uriRetriever;
81527 protected $uriResolver;
81528 protected $schemas = array();
81529
81530 public function __construct(
81531 UriRetrieverInterface $uriRetriever = null,
81532 UriResolverInterface $uriResolver = null
81533 ) {
81534 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
81535 $this->uriResolver = $uriResolver ?: new UriResolver();
81536 }
81537
81538
81539
81540
81541 public function getUriRetriever()
81542 {
81543 return $this->uriRetriever;
81544 }
81545
81546
81547
81548
81549 public function getUriResolver()
81550 {
81551 return $this->uriResolver;
81552 }
81553
81554
81555
81556
81557 public function addSchema($id, $schema = null)
81558 {
81559 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
81560
81561  
81562  
81563  $schema = $this->uriRetriever->retrieve($id);
81564 }
81565
81566
81567  if (is_array($schema)) {
81568 $schema = BaseConstraint::arrayToObjectRecursive($schema);
81569 }
81570
81571
81572  
81573  if (is_object($schema) && property_exists($schema, 'id')) {
81574 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
81575 $schema->properties->id->format = 'uri-reference';
81576 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
81577 $schema->properties->id->format = 'uri-reference';
81578 $schema->properties->{'$ref'}->format = 'uri-reference';
81579 }
81580 }
81581
81582
81583  $this->expandRefs($schema, $id);
81584
81585 $this->schemas[$id] = $schema;
81586 }
81587
81588
81589
81590
81591
81592
81593
81594 private function expandRefs(&$schema, $base = null)
81595 {
81596 if (!is_object($schema)) {
81597 if (is_array($schema)) {
81598 foreach ($schema as &$member) {
81599 $this->expandRefs($member, $base);
81600 }
81601 }
81602
81603 return;
81604 }
81605
81606 if (property_exists($schema, 'id') && is_string($schema->id) && $base != $schema->id) {
81607 $base = $this->uriResolver->resolve($schema->id, $base);
81608 }
81609
81610 if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
81611 $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $base));
81612 $schema->{'$ref'} = (string) $refPointer;
81613 }
81614
81615 foreach ($schema as &$member) {
81616 $this->expandRefs($member, $base);
81617 }
81618 }
81619
81620
81621
81622
81623 public function getSchema($id)
81624 {
81625 if (!array_key_exists($id, $this->schemas)) {
81626 $this->addSchema($id);
81627 }
81628
81629 return $this->schemas[$id];
81630 }
81631
81632
81633
81634
81635 public function resolveRef($ref)
81636 {
81637 $jsonPointer = new JsonPointer($ref);
81638
81639
81640  $fileName = $jsonPointer->getFilename();
81641 if (!strlen($fileName)) {
81642 throw new UnresolvableJsonPointerException(sprintf(
81643 "Could not resolve fragment '%s': no file is defined",
81644 $jsonPointer->getPropertyPathAsString()
81645 ));
81646 }
81647
81648
81649  $refSchema = $this->getSchema($fileName);
81650 foreach ($jsonPointer->getPropertyPaths() as $path) {
81651 if (is_object($refSchema) && property_exists($refSchema, $path)) {
81652 $refSchema = $this->resolveRefSchema($refSchema->{$path});
81653 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
81654 $refSchema = $this->resolveRefSchema($refSchema[$path]);
81655 } else {
81656 throw new UnresolvableJsonPointerException(sprintf(
81657 'File: %s is found, but could not resolve fragment: %s',
81658 $jsonPointer->getFilename(),
81659 $jsonPointer->getPropertyPathAsString()
81660 ));
81661 }
81662 }
81663
81664 return $refSchema;
81665 }
81666
81667
81668
81669
81670 public function resolveRefSchema($refSchema)
81671 {
81672 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
81673 $newSchema = $this->resolveRef($refSchema->{'$ref'});
81674 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
81675 unset($refSchema->{'$ref'});
81676 }
81677
81678 return $refSchema;
81679 }
81680 }
81681 <?php
81682
81683 namespace JsonSchema;
81684
81685 interface SchemaStorageInterface
81686 {
81687
81688
81689
81690
81691
81692
81693 public function addSchema($id, $schema = null);
81694
81695
81696
81697
81698
81699
81700
81701
81702 public function getSchema($id);
81703
81704
81705
81706
81707
81708
81709
81710
81711 public function resolveRef($ref);
81712
81713
81714
81715
81716
81717
81718
81719
81720 public function resolveRefSchema($refSchema);
81721 }
81722 <?php
81723
81724
81725
81726
81727
81728
81729 namespace JsonSchema\Uri\Retrievers;
81730
81731
81732
81733
81734
81735
81736
81737 abstract class AbstractRetriever implements UriRetrieverInterface
81738 {
81739
81740
81741
81742
81743
81744 protected $contentType;
81745
81746
81747
81748
81749
81750
81751 public function getContentType()
81752 {
81753 return $this->contentType;
81754 }
81755 }
81756 <?php
81757
81758
81759
81760
81761
81762
81763
81764
81765 namespace JsonSchema\Uri\Retrievers;
81766
81767 use JsonSchema\Exception\RuntimeException;
81768 use JsonSchema\Validator;
81769
81770
81771
81772
81773
81774
81775 class Curl extends AbstractRetriever
81776 {
81777 protected $messageBody;
81778
81779 public function __construct()
81780 {
81781 if (!function_exists('curl_init')) {
81782
81783  throw new RuntimeException('cURL not installed'); 
81784  }
81785 }
81786
81787
81788
81789
81790
81791
81792 public function retrieve($uri)
81793 {
81794 $ch = curl_init();
81795
81796 curl_setopt($ch, CURLOPT_URL, $uri);
81797 curl_setopt($ch, CURLOPT_HEADER, true);
81798 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
81799 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
81800
81801 $response = curl_exec($ch);
81802 if (false === $response) {
81803 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
81804 }
81805
81806 $this->fetchMessageBody($response);
81807 $this->fetchContentType($response);
81808
81809 curl_close($ch);
81810
81811 return $this->messageBody;
81812 }
81813
81814
81815
81816
81817 private function fetchMessageBody($response)
81818 {
81819 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
81820 $this->messageBody = $match[1];
81821 }
81822
81823
81824
81825
81826
81827
81828 protected function fetchContentType($response)
81829 {
81830 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
81831 $this->contentType = trim($match[1]);
81832
81833 return true;
81834 }
81835
81836 return false;
81837 }
81838 }
81839 <?php
81840
81841
81842
81843
81844
81845
81846
81847
81848 namespace JsonSchema\Uri\Retrievers;
81849
81850 use JsonSchema\Exception\ResourceNotFoundException;
81851
81852
81853
81854
81855
81856
81857 class FileGetContents extends AbstractRetriever
81858 {
81859 protected $messageBody;
81860
81861
81862
81863
81864
81865
81866 public function retrieve($uri)
81867 {
81868 $errorMessage = null;
81869 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
81870 $errorMessage = $errstr;
81871 });
81872 $response = file_get_contents($uri);
81873 restore_error_handler();
81874
81875 if ($errorMessage) {
81876 throw new ResourceNotFoundException($errorMessage);
81877 }
81878
81879 if (false === $response) {
81880 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
81881 }
81882
81883 if ($response == ''
81884 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
81885 ) {
81886 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
81887 }
81888
81889 $this->messageBody = $response;
81890 if (!empty($http_response_header)) {
81891
81892  
81893  $this->fetchContentType($http_response_header); 
81894  } else { 
81895  
81896  $this->contentType = null;
81897 }
81898
81899 return $this->messageBody;
81900 }
81901
81902
81903
81904
81905
81906
81907 private function fetchContentType(array $headers)
81908 {
81909 foreach ($headers as $header) {
81910 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
81911 return true;
81912 }
81913 }
81914
81915 return false;
81916 }
81917
81918
81919
81920
81921
81922
81923 protected static function getContentTypeMatchInHeader($header)
81924 {
81925 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
81926 return trim($match[1]);
81927 }
81928
81929 return null;
81930 }
81931 }
81932 <?php
81933
81934 namespace JsonSchema\Uri\Retrievers;
81935
81936 use JsonSchema\Validator;
81937
81938
81939
81940
81941
81942
81943
81944
81945
81946
81947
81948
81949
81950 class PredefinedArray extends AbstractRetriever
81951 {
81952
81953
81954
81955
81956
81957 private $schemas;
81958
81959
81960
81961
81962
81963
81964
81965 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
81966 {
81967 $this->schemas = $schemas;
81968 $this->contentType = $contentType;
81969 }
81970
81971
81972
81973
81974
81975
81976 public function retrieve($uri)
81977 {
81978 if (!array_key_exists($uri, $this->schemas)) {
81979 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
81980 'The JSON schema "%s" was not found.',
81981 $uri
81982 ));
81983 }
81984
81985 return $this->schemas[$uri];
81986 }
81987 }
81988 <?php
81989
81990
81991
81992
81993
81994
81995
81996
81997 namespace JsonSchema\Uri\Retrievers;
81998
81999
82000
82001
82002
82003
82004 interface UriRetrieverInterface
82005 {
82006
82007
82008
82009
82010
82011
82012
82013
82014
82015 public function retrieve($uri);
82016
82017
82018
82019
82020
82021
82022 public function getContentType();
82023 }
82024 <?php
82025
82026
82027
82028
82029
82030
82031
82032
82033 namespace JsonSchema\Uri;
82034
82035 use JsonSchema\Exception\UriResolverException;
82036 use JsonSchema\UriResolverInterface;
82037
82038
82039
82040
82041
82042
82043 class UriResolver implements UriResolverInterface
82044 {
82045
82046
82047
82048
82049
82050
82051
82052 public function parse($uri)
82053 {
82054 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
82055
82056 $components = array();
82057 if (5 < count($match)) {
82058 $components = array(
82059 'scheme' => $match[2],
82060 'authority' => $match[4],
82061 'path' => $match[5]
82062 );
82063 }
82064 if (7 < count($match)) {
82065 $components['query'] = $match[7];
82066 }
82067 if (9 < count($match)) {
82068 $components['fragment'] = $match[9];
82069 }
82070
82071 return $components;
82072 }
82073
82074
82075
82076
82077
82078
82079
82080
82081 public function generate(array $components)
82082 {
82083 $uri = $components['scheme'] . '://'
82084 . $components['authority']
82085 . $components['path'];
82086
82087 if (array_key_exists('query', $components) && strlen($components['query'])) {
82088 $uri .= '?' . $components['query'];
82089 }
82090 if (array_key_exists('fragment', $components)) {
82091 $uri .= '#' . $components['fragment'];
82092 }
82093
82094 return $uri;
82095 }
82096
82097
82098
82099
82100 public function resolve($uri, $baseUri = null)
82101 {
82102
82103  if (
82104 !is_null($baseUri) &&
82105 !filter_var($baseUri, \FILTER_VALIDATE_URL) &&
82106 !preg_match('|^[^/]+://|u', $baseUri)
82107 ) {
82108 if (is_file($baseUri)) {
82109 $baseUri = 'file://' . realpath($baseUri);
82110 } elseif (is_dir($baseUri)) {
82111 $baseUri = 'file://' . realpath($baseUri) . '/';
82112 } else {
82113 $baseUri = 'file://' . getcwd() . '/' . $baseUri;
82114 }
82115 }
82116
82117 if ($uri == '') {
82118 return $baseUri;
82119 }
82120
82121 $components = $this->parse($uri);
82122 $path = $components['path'];
82123
82124 if (!empty($components['scheme'])) {
82125 return $uri;
82126 }
82127 $baseComponents = $this->parse($baseUri);
82128 $basePath = $baseComponents['path'];
82129
82130 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
82131 if (isset($components['fragment'])) {
82132 $baseComponents['fragment'] = $components['fragment'];
82133 }
82134
82135 return $this->generate($baseComponents);
82136 }
82137
82138
82139
82140
82141
82142
82143
82144
82145
82146
82147
82148 public static function combineRelativePathWithBasePath($relativePath, $basePath)
82149 {
82150 $relativePath = self::normalizePath($relativePath);
82151 if ($relativePath == '') {
82152 return $basePath;
82153 }
82154 if ($relativePath[0] == '/') {
82155 return $relativePath;
82156 }
82157
82158 $basePathSegments = explode('/', $basePath);
82159
82160 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
82161 $numLevelUp = strlen($match[0]) /3 + 1;
82162 if ($numLevelUp >= count($basePathSegments)) {
82163 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
82164 }
82165
82166 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
82167 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
82168
82169 return implode('/', $basePathSegments) . '/' . $path;
82170 }
82171
82172
82173
82174
82175
82176
82177
82178
82179 private static function normalizePath($path)
82180 {
82181 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
82182 $path = preg_replace('|//|', '/', $path);
82183
82184 return $path;
82185 }
82186
82187
82188
82189
82190
82191
82192 public function isValid($uri)
82193 {
82194 $components = $this->parse($uri);
82195
82196 return !empty($components);
82197 }
82198 }
82199 <?php
82200
82201
82202
82203
82204
82205
82206
82207
82208 namespace JsonSchema\Uri;
82209
82210 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
82211 use JsonSchema\Exception\JsonDecodingException;
82212 use JsonSchema\Exception\ResourceNotFoundException;
82213 use JsonSchema\Uri\Retrievers\FileGetContents;
82214 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
82215 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
82216 use JsonSchema\Validator;
82217
82218
82219
82220
82221
82222
82223 class UriRetriever implements BaseUriRetrieverInterface
82224 {
82225
82226
82227
82228 protected $translationMap = array(
82229
82230  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
82231 );
82232
82233
82234
82235
82236 protected $allowedInvalidContentTypeEndpoints = array(
82237 'http://json-schema.org/',
82238 'https://json-schema.org/'
82239 );
82240
82241
82242
82243
82244 protected $uriRetriever = null;
82245
82246
82247
82248
82249
82250
82251 private $schemaCache = array();
82252
82253
82254
82255
82256
82257
82258 public function addInvalidContentTypeEndpoint($endpoint)
82259 {
82260 $this->allowedInvalidContentTypeEndpoints[] = $endpoint;
82261 }
82262
82263
82264
82265
82266
82267
82268
82269
82270
82271 public function confirmMediaType($uriRetriever, $uri)
82272 {
82273 $contentType = $uriRetriever->getContentType();
82274
82275 if (is_null($contentType)) {
82276
82277  return;
82278 }
82279
82280 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
82281 return;
82282 }
82283
82284 foreach ($this->allowedInvalidContentTypeEndpoints as $endpoint) {
82285 if (strpos($uri, $endpoint) === 0) {
82286 return true;
82287 }
82288 }
82289
82290 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
82291 }
82292
82293
82294
82295
82296
82297
82298
82299
82300
82301 public function getUriRetriever()
82302 {
82303 if (is_null($this->uriRetriever)) {
82304 $this->setUriRetriever(new FileGetContents());
82305 }
82306
82307 return $this->uriRetriever;
82308 }
82309
82310
82311
82312
82313
82314
82315
82316
82317
82318
82319
82320
82321
82322
82323
82324 public function resolvePointer($jsonSchema, $uri)
82325 {
82326 $resolver = new UriResolver();
82327 $parsed = $resolver->parse($uri);
82328 if (empty($parsed['fragment'])) {
82329 return $jsonSchema;
82330 }
82331
82332 $path = explode('/', $parsed['fragment']);
82333 while ($path) {
82334 $pathElement = array_shift($path);
82335 if (!empty($pathElement)) {
82336 $pathElement = str_replace('~1', '/', $pathElement);
82337 $pathElement = str_replace('~0', '~', $pathElement);
82338 if (!empty($jsonSchema->$pathElement)) {
82339 $jsonSchema = $jsonSchema->$pathElement;
82340 } else {
82341 throw new ResourceNotFoundException(
82342 'Fragment "' . $parsed['fragment'] . '" not found'
82343 . ' in ' . $uri
82344 );
82345 }
82346
82347 if (!is_object($jsonSchema)) {
82348 throw new ResourceNotFoundException(
82349 'Fragment part "' . $pathElement . '" is no object '
82350 . ' in ' . $uri
82351 );
82352 }
82353 }
82354 }
82355
82356 return $jsonSchema;
82357 }
82358
82359
82360
82361
82362 public function retrieve($uri, $baseUri = null, $translate = true)
82363 {
82364 $resolver = new UriResolver();
82365 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
82366
82367
82368  $arParts = $resolver->parse($resolvedUri);
82369 if (isset($arParts['fragment'])) {
82370 unset($arParts['fragment']);
82371 $fetchUri = $resolver->generate($arParts);
82372 }
82373
82374
82375  if ($translate) {
82376 $fetchUri = $this->translate($fetchUri);
82377 }
82378
82379 $jsonSchema = $this->loadSchema($fetchUri);
82380
82381
82382  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
82383
82384 if ($jsonSchema instanceof \stdClass) {
82385 $jsonSchema->id = $resolvedUri;
82386 }
82387
82388 return $jsonSchema;
82389 }
82390
82391
82392
82393
82394
82395
82396
82397
82398
82399 protected function loadSchema($fetchUri)
82400 {
82401 if (isset($this->schemaCache[$fetchUri])) {
82402 return $this->schemaCache[$fetchUri];
82403 }
82404
82405 $uriRetriever = $this->getUriRetriever();
82406 $contents = $this->uriRetriever->retrieve($fetchUri);
82407 $this->confirmMediaType($uriRetriever, $fetchUri);
82408 $jsonSchema = json_decode($contents);
82409
82410 if (JSON_ERROR_NONE < $error = json_last_error()) {
82411 throw new JsonDecodingException($error);
82412 }
82413
82414 $this->schemaCache[$fetchUri] = $jsonSchema;
82415
82416 return $jsonSchema;
82417 }
82418
82419
82420
82421
82422
82423
82424
82425
82426 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
82427 {
82428 $this->uriRetriever = $uriRetriever;
82429
82430 return $this;
82431 }
82432
82433
82434
82435
82436
82437
82438
82439
82440 public function parse($uri)
82441 {
82442 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
82443
82444 $components = array();
82445 if (5 < count($match)) {
82446 $components = array(
82447 'scheme' => $match[2],
82448 'authority' => $match[4],
82449 'path' => $match[5]
82450 );
82451 }
82452
82453 if (7 < count($match)) {
82454 $components['query'] = $match[7];
82455 }
82456
82457 if (9 < count($match)) {
82458 $components['fragment'] = $match[9];
82459 }
82460
82461 return $components;
82462 }
82463
82464
82465
82466
82467
82468
82469
82470
82471 public function generate(array $components)
82472 {
82473 $uri = $components['scheme'] . '://'
82474 . $components['authority']
82475 . $components['path'];
82476
82477 if (array_key_exists('query', $components)) {
82478 $uri .= $components['query'];
82479 }
82480
82481 if (array_key_exists('fragment', $components)) {
82482 $uri .= $components['fragment'];
82483 }
82484
82485 return $uri;
82486 }
82487
82488
82489
82490
82491
82492
82493
82494
82495
82496 public function resolve($uri, $baseUri = null)
82497 {
82498 $components = $this->parse($uri);
82499 $path = $components['path'];
82500
82501 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
82502 return $uri;
82503 }
82504
82505 $baseComponents = $this->parse($baseUri);
82506 $basePath = $baseComponents['path'];
82507
82508 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
82509
82510 return $this->generate($baseComponents);
82511 }
82512
82513
82514
82515
82516
82517
82518 public function isValid($uri)
82519 {
82520 $components = $this->parse($uri);
82521
82522 return !empty($components);
82523 }
82524
82525
82526
82527
82528 public function setTranslation($from, $to)
82529 {
82530 $this->translationMap[$from] = $to;
82531 }
82532
82533
82534
82535
82536 public function translate($uri)
82537 {
82538 foreach ($this->translationMap as $from => $to) {
82539 $uri = preg_replace($from, $to, $uri);
82540 }
82541
82542
82543  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
82544
82545 return $uri;
82546 }
82547 }
82548 <?php
82549
82550
82551
82552
82553
82554
82555
82556
82557 namespace JsonSchema;
82558
82559
82560
82561
82562 interface UriResolverInterface
82563 {
82564
82565
82566
82567
82568
82569
82570
82571
82572 public function resolve($uri, $baseUri = null);
82573 }
82574 <?php
82575
82576
82577
82578
82579
82580
82581
82582
82583 namespace JsonSchema;
82584
82585
82586
82587
82588 interface UriRetrieverInterface
82589 {
82590
82591
82592
82593
82594
82595
82596
82597
82598 public function retrieve($uri, $baseUri = null);
82599 }
82600 <?php
82601
82602
82603
82604
82605
82606
82607
82608
82609 namespace JsonSchema;
82610
82611 use JsonSchema\Constraints\BaseConstraint;
82612 use JsonSchema\Constraints\Constraint;
82613
82614
82615
82616
82617
82618
82619
82620
82621
82622 class Validator extends BaseConstraint
82623 {
82624 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
82625
82626 const ERROR_NONE = 0x00000000;
82627 const ERROR_ALL = 0xFFFFFFFF;
82628 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
82629 const ERROR_SCHEMA_VALIDATION = 0x00000002;
82630
82631
82632
82633
82634
82635
82636
82637
82638 public function validate(&$value, $schema = null, $checkMode = null)
82639 {
82640
82641  if (is_array($schema)) {
82642 $schema = self::arrayToObjectRecursive($schema);
82643 }
82644
82645
82646  $initialCheckMode = $this->factory->getConfig();
82647 if ($checkMode !== null) {
82648 $this->factory->setConfig($checkMode);
82649 }
82650
82651
82652  if (is_object($schema) && property_exists($schema, 'id')) {
82653 $schemaURI = $schema->id;
82654 } else {
82655 $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
82656 }
82657 $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
82658
82659 $validator = $this->factory->createInstanceFor('schema');
82660 $validator->check(
82661 $value,
82662 $this->factory->getSchemaStorage()->getSchema($schemaURI)
82663 );
82664
82665 $this->factory->setConfig($initialCheckMode);
82666
82667 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
82668
82669 return $validator->getErrorMask();
82670 }
82671
82672
82673
82674
82675 public function check($value, $schema)
82676 {
82677 return $this->validate($value, $schema);
82678 }
82679
82680
82681
82682
82683 public function coerce(&$value, $schema)
82684 {
82685 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
82686 }
82687 }
82688 Copyright (C) 2015 Composer
82689
82690 Permission is hereby granted, free of charge, to any person obtaining a copy of
82691 this software and associated documentation files (the "Software"), to deal in
82692 the Software without restriction, including without limitation the rights to
82693 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
82694 of the Software, and to permit persons to whom the Software is furnished to do
82695 so, subject to the following conditions:
82696
82697 The above copyright notice and this permission notice shall be included in all
82698 copies or substantial portions of the Software.
82699
82700 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82701 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82702 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
82703 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
82704 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82705 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
82706 SOFTWARE.
82707 <?php
82708
82709
82710
82711
82712
82713
82714
82715
82716
82717
82718 namespace Composer\Spdx;
82719
82720 class SpdxLicenses
82721 {
82722
82723 const LICENSES_FILE = 'spdx-licenses.json';
82724
82725
82726 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
82727
82728
82729
82730
82731
82732
82733
82734
82735
82736
82737
82738
82739
82740
82741 private $licenses;
82742
82743
82744
82745
82746 private $licensesExpression;
82747
82748
82749
82750
82751
82752
82753
82754
82755
82756
82757
82758
82759
82760
82761 private $exceptions;
82762
82763
82764
82765
82766 private $exceptionsExpression;
82767
82768 public function __construct()
82769 {
82770 $this->loadLicenses();
82771 $this->loadExceptions();
82772 }
82773
82774
82775
82776
82777
82778
82779
82780
82781
82782
82783
82784
82785
82786 public function getLicenseByIdentifier($identifier)
82787 {
82788 $key = strtolower($identifier);
82789
82790 if (!isset($this->licenses[$key])) {
82791 return;
82792 }
82793
82794 list($identifier, $name, $isOsiApproved, $isDeprecatedLicenseId) = $this->licenses[$key];
82795
82796 return array(
82797 $name,
82798 $isOsiApproved,
82799 'https://spdx.org/licenses/' . $identifier . '.html#licenseText',
82800 $isDeprecatedLicenseId,
82801 );
82802 }
82803
82804
82805
82806
82807
82808
82809 public function getLicenses()
82810 {
82811 return $this->licenses;
82812 }
82813
82814
82815
82816
82817
82818
82819
82820
82821
82822
82823
82824
82825
82826 public function getExceptionByIdentifier($identifier)
82827 {
82828 $key = strtolower($identifier);
82829
82830 if (!isset($this->exceptions[$key])) {
82831 return;
82832 }
82833
82834 list($identifier, $name) = $this->exceptions[$key];
82835
82836 return array(
82837 $name,
82838 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText',
82839 );
82840 }
82841
82842
82843
82844
82845
82846
82847
82848
82849 public function getIdentifierByName($name)
82850 {
82851 foreach ($this->licenses as $licenseData) {
82852 if ($licenseData[1] === $name) {
82853 return $licenseData[0];
82854 }
82855 }
82856
82857 foreach ($this->exceptions as $licenseData) {
82858 if ($licenseData[1] === $name) {
82859 return $licenseData[0];
82860 }
82861 }
82862 }
82863
82864
82865
82866
82867
82868
82869
82870
82871 public function isOsiApprovedByIdentifier($identifier)
82872 {
82873 return $this->licenses[strtolower($identifier)][2];
82874 }
82875
82876
82877
82878
82879
82880
82881
82882
82883 public function isDeprecatedByIdentifier($identifier)
82884 {
82885 return $this->licenses[strtolower($identifier)][3];
82886 }
82887
82888
82889
82890
82891
82892
82893
82894
82895 public function validate($license)
82896 {
82897 if (is_array($license)) {
82898 $count = count($license);
82899 if ($count !== count(array_filter($license, 'is_string'))) {
82900 throw new \InvalidArgumentException('Array of strings expected.');
82901 }
82902 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
82903 }
82904
82905 if (!is_string($license)) {
82906 throw new \InvalidArgumentException(sprintf(
82907 'Array or String expected, %s given.',
82908 gettype($license)
82909 ));
82910 }
82911
82912 return $this->isValidLicenseString($license);
82913 }
82914
82915
82916
82917
82918 public static function getResourcesDir()
82919 {
82920 return dirname(__DIR__) . '/res';
82921 }
82922
82923 private function loadLicenses()
82924 {
82925 if (null !== $this->licenses) {
82926 return;
82927 }
82928
82929 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
82930 $this->licenses = array();
82931
82932 foreach (json_decode($json, true) as $identifier => $license) {
82933 $this->licenses[strtolower($identifier)] = array($identifier, $license[0], $license[1], $license[2]);
82934 }
82935 }
82936
82937 private function loadExceptions()
82938 {
82939 if (null !== $this->exceptions) {
82940 return;
82941 }
82942
82943 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
82944 $this->exceptions = array();
82945
82946 foreach (json_decode($json, true) as $identifier => $exception) {
82947 $this->exceptions[strtolower($identifier)] = array($identifier, $exception[0]);
82948 }
82949 }
82950
82951
82952
82953
82954 private function getLicensesExpression()
82955 {
82956 if (null === $this->licensesExpression) {
82957 $licenses = array_map('preg_quote', array_keys($this->licenses));
82958 rsort($licenses);
82959 $licenses = implode('|', $licenses);
82960 $this->licensesExpression = $licenses;
82961 }
82962
82963 return $this->licensesExpression;
82964 }
82965
82966
82967
82968
82969 private function getExceptionsExpression()
82970 {
82971 if (null === $this->exceptionsExpression) {
82972 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
82973 rsort($exceptions);
82974 $exceptions = implode('|', $exceptions);
82975 $this->exceptionsExpression = $exceptions;
82976 }
82977
82978 return $this->exceptionsExpression;
82979 }
82980
82981
82982
82983
82984
82985
82986
82987
82988 private function isValidLicenseString($license)
82989 {
82990 if (isset($this->licenses[strtolower($license)])) {
82991 return true;
82992 }
82993
82994 $licenses = $this->getLicensesExpression();
82995 $exceptions = $this->getExceptionsExpression();
82996
82997 $regex = <<<REGEX
82998 {
82999 (?(DEFINE)
83000     # idstring: 1*( ALPHA / DIGIT / - / . )
83001     (?<idstring>[\pL\pN.-]{1,})
83002
83003     # license-id: taken from list
83004     (?<licenseid>${licenses})
83005
83006     # license-exception-id: taken from list
83007     (?<licenseexceptionid>${exceptions})
83008
83009     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
83010     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
83011
83012     # simple-expresssion: license-id / license-id+ / license-ref
83013     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
83014
83015     # compound-expression: 1*(
83016     #   simple-expression /
83017     #   simple-expression WITH license-exception-id /
83018     #   compound-expression AND compound-expression /
83019     #   compound-expression OR compound-expression
83020     # ) / ( compound-expression ) )
83021     (?<compound_head>
83022         (?&simple_expression) ( \s+ WITH \s+ (?&licenseexceptionid))?
83023             | \( \s* (?&compound_expression) \s* \)
83024     )
83025     (?<compound_expression>
83026         (?&compound_head) (?: \s+ (?:AND|OR) \s+ (?&compound_expression))?
83027     )
83028
83029     # license-expression: 1*1(simple-expression / compound-expression)
83030     (?<license_expression>(?&compound_expression) | (?&simple_expression))
83031 ) # end of define
83032
83033 ^(NONE | NOASSERTION | (?&license_expression))$
83034 }xi
83035 REGEX;
83036
83037 $match = preg_match($regex, $license);
83038
83039 if (0 === $match) {
83040 return false;
83041 }
83042
83043 if (false === $match) {
83044 throw new \RuntimeException('Regex failed to compile/run.');
83045 }
83046
83047 return true;
83048 }
83049 }
83050 Copyright (C) 2015 Composer
83051
83052 Permission is hereby granted, free of charge, to any person obtaining a copy of
83053 this software and associated documentation files (the "Software"), to deal in
83054 the Software without restriction, including without limitation the rights to
83055 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
83056 of the Software, and to permit persons to whom the Software is furnished to do
83057 so, subject to the following conditions:
83058
83059 The above copyright notice and this permission notice shall be included in all
83060 copies or substantial portions of the Software.
83061
83062 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
83063 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
83064 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
83065 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
83066 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
83067 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
83068 SOFTWARE.
83069 <?php
83070
83071
83072
83073
83074
83075
83076
83077
83078
83079
83080 namespace Composer\Semver;
83081
83082 use Composer\Semver\Constraint\Constraint;
83083
83084 class Comparator
83085 {
83086
83087
83088
83089
83090
83091
83092
83093
83094 public static function greaterThan($version1, $version2)
83095 {
83096 return self::compare($version1, '>', $version2);
83097 }
83098
83099
83100
83101
83102
83103
83104
83105
83106
83107 public static function greaterThanOrEqualTo($version1, $version2)
83108 {
83109 return self::compare($version1, '>=', $version2);
83110 }
83111
83112
83113
83114
83115
83116
83117
83118
83119
83120 public static function lessThan($version1, $version2)
83121 {
83122 return self::compare($version1, '<', $version2);
83123 }
83124
83125
83126
83127
83128
83129
83130
83131
83132
83133 public static function lessThanOrEqualTo($version1, $version2)
83134 {
83135 return self::compare($version1, '<=', $version2);
83136 }
83137
83138
83139
83140
83141
83142
83143
83144
83145
83146 public static function equalTo($version1, $version2)
83147 {
83148 return self::compare($version1, '==', $version2);
83149 }
83150
83151
83152
83153
83154
83155
83156
83157
83158
83159 public static function notEqualTo($version1, $version2)
83160 {
83161 return self::compare($version1, '!=', $version2);
83162 }
83163
83164
83165
83166
83167
83168
83169
83170
83171
83172
83173 public static function compare($version1, $operator, $version2)
83174 {
83175 $constraint = new Constraint($operator, $version2);
83176
83177 return $constraint->matches(new Constraint('==', $version1));
83178 }
83179 }
83180 <?php
83181
83182
83183
83184
83185
83186
83187
83188
83189
83190
83191 namespace Composer\Semver\Constraint;
83192
83193 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);
83194
83195
83196
83197
83198 abstract class AbstractConstraint implements ConstraintInterface
83199 {
83200
83201 protected $prettyString;
83202
83203
83204
83205
83206
83207
83208 public function matches(ConstraintInterface $provider)
83209 {
83210 if ($provider instanceof $this) {
83211
83212  return $this->matchSpecific($provider);
83213 }
83214
83215
83216  return $provider->matches($this);
83217 }
83218
83219
83220
83221
83222 public function setPrettyString($prettyString)
83223 {
83224 $this->prettyString = $prettyString;
83225 }
83226
83227
83228
83229
83230 public function getPrettyString()
83231 {
83232 if ($this->prettyString) {
83233 return $this->prettyString;
83234 }
83235
83236 return $this->__toString();
83237 }
83238
83239
83240  
83241  
83242 }
83243 <?php
83244
83245
83246
83247
83248
83249
83250
83251
83252
83253
83254 namespace Composer\Semver\Constraint;
83255
83256
83257
83258
83259 class Constraint implements ConstraintInterface
83260 {
83261
83262 const OP_EQ = 0;
83263 const OP_LT = 1;
83264 const OP_LE = 2;
83265 const OP_GT = 3;
83266 const OP_GE = 4;
83267 const OP_NE = 5;
83268
83269
83270
83271
83272
83273
83274 private static $transOpStr = array(
83275 '=' => self::OP_EQ,
83276 '==' => self::OP_EQ,
83277 '<' => self::OP_LT,
83278 '<=' => self::OP_LE,
83279 '>' => self::OP_GT,
83280 '>=' => self::OP_GE,
83281 '<>' => self::OP_NE,
83282 '!=' => self::OP_NE,
83283 );
83284
83285
83286
83287
83288
83289
83290 private static $transOpInt = array(
83291 self::OP_EQ => '==',
83292 self::OP_LT => '<',
83293 self::OP_LE => '<=',
83294 self::OP_GT => '>',
83295 self::OP_GE => '>=',
83296 self::OP_NE => '!=',
83297 );
83298
83299
83300 protected $operator;
83301
83302
83303 protected $version;
83304
83305
83306 protected $prettyString;
83307
83308
83309
83310
83311
83312
83313 public function matches(ConstraintInterface $provider)
83314 {
83315 if ($provider instanceof $this) {
83316 return $this->matchSpecific($provider);
83317 }
83318
83319
83320  return $provider->matches($this);
83321 }
83322
83323
83324
83325
83326 public function setPrettyString($prettyString)
83327 {
83328 $this->prettyString = $prettyString;
83329 }
83330
83331
83332
83333
83334 public function getPrettyString()
83335 {
83336 if ($this->prettyString) {
83337 return $this->prettyString;
83338 }
83339
83340 return $this->__toString();
83341 }
83342
83343
83344
83345
83346
83347
83348 public static function getSupportedOperators()
83349 {
83350 return array_keys(self::$transOpStr);
83351 }
83352
83353
83354
83355
83356
83357
83358
83359
83360
83361 public function __construct($operator, $version)
83362 {
83363 if (!isset(self::$transOpStr[$operator])) {
83364 throw new \InvalidArgumentException(sprintf(
83365 'Invalid operator "%s" given, expected one of: %s',
83366 $operator,
83367 implode(', ', self::getSupportedOperators())
83368 ));
83369 }
83370
83371 $this->operator = self::$transOpStr[$operator];
83372 $this->version = $version;
83373 }
83374
83375
83376
83377
83378
83379
83380
83381
83382
83383
83384
83385 public function versionCompare($a, $b, $operator, $compareBranches = false)
83386 {
83387 if (!isset(self::$transOpStr[$operator])) {
83388 throw new \InvalidArgumentException(sprintf(
83389 'Invalid operator "%s" given, expected one of: %s',
83390 $operator,
83391 implode(', ', self::getSupportedOperators())
83392 ));
83393 }
83394
83395 $aIsBranch = 'dev-' === substr($a, 0, 4);
83396 $bIsBranch = 'dev-' === substr($b, 0, 4);
83397
83398 if ($aIsBranch && $bIsBranch) {
83399 return $operator === '==' && $a === $b;
83400 }
83401
83402
83403  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
83404 return false;
83405 }
83406
83407 return version_compare($a, $b, $operator);
83408 }
83409
83410
83411
83412
83413
83414
83415
83416 public function matchSpecific(Constraint $provider, $compareBranches = false)
83417 {
83418 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
83419 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
83420
83421 $isEqualOp = self::OP_EQ === $this->operator;
83422 $isNonEqualOp = self::OP_NE === $this->operator;
83423 $isProviderEqualOp = self::OP_EQ === $provider->operator;
83424 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
83425
83426
83427  
83428  if ($isNonEqualOp || $isProviderNonEqualOp) {
83429 return !$isEqualOp && !$isProviderEqualOp
83430 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
83431 }
83432
83433
83434  
83435  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
83436 return true;
83437 }
83438
83439 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
83440
83441  
83442  if ($provider->version === $this->version
83443 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
83444 && self::$transOpInt[$this->operator] !== $noEqualOp) {
83445 return false;
83446 }
83447
83448 return true;
83449 }
83450
83451 return false;
83452 }
83453
83454
83455
83456
83457 public function __toString()
83458 {
83459 return self::$transOpInt[$this->operator] . ' ' . $this->version;
83460 }
83461 }
83462 <?php
83463
83464
83465
83466
83467
83468
83469
83470
83471
83472
83473 namespace Composer\Semver\Constraint;
83474
83475 interface ConstraintInterface
83476 {
83477
83478
83479
83480
83481
83482 public function matches(ConstraintInterface $provider);
83483
83484
83485
83486
83487 public function getPrettyString();
83488
83489
83490
83491
83492 public function __toString();
83493 }
83494 <?php
83495
83496
83497
83498
83499
83500
83501
83502
83503
83504
83505 namespace Composer\Semver\Constraint;
83506
83507
83508
83509
83510 class EmptyConstraint implements ConstraintInterface
83511 {
83512
83513 protected $prettyString;
83514
83515
83516
83517
83518
83519
83520 public function matches(ConstraintInterface $provider)
83521 {
83522 return true;
83523 }
83524
83525
83526
83527
83528 public function setPrettyString($prettyString)
83529 {
83530 $this->prettyString = $prettyString;
83531 }
83532
83533
83534
83535
83536 public function getPrettyString()
83537 {
83538 if ($this->prettyString) {
83539 return $this->prettyString;
83540 }
83541
83542 return $this->__toString();
83543 }
83544
83545
83546
83547
83548 public function __toString()
83549 {
83550 return '[]';
83551 }
83552 }
83553 <?php
83554
83555
83556
83557
83558
83559
83560
83561
83562
83563
83564 namespace Composer\Semver\Constraint;
83565
83566
83567
83568
83569 class MultiConstraint implements ConstraintInterface
83570 {
83571
83572 protected $constraints;
83573
83574
83575 protected $prettyString;
83576
83577
83578 protected $conjunctive;
83579
83580
83581
83582
83583
83584 public function __construct(array $constraints, $conjunctive = true)
83585 {
83586 $this->constraints = $constraints;
83587 $this->conjunctive = $conjunctive;
83588 }
83589
83590
83591
83592
83593 public function getConstraints()
83594 {
83595 return $this->constraints;
83596 }
83597
83598
83599
83600
83601 public function isConjunctive()
83602 {
83603 return $this->conjunctive;
83604 }
83605
83606
83607
83608
83609 public function isDisjunctive()
83610 {
83611 return !$this->conjunctive;
83612 }
83613
83614
83615
83616
83617
83618
83619 public function matches(ConstraintInterface $provider)
83620 {
83621 if (false === $this->conjunctive) {
83622 foreach ($this->constraints as $constraint) {
83623 if ($constraint->matches($provider)) {
83624 return true;
83625 }
83626 }
83627
83628 return false;
83629 }
83630
83631 foreach ($this->constraints as $constraint) {
83632 if (!$constraint->matches($provider)) {
83633 return false;
83634 }
83635 }
83636
83637 return true;
83638 }
83639
83640
83641
83642
83643 public function setPrettyString($prettyString)
83644 {
83645 $this->prettyString = $prettyString;
83646 }
83647
83648
83649
83650
83651 public function getPrettyString()
83652 {
83653 if ($this->prettyString) {
83654 return $this->prettyString;
83655 }
83656
83657 return $this->__toString();
83658 }
83659
83660
83661
83662
83663 public function __toString()
83664 {
83665 $constraints = array();
83666 foreach ($this->constraints as $constraint) {
83667 $constraints[] = (string) $constraint;
83668 }
83669
83670 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
83671 }
83672 }
83673 <?php
83674
83675
83676
83677
83678
83679
83680
83681
83682
83683
83684 namespace Composer\Semver;
83685
83686 use Composer\Semver\Constraint\Constraint;
83687
83688 class Semver
83689 {
83690 const SORT_ASC = 1;
83691 const SORT_DESC = -1;
83692
83693
83694 private static $versionParser;
83695
83696
83697
83698
83699
83700
83701
83702
83703
83704 public static function satisfies($version, $constraints)
83705 {
83706 if (null === self::$versionParser) {
83707 self::$versionParser = new VersionParser();
83708 }
83709
83710 $versionParser = self::$versionParser;
83711 $provider = new Constraint('==', $versionParser->normalize($version));
83712 $constraints = $versionParser->parseConstraints($constraints);
83713
83714 return $constraints->matches($provider);
83715 }
83716
83717
83718
83719
83720
83721
83722
83723
83724
83725 public static function satisfiedBy(array $versions, $constraints)
83726 {
83727 $versions = array_filter($versions, function ($version) use ($constraints) {
83728 return Semver::satisfies($version, $constraints);
83729 });
83730
83731 return array_values($versions);
83732 }
83733
83734
83735
83736
83737
83738
83739
83740
83741 public static function sort(array $versions)
83742 {
83743 return self::usort($versions, self::SORT_ASC);
83744 }
83745
83746
83747
83748
83749
83750
83751
83752
83753 public static function rsort(array $versions)
83754 {
83755 return self::usort($versions, self::SORT_DESC);
83756 }
83757
83758
83759
83760
83761
83762
83763
83764 private static function usort(array $versions, $direction)
83765 {
83766 if (null === self::$versionParser) {
83767 self::$versionParser = new VersionParser();
83768 }
83769
83770 $versionParser = self::$versionParser;
83771 $normalized = array();
83772
83773
83774  
83775  foreach ($versions as $key => $version) {
83776 $normalized[] = array($versionParser->normalize($version), $key);
83777 }
83778
83779 usort($normalized, function (array $left, array $right) use ($direction) {
83780 if ($left[0] === $right[0]) {
83781 return 0;
83782 }
83783
83784 if (Comparator::lessThan($left[0], $right[0])) {
83785 return -$direction;
83786 }
83787
83788 return $direction;
83789 });
83790
83791
83792  $sorted = array();
83793 foreach ($normalized as $item) {
83794 $sorted[] = $versions[$item[1]];
83795 }
83796
83797 return $sorted;
83798 }
83799 }
83800 <?php
83801
83802
83803
83804
83805
83806
83807
83808
83809
83810
83811 namespace Composer\Semver;
83812
83813 use Composer\Semver\Constraint\ConstraintInterface;
83814 use Composer\Semver\Constraint\EmptyConstraint;
83815 use Composer\Semver\Constraint\MultiConstraint;
83816 use Composer\Semver\Constraint\Constraint;
83817
83818
83819
83820
83821
83822
83823 class VersionParser
83824 {
83825
83826
83827
83828
83829
83830
83831
83832
83833
83834
83835
83836
83837
83838 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
83839
83840
83841 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
83842
83843
83844
83845
83846
83847
83848
83849
83850 public static function parseStability($version)
83851 {
83852 $version = preg_replace('{#.+$}i', '', $version);
83853
83854 if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
83855 return 'dev';
83856 }
83857
83858 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
83859 if (!empty($match[3])) {
83860 return 'dev';
83861 }
83862
83863 if (!empty($match[1])) {
83864 if ('beta' === $match[1] || 'b' === $match[1]) {
83865 return 'beta';
83866 }
83867 if ('alpha' === $match[1] || 'a' === $match[1]) {
83868 return 'alpha';
83869 }
83870 if ('rc' === $match[1]) {
83871 return 'RC';
83872 }
83873 }
83874
83875 return 'stable';
83876 }
83877
83878
83879
83880
83881
83882
83883 public static function normalizeStability($stability)
83884 {
83885 $stability = strtolower($stability);
83886
83887 return $stability === 'rc' ? 'RC' : $stability;
83888 }
83889
83890
83891
83892
83893
83894
83895
83896
83897
83898
83899
83900 public function normalize($version, $fullVersion = null)
83901 {
83902 $version = trim($version);
83903 if (null === $fullVersion) {
83904 $fullVersion = $version;
83905 }
83906
83907
83908  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
83909 $version = $match[1];
83910 }
83911
83912
83913  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
83914 return '9999999-dev';
83915 }
83916
83917
83918  if ('dev-' === strtolower(substr($version, 0, 4))) {
83919 return 'dev-' . substr($version, 4);
83920 }
83921
83922
83923  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
83924 $version = $match[1];
83925 }
83926
83927
83928  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
83929 $version = $matches[1]
83930 . (!empty($matches[2]) ? $matches[2] : '.0')
83931 . (!empty($matches[3]) ? $matches[3] : '.0')
83932 . (!empty($matches[4]) ? $matches[4] : '.0');
83933 $index = 5;
83934
83935  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
83936 $version = preg_replace('{\D}', '.', $matches[1]);
83937 $index = 2;
83938 }
83939
83940
83941  if (isset($index)) {
83942 if (!empty($matches[$index])) {
83943 if ('stable' === $matches[$index]) {
83944 return $version;
83945 }
83946 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
83947 }
83948
83949 if (!empty($matches[$index + 2])) {
83950 $version .= '-dev';
83951 }
83952
83953 return $version;
83954 }
83955
83956
83957  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
83958 try {
83959 return $this->normalizeBranch($match[1]);
83960 } catch (\Exception $e) {
83961 }
83962 }
83963
83964 $extraMessage = '';
83965 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
83966 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
83967 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
83968 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
83969 }
83970
83971 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
83972 }
83973
83974
83975
83976
83977
83978
83979
83980
83981 public function parseNumericAliasPrefix($branch)
83982 {
83983 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
83984 return $matches['version'] . '.';
83985 }
83986
83987 return false;
83988 }
83989
83990
83991
83992
83993
83994
83995
83996
83997 public function normalizeBranch($name)
83998 {
83999 $name = trim($name);
84000
84001 if (in_array($name, array('master', 'trunk', 'default'))) {
84002 return $this->normalize($name);
84003 }
84004
84005 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
84006 $version = '';
84007 for ($i = 1; $i < 5; ++$i) {
84008 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
84009 }
84010
84011 return str_replace('x', '9999999', $version) . '-dev';
84012 }
84013
84014 return 'dev-' . $name;
84015 }
84016
84017
84018
84019
84020
84021
84022
84023
84024 public function parseConstraints($constraints)
84025 {
84026 $prettyConstraint = $constraints;
84027
84028 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
84029 $constraints = empty($match[1]) ? '*' : $match[1];
84030 }
84031
84032 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
84033 $constraints = $match[1];
84034 }
84035
84036 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
84037 $orGroups = array();
84038 foreach ($orConstraints as $constraints) {
84039 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
84040 if (count($andConstraints) > 1) {
84041 $constraintObjects = array();
84042 foreach ($andConstraints as $constraint) {
84043 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
84044 $constraintObjects[] = $parsedConstraint;
84045 }
84046 }
84047 } else {
84048 $constraintObjects = $this->parseConstraint($andConstraints[0]);
84049 }
84050
84051 if (1 === count($constraintObjects)) {
84052 $constraint = $constraintObjects[0];
84053 } else {
84054 $constraint = new MultiConstraint($constraintObjects);
84055 }
84056
84057 $orGroups[] = $constraint;
84058 }
84059
84060 if (1 === count($orGroups)) {
84061 $constraint = $orGroups[0];
84062 } elseif (2 === count($orGroups)
84063
84064  
84065  && $orGroups[0] instanceof MultiConstraint
84066 && $orGroups[1] instanceof MultiConstraint
84067 && 2 === count($orGroups[0]->getConstraints())
84068 && 2 === count($orGroups[1]->getConstraints())
84069 && ($a = (string) $orGroups[0])
84070 && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
84071 && ($b = (string) $orGroups[1])
84072 && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
84073 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
84074 ) {
84075 $constraint = new MultiConstraint(array(
84076 new Constraint('>=', substr($a, 4, $posA - 5)),
84077 new Constraint('<', substr($b, $posB + 2, -1)),
84078 ));
84079 } else {
84080 $constraint = new MultiConstraint($orGroups, false);
84081 }
84082
84083 $constraint->setPrettyString($prettyConstraint);
84084
84085 return $constraint;
84086 }
84087
84088
84089
84090
84091
84092
84093
84094
84095 private function parseConstraint($constraint)
84096 {
84097 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
84098 $constraint = $match[1];
84099 if ($match[2] !== 'stable') {
84100 $stabilityModifier = $match[2];
84101 }
84102 }
84103
84104 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
84105 return array(new EmptyConstraint());
84106 }
84107
84108 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
84109
84110
84111  
84112  
84113  
84114  
84115  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
84116 if (substr($constraint, 0, 2) === '~>') {
84117 throw new \UnexpectedValueException(
84118 'Could not parse version constraint ' . $constraint . ': ' .
84119 'Invalid operator "~>", you probably meant to use the "~" operator'
84120 );
84121 }
84122
84123
84124  if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
84125 $position = 4;
84126 } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
84127 $position = 3;
84128 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
84129 $position = 2;
84130 } else {
84131 $position = 1;
84132 }
84133
84134
84135  $stabilitySuffix = '';
84136 if (empty($matches[5]) && empty($matches[7])) {
84137 $stabilitySuffix .= '-dev';
84138 }
84139
84140 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
84141 $lowerBound = new Constraint('>=', $lowVersion);
84142
84143
84144  
84145  $highPosition = max(1, $position - 1);
84146 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
84147 $upperBound = new Constraint('<', $highVersion);
84148
84149 return array(
84150 $lowerBound,
84151 $upperBound,
84152 );
84153 }
84154
84155
84156  
84157  
84158  
84159  
84160  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
84161
84162  if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
84163 $position = 1;
84164 } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
84165 $position = 2;
84166 } else {
84167 $position = 3;
84168 }
84169
84170
84171  $stabilitySuffix = '';
84172 if (empty($matches[5]) && empty($matches[7])) {
84173 $stabilitySuffix .= '-dev';
84174 }
84175
84176 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
84177 $lowerBound = new Constraint('>=', $lowVersion);
84178
84179
84180  
84181  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
84182 $upperBound = new Constraint('<', $highVersion);
84183
84184 return array(
84185 $lowerBound,
84186 $upperBound,
84187 );
84188 }
84189
84190
84191  
84192  
84193  
84194  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
84195 if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
84196 $position = 3;
84197 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
84198 $position = 2;
84199 } else {
84200 $position = 1;
84201 }
84202
84203 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
84204 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
84205
84206 if ($lowVersion === '0.0.0.0-dev') {
84207 return array(new Constraint('<', $highVersion));
84208 }
84209
84210 return array(
84211 new Constraint('>=', $lowVersion),
84212 new Constraint('<', $highVersion),
84213 );
84214 }
84215
84216
84217  
84218  
84219  
84220  
84221  
84222  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
84223
84224  $lowStabilitySuffix = '';
84225 if (empty($matches[6]) && empty($matches[8])) {
84226 $lowStabilitySuffix = '-dev';
84227 }
84228
84229 $lowVersion = $this->normalize($matches['from']);
84230 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
84231
84232 $empty = function ($x) {
84233 return ($x === 0 || $x === '0') ? false : empty($x);
84234 };
84235
84236 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
84237 $highVersion = $this->normalize($matches['to']);
84238 $upperBound = new Constraint('<=', $highVersion);
84239 } else {
84240 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
84241 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
84242 $upperBound = new Constraint('<', $highVersion);
84243 }
84244
84245 return array(
84246 $lowerBound,
84247 $upperBound,
84248 );
84249 }
84250
84251
84252  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
84253 try {
84254 $version = $this->normalize($matches[2]);
84255
84256 if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
84257 $version .= '-' . $stabilityModifier;
84258 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
84259 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
84260 if (substr($matches[2], 0, 4) !== 'dev-') {
84261 $version .= '-dev';
84262 }
84263 }
84264 }
84265
84266 return array(new Constraint($matches[1] ?: '=', $version));
84267 } catch (\Exception $e) {
84268 }
84269 }
84270
84271 $message = 'Could not parse version constraint ' . $constraint;
84272 if (isset($e)) {
84273 $message .= ': ' . $e->getMessage();
84274 }
84275
84276 throw new \UnexpectedValueException($message);
84277 }
84278
84279
84280
84281
84282
84283
84284
84285
84286
84287
84288
84289
84290
84291 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
84292 {
84293 for ($i = 4; $i > 0; --$i) {
84294 if ($i > $position) {
84295 $matches[$i] = $pad;
84296 } elseif ($i === $position && $increment) {
84297 $matches[$i] += $increment;
84298
84299  if ($matches[$i] < 0) {
84300 $matches[$i] = $pad;
84301 --$position;
84302
84303
84304  if ($i === 1) {
84305 return;
84306 }
84307 }
84308 }
84309 }
84310
84311 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
84312 }
84313
84314
84315
84316
84317
84318
84319
84320
84321 private function expandStability($stability)
84322 {
84323 $stability = strtolower($stability);
84324
84325 switch ($stability) {
84326 case 'a':
84327 return 'alpha';
84328 case 'b':
84329 return 'beta';
84330 case 'p':
84331 case 'pl':
84332 return 'patch';
84333 case 'rc':
84334 return 'RC';
84335 default:
84336 return $stability;
84337 }
84338 }
84339 }
84340 Copyright (C) 2016 Composer
84341
84342 Permission is hereby granted, free of charge, to any person obtaining a copy of
84343 this software and associated documentation files (the "Software"), to deal in
84344 the Software without restriction, including without limitation the rights to
84345 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
84346 of the Software, and to permit persons to whom the Software is furnished to do
84347 so, subject to the following conditions:
84348
84349 The above copyright notice and this permission notice shall be included in all
84350 copies or substantial portions of the Software.
84351
84352 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84353 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84354 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84355 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84356 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84357 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
84358 SOFTWARE.
84359 <?php
84360
84361
84362
84363
84364
84365
84366
84367
84368
84369
84370 namespace Composer\CaBundle;
84371
84372 use Psr\Log\LoggerInterface;
84373 use Symfony\Component\Process\PhpProcess;
84374
84375
84376
84377
84378
84379 class CaBundle
84380 {
84381 private static $caPath;
84382 private static $caFileValidity = array();
84383 private static $useOpensslParse;
84384
84385
84386
84387
84388
84389
84390
84391
84392
84393
84394
84395
84396
84397
84398
84399
84400
84401
84402
84403
84404
84405
84406
84407
84408
84409
84410
84411
84412
84413
84414
84415
84416
84417
84418
84419
84420
84421
84422 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
84423 {
84424 if (self::$caPath !== null) {
84425 return self::$caPath;
84426 }
84427 $caBundlePaths = array();
84428
84429
84430
84431  
84432  $caBundlePaths[] = getenv('SSL_CERT_FILE');
84433
84434
84435  
84436  $caBundlePaths[] = getenv('SSL_CERT_DIR');
84437
84438 $caBundlePaths[] = ini_get('openssl.cafile');
84439 $caBundlePaths[] = ini_get('openssl.capath');
84440
84441 $otherLocations = array(
84442 '/etc/pki/tls/certs/ca-bundle.crt', 
84443  '/etc/ssl/certs/ca-certificates.crt', 
84444  '/etc/ssl/ca-bundle.pem', 
84445  '/usr/local/share/certs/ca-root-nss.crt', 
84446  '/usr/ssl/certs/ca-bundle.crt', 
84447  '/opt/local/share/curl/curl-ca-bundle.crt', 
84448  '/usr/local/share/curl/curl-ca-bundle.crt', 
84449  '/usr/share/ssl/certs/ca-bundle.crt', 
84450  '/etc/ssl/cert.pem', 
84451  '/usr/local/etc/ssl/cert.pem', 
84452  '/usr/local/etc/openssl/cert.pem', 
84453  );
84454
84455 foreach($otherLocations as $location) {
84456 $otherLocations[] = dirname($location);
84457 }
84458
84459 $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
84460
84461 foreach ($caBundlePaths as $caBundle) {
84462 if (self::caFileUsable($caBundle, $logger)) {
84463 return self::$caPath = $caBundle;
84464 }
84465
84466 if (self::caDirUsable($caBundle)) {
84467 return self::$caPath = $caBundle;
84468 }
84469 }
84470
84471 return self::$caPath = static::getBundledCaBundlePath(); 
84472  }
84473
84474
84475
84476
84477
84478
84479
84480
84481 public static function getBundledCaBundlePath()
84482 {
84483 $caBundleFile = __DIR__.'/../res/cacert.pem';
84484
84485
84486  
84487  if (0 === strpos($caBundleFile, 'phar://')) {
84488 file_put_contents(
84489 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
84490 file_get_contents($caBundleFile)
84491 );
84492
84493 register_shutdown_function(function() use ($tempCaBundleFile) {
84494 @unlink($tempCaBundleFile);
84495 });
84496
84497 $caBundleFile = $tempCaBundleFile;
84498 }
84499
84500 return $caBundleFile;
84501 }
84502
84503
84504
84505
84506
84507
84508
84509
84510
84511 public static function validateCaFile($filename, LoggerInterface $logger = null)
84512 {
84513 static $warned = false;
84514
84515 if (isset(self::$caFileValidity[$filename])) {
84516 return self::$caFileValidity[$filename];
84517 }
84518
84519 $contents = file_get_contents($filename);
84520
84521
84522  
84523  if (!static::isOpensslParseSafe()) {
84524 if (!$warned && $logger) {
84525 $logger->warning(sprintf(
84526 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
84527 PHP_VERSION
84528 ));
84529 $warned = true;
84530 }
84531
84532 $isValid = !empty($contents);
84533 } else {
84534 $isValid = (bool) openssl_x509_parse($contents);
84535 }
84536
84537 if ($logger) {
84538 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
84539 }
84540
84541 return self::$caFileValidity[$filename] = $isValid;
84542 }
84543
84544
84545
84546
84547
84548
84549
84550
84551
84552 public static function isOpensslParseSafe()
84553 {
84554 if (null !== self::$useOpensslParse) {
84555 return self::$useOpensslParse;
84556 }
84557
84558 if (PHP_VERSION_ID >= 50600) {
84559 return self::$useOpensslParse = true;
84560 }
84561
84562
84563  
84564  
84565  
84566  if (
84567 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
84568 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
84569 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
84570 ) {
84571
84572  return self::$useOpensslParse = true;
84573 }
84574
84575 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
84576
84577  return self::$useOpensslParse = false;
84578 }
84579
84580 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
84581 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
84582
84583 if (preg_match($regex, PHP_VERSION, $m)) {
84584 return ((int) $m[1]) >= $fixedVersion;
84585 }
84586
84587 return false;
84588 };
84589
84590
84591  if (
84592 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
84593  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
84594  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
84595  ) {
84596 return self::$useOpensslParse = true;
84597 }
84598
84599
84600  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
84601 return self::$useOpensslParse = false;
84602 }
84603
84604
84605  
84606  
84607  
84608  
84609  
84610
84611
84612  
84613  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
84614 $script = <<<'EOT'
84615
84616 error_reporting(-1);
84617 $info = openssl_x509_parse(base64_decode('%s'));
84618 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
84619
84620 EOT;
84621 $script = '<'."?php\n".sprintf($script, $cert);
84622
84623 try {
84624 $process = new PhpProcess($script);
84625 $process->mustRun();
84626 } catch (\Exception $e) {
84627
84628  
84629  return self::$useOpensslParse = false;
84630 }
84631
84632 $output = preg_split('{\r?\n}', trim($process->getOutput()));
84633 $errorOutput = trim($process->getErrorOutput());
84634
84635 if (
84636 count($output) === 3
84637 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
84638 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
84639 && $output[2] === 'int(-1)'
84640 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
84641 ) {
84642
84643  return self::$useOpensslParse = true;
84644 }
84645
84646 return self::$useOpensslParse = false;
84647 }
84648
84649
84650
84651
84652 public static function reset()
84653 {
84654 self::$caFileValidity = array();
84655 self::$caPath = null;
84656 self::$useOpensslParse = null;
84657 }
84658
84659 private static function caFileUsable($certFile, LoggerInterface $logger = null)
84660 {
84661 return $certFile && @is_file($certFile) && @is_readable($certFile) && static::validateCaFile($certFile, $logger);
84662 }
84663
84664 private static function caDirUsable($certDir)
84665 {
84666 return $certDir && @is_dir($certDir) && @is_readable($certDir) && glob($certDir . '/*');
84667 }
84668 }
84669 MIT License
84670
84671 Copyright (c) 2017 Composer
84672
84673 Permission is hereby granted, free of charge, to any person obtaining a copy
84674 of this software and associated documentation files (the "Software"), to deal
84675 in the Software without restriction, including without limitation the rights
84676 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
84677 copies of the Software, and to permit persons to whom the Software is
84678 furnished to do so, subject to the following conditions:
84679
84680 The above copyright notice and this permission notice shall be included in all
84681 copies or substantial portions of the Software.
84682
84683 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84684 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84685 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84686 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84687 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84688 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
84689 SOFTWARE.
84690 <?php
84691
84692
84693
84694
84695
84696
84697
84698
84699
84700
84701 namespace Composer\XdebugHandler;
84702
84703
84704
84705
84706 class PhpConfig
84707 {
84708
84709
84710
84711
84712
84713 public function useOriginal()
84714 {
84715 $this->getDataAndReset();
84716 return array();
84717 }
84718
84719
84720
84721
84722
84723
84724 public function useStandard()
84725 {
84726 if ($data = $this->getDataAndReset()) {
84727 return array('-n', '-c', $data['tmpIni']);
84728 }
84729
84730 return array();
84731 }
84732
84733
84734
84735
84736
84737
84738 public function usePersistent()
84739 {
84740 if ($data = $this->getDataAndReset()) {
84741 Process::setEnv('PHPRC', $data['tmpIni']);
84742 Process::setEnv('PHP_INI_SCAN_DIR', '');
84743 }
84744
84745 return array();
84746 }
84747
84748
84749
84750
84751
84752
84753 private function getDataAndReset()
84754 {
84755 if ($data = XdebugHandler::getRestartSettings()) {
84756 Process::setEnv('PHPRC', $data['phprc']);
84757 Process::setEnv('PHP_INI_SCAN_DIR', $data['scanDir']);
84758 }
84759
84760 return $data;
84761 }
84762 }
84763 <?php
84764
84765
84766
84767
84768
84769
84770
84771
84772
84773
84774 namespace Composer\XdebugHandler;
84775
84776
84777
84778
84779
84780
84781
84782
84783 class Process
84784 {
84785
84786
84787
84788
84789
84790
84791
84792
84793
84794
84795 public static function addColorOption(array $args, $colorOption)
84796 {
84797 if (!$colorOption
84798 || in_array($colorOption, $args)
84799 || !preg_match('/^--([a-z]+$)|(^--[a-z]+=)/', $colorOption, $matches)) {
84800 return $args;
84801 }
84802
84803 if (isset($matches[2])) {
84804
84805  if (false !== ($index = array_search($matches[2].'auto', $args))) {
84806 $args[$index] = $colorOption;
84807 return $args;
84808 } elseif (preg_grep('/^'.$matches[2].'/', $args)) {
84809 return $args;
84810 }
84811 } elseif (in_array('--no-'.$matches[1], $args)) {
84812 return $args;
84813 }
84814
84815 if (false !== ($index = array_search('--', $args))) {
84816
84817  array_splice($args, $index, 0, $colorOption);
84818 } else {
84819 $args[] = $colorOption;
84820 }
84821
84822 return $args;
84823 }
84824
84825
84826
84827
84828
84829
84830
84831
84832
84833
84834
84835
84836
84837 public static function escape($arg, $meta = true, $module = false)
84838 {
84839 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
84840 return "'".str_replace("'", "'\\''", $arg)."'";
84841 }
84842
84843 $quote = strpbrk($arg, " \t") !== false || $arg === '';
84844
84845 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
84846
84847 if ($meta) {
84848 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
84849
84850 if (!$meta) {
84851 $quote = $quote || strpbrk($arg, '^&|<>()') !== false;
84852 } elseif ($module && !$dquotes && $quote) {
84853 $meta = false;
84854 }
84855 }
84856
84857 if ($quote) {
84858 $arg = '"'.preg_replace('/(\\\\*)$/', '$1$1', $arg).'"';
84859 }
84860
84861 if ($meta) {
84862 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
84863 }
84864
84865 return $arg;
84866 }
84867
84868
84869
84870
84871
84872
84873
84874
84875
84876
84877
84878 public static function supportsColor($output)
84879 {
84880 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
84881 return (function_exists('sapi_windows_vt100_support')
84882 && sapi_windows_vt100_support($output))
84883 || false !== getenv('ANSICON')
84884 || 'ON' === getenv('ConEmuANSI')
84885 || 'xterm' === getenv('TERM');
84886 }
84887
84888 if (function_exists('stream_isatty')) {
84889 return stream_isatty($output);
84890 } elseif (function_exists('posix_isatty')) {
84891 return posix_isatty($output);
84892 }
84893
84894 $stat = fstat($output);
84895
84896  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
84897 }
84898
84899
84900
84901
84902
84903
84904
84905
84906
84907 public static function setEnv($name, $value = false)
84908 {
84909 $unset = false === $value;
84910
84911 if (!putenv($unset ? $name : $name.'='.$value)) {
84912 return false;
84913 }
84914
84915 if ($unset) {
84916 unset($_SERVER[$name]);
84917 } else {
84918 $_SERVER[$name] = $value;
84919 }
84920
84921
84922  if (false !== stripos((string) ini_get('variables_order'), 'E')) {
84923 if ($unset) {
84924 unset($_ENV[$name]);
84925 } else {
84926 $_ENV[$name] = $value;
84927 }
84928 }
84929
84930 return true;
84931 }
84932 }
84933 <?php
84934
84935
84936
84937
84938
84939
84940
84941
84942
84943
84944 namespace Composer\XdebugHandler;
84945
84946 use Psr\Log\LoggerInterface;
84947 use Psr\Log\LogLevel;
84948
84949
84950
84951
84952
84953 class Status
84954 {
84955 const ENV_RESTART = 'XDEBUG_HANDLER_RESTART';
84956 const CHECK = 'Check';
84957 const ERROR = 'Error';
84958 const INFO = 'Info';
84959 const NORESTART = 'NoRestart';
84960 const RESTART = 'Restart';
84961 const RESTARTING = 'Restarting';
84962 const RESTARTED = 'Restarted';
84963
84964 private $debug;
84965 private $envAllowXdebug;
84966 private $loaded;
84967 private $logger;
84968 private $time;
84969
84970
84971
84972
84973
84974
84975
84976 public function __construct($envAllowXdebug, $debug)
84977 {
84978 $start = getenv(self::ENV_RESTART);
84979 Process::setEnv(self::ENV_RESTART);
84980 $this->time = $start ? round((microtime(true) - $start) * 1000) : 0;
84981
84982 $this->envAllowXdebug = $envAllowXdebug;
84983 $this->debug = $debug && defined('STDERR');
84984 }
84985
84986
84987
84988
84989 public function setLogger(LoggerInterface $logger)
84990 {
84991 $this->logger = $logger;
84992 }
84993
84994
84995
84996
84997
84998
84999
85000 public function report($op, $data)
85001 {
85002 if ($this->logger || $this->debug) {
85003 call_user_func(array($this, 'report'.$op), $data);
85004 }
85005 }
85006
85007
85008
85009
85010
85011
85012
85013 private function output($text, $level = null)
85014 {
85015 if ($this->logger) {
85016 $this->logger->log($level ?: LogLevel::DEBUG, $text);
85017 }
85018
85019 if ($this->debug) {
85020 fwrite(STDERR, sprintf('xdebug-handler[%d] %s', getmypid(), $text.PHP_EOL));
85021 }
85022 }
85023
85024 private function reportCheck($loaded)
85025 {
85026 $this->loaded = $loaded;
85027 $this->output('Checking '.$this->envAllowXdebug);
85028 }
85029
85030 private function reportError($error)
85031 {
85032 $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
85033 }
85034
85035 private function reportInfo($info)
85036 {
85037 $this->output($info);
85038 }
85039
85040 private function reportNoRestart()
85041 {
85042 $this->output($this->getLoadedMessage());
85043
85044 if ($this->loaded) {
85045 $text = sprintf('No restart (%s)', $this->getEnvAllow());
85046 if (!getenv($this->envAllowXdebug)) {
85047 $text .= ' Allowed by application';
85048 }
85049 $this->output($text);
85050 }
85051 }
85052
85053 private function reportRestart()
85054 {
85055 $this->output($this->getLoadedMessage());
85056 Process::setEnv(self::ENV_RESTART, (string) microtime(true));
85057 }
85058
85059 private function reportRestarted()
85060 {
85061 $loaded = $this->getLoadedMessage();
85062 $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded);
85063 $level = $this->loaded ? LogLevel::WARNING : null;
85064 $this->output($text, $level);
85065 }
85066
85067 private function reportRestarting($command)
85068 {
85069 $text = sprintf('Process restarting (%s)', $this->getEnvAllow());
85070 $this->output($text);
85071 $text = 'Running '.$command;
85072 $this->output($text);
85073 }
85074
85075
85076
85077
85078
85079
85080 private function getEnvAllow()
85081 {
85082 return $this->envAllowXdebug.'='.getenv($this->envAllowXdebug);
85083 }
85084
85085
85086
85087
85088
85089
85090 private function getLoadedMessage()
85091 {
85092 $loaded = $this->loaded ? sprintf('loaded (%s)', $this->loaded) : 'not loaded';
85093 return 'The xdebug extension is '.$loaded;
85094 }
85095 }
85096 <?php
85097
85098
85099
85100
85101
85102
85103
85104
85105
85106
85107 namespace Composer\XdebugHandler;
85108
85109 use Psr\Log\LoggerInterface;
85110
85111
85112
85113
85114 class XdebugHandler
85115 {
85116 const SUFFIX_ALLOW = '_ALLOW_XDEBUG';
85117 const SUFFIX_INIS = '_ORIGINAL_INIS';
85118 const RESTART_ID = 'internal';
85119 const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS';
85120 const DEBUG = 'XDEBUG_HANDLER_DEBUG';
85121
85122
85123 protected $tmpIni;
85124
85125 private static $inRestart;
85126 private static $name;
85127 private static $skipped;
85128
85129 private $cli;
85130 private $colorOption;
85131 private $debug;
85132 private $envAllowXdebug;
85133 private $envOriginalInis;
85134 private $loaded;
85135 private $persistent;
85136 private $script;
85137
85138 private $statusWriter;
85139
85140
85141
85142
85143
85144
85145
85146
85147
85148
85149
85150
85151 public function __construct($envPrefix, $colorOption = '')
85152 {
85153 if (!is_string($envPrefix) || empty($envPrefix) || !is_string($colorOption)) {
85154 throw new \RuntimeException('Invalid constructor parameter');
85155 }
85156
85157 self::$name = strtoupper($envPrefix);
85158 $this->envAllowXdebug = self::$name.self::SUFFIX_ALLOW;
85159 $this->envOriginalInis = self::$name.self::SUFFIX_INIS;
85160
85161 $this->colorOption = $colorOption;
85162
85163 if (extension_loaded('xdebug')) {
85164 $ext = new \ReflectionExtension('xdebug');
85165 $this->loaded = $ext->getVersion() ?: 'unknown';
85166 }
85167
85168 if ($this->cli = PHP_SAPI === 'cli') {
85169 $this->debug = getenv(self::DEBUG);
85170 }
85171
85172 $this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug);
85173 }
85174
85175
85176
85177
85178
85179
85180
85181
85182 public function setLogger(LoggerInterface $logger)
85183 {
85184 $this->statusWriter->setLogger($logger);
85185 return $this;
85186 }
85187
85188
85189
85190
85191
85192
85193
85194
85195 public function setMainScript($script)
85196 {
85197 $this->script = $script;
85198 return $this;
85199 }
85200
85201
85202
85203
85204
85205
85206 public function setPersistent()
85207 {
85208 $this->persistent = true;
85209 return $this;
85210 }
85211
85212
85213
85214
85215
85216
85217
85218
85219 public function check()
85220 {
85221 $this->notify(Status::CHECK, $this->loaded);
85222 $envArgs = explode('|', (string) getenv($this->envAllowXdebug));
85223
85224 if (empty($envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) {
85225
85226  $this->notify(Status::RESTART);
85227
85228 if ($this->prepareRestart()) {
85229 $command = $this->getCommand();
85230 $this->notify(Status::RESTARTING, $command);
85231 $this->restart($command);
85232 }
85233 return;
85234 }
85235
85236 if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
85237
85238  $this->notify(Status::RESTARTED);
85239
85240 Process::setEnv($this->envAllowXdebug);
85241 self::$inRestart = true;
85242
85243 if (!$this->loaded) {
85244
85245  self::$skipped = $envArgs[1];
85246 }
85247
85248
85249  $this->setEnvRestartSettings($envArgs);
85250 return;
85251 }
85252
85253 $this->notify(Status::NORESTART);
85254
85255 if ($settings = self::getRestartSettings()) {
85256
85257  $this->syncSettings($settings);
85258 }
85259 }
85260
85261
85262
85263
85264
85265
85266
85267
85268
85269 public static function getAllIniFiles()
85270 {
85271 if (!empty(self::$name)) {
85272 $env = getenv(self::$name.self::SUFFIX_INIS);
85273
85274 if (false !== $env) {
85275 return explode(PATH_SEPARATOR, $env);
85276 }
85277 }
85278
85279 $paths = array((string) php_ini_loaded_file());
85280
85281 if ($scanned = php_ini_scanned_files()) {
85282 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
85283 }
85284
85285 return $paths;
85286 }
85287
85288
85289
85290
85291
85292
85293
85294
85295
85296 public static function getRestartSettings()
85297 {
85298 $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS));
85299
85300 if (count($envArgs) !== 6
85301 || (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) {
85302 return;
85303 }
85304
85305 return array(
85306 'tmpIni' => $envArgs[0],
85307 'scannedInis' => (bool) $envArgs[1],
85308 'scanDir' => '*' === $envArgs[2] ? false : $envArgs[2],
85309 'phprc' => '*' === $envArgs[3] ? false : $envArgs[3],
85310 'inis' => explode(PATH_SEPARATOR, $envArgs[4]),
85311 'skipped' => $envArgs[5],
85312 );
85313 }
85314
85315
85316
85317
85318
85319
85320 public static function getSkippedVersion()
85321 {
85322 return (string) self::$skipped;
85323 }
85324
85325
85326
85327
85328
85329
85330
85331
85332 protected function requiresRestart($isLoaded)
85333 {
85334 return $isLoaded;
85335 }
85336
85337
85338
85339
85340
85341
85342 protected function restart($command)
85343 {
85344 $this->doRestart($command);
85345 }
85346
85347
85348
85349
85350
85351
85352 private function doRestart($command)
85353 {
85354 passthru($command, $exitCode);
85355 $this->notify(Status::INFO, 'Restarted process exited '.$exitCode);
85356
85357 if ($this->debug === '2') {
85358 $this->notify(Status::INFO, 'Temp ini saved: '.$this->tmpIni);
85359 } else {
85360 @unlink($this->tmpIni);
85361 }
85362
85363 exit($exitCode);
85364 }
85365
85366
85367
85368
85369
85370
85371
85372
85373
85374
85375
85376 private function prepareRestart()
85377 {
85378 $error = '';
85379 $iniFiles = self::getAllIniFiles();
85380 $scannedInis = count($iniFiles) > 1;
85381 $tmpDir = sys_get_temp_dir();
85382
85383 if (!$this->cli) {
85384 $error = 'Unsupported SAPI: '.PHP_SAPI;
85385 } elseif (!defined('PHP_BINARY')) {
85386 $error = 'PHP version is too old: '.PHP_VERSION;
85387 } elseif (!$this->checkConfiguration($info)) {
85388 $error = $info;
85389 } elseif (!$this->checkScanDirConfig()) {
85390 $error = 'PHP version does not report scanned inis: '.PHP_VERSION;
85391 } elseif (!$this->checkMainScript()) {
85392 $error = 'Unable to access main script: '.$this->script;
85393 } elseif (!$this->writeTmpIni($iniFiles, $tmpDir, $error)) {
85394 $error = $error ?: 'Unable to create temp ini file at: '.$tmpDir;
85395 } elseif (!$this->setEnvironment($scannedInis, $iniFiles)) {
85396 $error = 'Unable to set environment variables';
85397 }
85398
85399 if ($error) {
85400 $this->notify(Status::ERROR, $error);
85401 }
85402
85403 return empty($error);
85404 }
85405
85406
85407
85408
85409
85410
85411
85412
85413
85414
85415 private function writeTmpIni(array $iniFiles, $tmpDir, &$error)
85416 {
85417 if (!$this->tmpIni = @tempnam($tmpDir, '')) {
85418 return false;
85419 }
85420
85421
85422  if (empty($iniFiles[0])) {
85423 array_shift($iniFiles);
85424 }
85425
85426 $content = '';
85427 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
85428
85429 foreach ($iniFiles as $file) {
85430
85431  if (!$data = @file_get_contents($file)) {
85432 $error = 'Unable to read ini: '.$file;
85433 return false;
85434 }
85435 $content .= preg_replace($regex, ';$1', $data).PHP_EOL;
85436 }
85437
85438
85439  if ($config = parse_ini_string($content)) {
85440 $loaded = ini_get_all(null, false);
85441 $content .= $this->mergeLoadedConfig($loaded, $config);
85442 }
85443
85444
85445  $content .= 'opcache.enable_cli=0'.PHP_EOL;
85446
85447 return @file_put_contents($this->tmpIni, $content);
85448 }
85449
85450
85451
85452
85453
85454
85455 private function getCommand()
85456 {
85457 $php = array(PHP_BINARY);
85458 $args = array_slice($_SERVER['argv'], 1);
85459
85460 if (!$this->persistent) {
85461
85462  array_push($php, '-n', '-c', $this->tmpIni);
85463 }
85464
85465 if (defined('STDOUT') && Process::supportsColor(STDOUT)) {
85466 $args = Process::addColorOption($args, $this->colorOption);
85467 }
85468
85469 $args = array_merge($php, array($this->script), $args);
85470
85471 $cmd = Process::escape(array_shift($args), true, true);
85472 foreach ($args as $arg) {
85473 $cmd .= ' '.Process::escape($arg);
85474 }
85475
85476 return $cmd;
85477 }
85478
85479
85480
85481
85482
85483
85484
85485
85486
85487
85488
85489 private function setEnvironment($scannedInis, array $iniFiles)
85490 {
85491 $scanDir = getenv('PHP_INI_SCAN_DIR');
85492 $phprc = getenv('PHPRC');
85493
85494
85495  if (!putenv($this->envOriginalInis.'='.implode(PATH_SEPARATOR, $iniFiles))) {
85496 return false;
85497 }
85498
85499 if ($this->persistent) {
85500
85501  if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC='.$this->tmpIni)) {
85502 return false;
85503 }
85504 }
85505
85506
85507  $envArgs = array(
85508 self::RESTART_ID,
85509 $this->loaded,
85510 (int) $scannedInis,
85511 false === $scanDir ? '*' : $scanDir,
85512 false === $phprc ? '*' : $phprc,
85513 );
85514
85515 return putenv($this->envAllowXdebug.'='.implode('|', $envArgs));
85516 }
85517
85518
85519
85520
85521
85522
85523
85524 private function notify($op, $data = null)
85525 {
85526 $this->statusWriter->report($op, $data);
85527 }
85528
85529
85530
85531
85532
85533
85534
85535
85536
85537 private function mergeLoadedConfig(array $loadedConfig, array $iniConfig)
85538 {
85539 $content = '';
85540
85541 foreach ($loadedConfig as $name => $value) {
85542
85543  if (!is_string($value)
85544 || strpos($name, 'xdebug') === 0
85545 || $name === 'apc.mmap_file_mask') {
85546 continue;
85547 }
85548
85549 if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
85550
85551  $content .= $name.'="'.addcslashes($value, '\\"').'"'.PHP_EOL;
85552 }
85553 }
85554
85555 return $content;
85556 }
85557
85558
85559
85560
85561
85562
85563 private function checkMainScript()
85564 {
85565 if (null !== $this->script) {
85566
85567  return file_exists($this->script) || '--' === $this->script;
85568 }
85569
85570 if (file_exists($this->script = $_SERVER['argv'][0])) {
85571 return true;
85572 }
85573
85574
85575  $options = PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false;
85576 $trace = debug_backtrace($options);
85577
85578 if (($main = end($trace)) && isset($main['file'])) {
85579 return file_exists($this->script = $main['file']);
85580 }
85581
85582 return false;
85583 }
85584
85585
85586
85587
85588
85589
85590 private function setEnvRestartSettings($envArgs)
85591 {
85592 $settings = array(
85593 php_ini_loaded_file(),
85594 $envArgs[2],
85595 $envArgs[3],
85596 $envArgs[4],
85597 getenv($this->envOriginalInis),
85598 self::$skipped,
85599 );
85600
85601 Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings));
85602 }
85603
85604
85605
85606
85607
85608
85609 private function syncSettings(array $settings)
85610 {
85611 if (false === getenv($this->envOriginalInis)) {
85612
85613  Process::setEnv($this->envOriginalInis, implode(PATH_SEPARATOR, $settings['inis']));
85614 }
85615
85616 self::$skipped = $settings['skipped'];
85617 $this->notify(Status::INFO, 'Process called with existing restart settings');
85618 }
85619
85620
85621
85622
85623
85624
85625
85626
85627
85628 private function checkScanDirConfig()
85629 {
85630 return !(getenv('PHP_INI_SCAN_DIR')
85631 && !PHP_CONFIG_FILE_SCAN_DIR
85632 && (PHP_VERSION_ID < 70113
85633 || PHP_VERSION_ID === 70200));
85634 }
85635
85636
85637
85638
85639
85640
85641 private function checkConfiguration(&$info)
85642 {
85643 if (false !== strpos(ini_get('disable_functions'), 'passthru')) {
85644 $info = 'passthru function is disabled';
85645 return false;
85646 }
85647
85648 if (extension_loaded('uopz')) {
85649
85650  if (function_exists('uopz_allow_exit')) {
85651 @uopz_allow_exit(true);
85652 } else {
85653 $info = 'uopz extension is not compatible';
85654 return false;
85655 }
85656 }
85657
85658 return true;
85659 }
85660 }
85661 Copyright (c) 2012 PHP Framework Interoperability Group
85662
85663 Permission is hereby granted, free of charge, to any person obtaining a copy 
85664 of this software and associated documentation files (the "Software"), to deal
85665 in the Software without restriction, including without limitation the rights 
85666 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
85667 copies of the Software, and to permit persons to whom the Software is 
85668 furnished to do so, subject to the following conditions:
85669
85670 The above copyright notice and this permission notice shall be included in 
85671 all copies or substantial portions of the Software.
85672
85673 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
85674 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85675 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
85676 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
85677 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
85678 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
85679 THE SOFTWARE.
85680 <?php
85681
85682 namespace Psr\Log;
85683
85684
85685
85686
85687
85688
85689
85690
85691 abstract class AbstractLogger implements LoggerInterface
85692 {
85693
85694
85695
85696
85697
85698
85699
85700
85701 public function emergency($message, array $context = array())
85702 {
85703 $this->log(LogLevel::EMERGENCY, $message, $context);
85704 }
85705
85706
85707
85708
85709
85710
85711
85712
85713
85714
85715
85716
85717 public function alert($message, array $context = array())
85718 {
85719 $this->log(LogLevel::ALERT, $message, $context);
85720 }
85721
85722
85723
85724
85725
85726
85727
85728
85729
85730
85731
85732 public function critical($message, array $context = array())
85733 {
85734 $this->log(LogLevel::CRITICAL, $message, $context);
85735 }
85736
85737
85738
85739
85740
85741
85742
85743
85744
85745
85746 public function error($message, array $context = array())
85747 {
85748 $this->log(LogLevel::ERROR, $message, $context);
85749 }
85750
85751
85752
85753
85754
85755
85756
85757
85758
85759
85760
85761
85762 public function warning($message, array $context = array())
85763 {
85764 $this->log(LogLevel::WARNING, $message, $context);
85765 }
85766
85767
85768
85769
85770
85771
85772
85773
85774
85775 public function notice($message, array $context = array())
85776 {
85777 $this->log(LogLevel::NOTICE, $message, $context);
85778 }
85779
85780
85781
85782
85783
85784
85785
85786
85787
85788
85789
85790 public function info($message, array $context = array())
85791 {
85792 $this->log(LogLevel::INFO, $message, $context);
85793 }
85794
85795
85796
85797
85798
85799
85800
85801
85802
85803 public function debug($message, array $context = array())
85804 {
85805 $this->log(LogLevel::DEBUG, $message, $context);
85806 }
85807 }
85808 <?php
85809
85810 namespace Psr\Log;
85811
85812 class InvalidArgumentException extends \InvalidArgumentException
85813 {
85814 }
85815 <?php
85816
85817 namespace Psr\Log;
85818
85819
85820
85821
85822 class LogLevel
85823 {
85824 const EMERGENCY = 'emergency';
85825 const ALERT = 'alert';
85826 const CRITICAL = 'critical';
85827 const ERROR = 'error';
85828 const WARNING = 'warning';
85829 const NOTICE = 'notice';
85830 const INFO = 'info';
85831 const DEBUG = 'debug';
85832 }
85833 <?php
85834
85835 namespace Psr\Log;
85836
85837
85838
85839
85840 interface LoggerAwareInterface
85841 {
85842
85843
85844
85845
85846
85847
85848
85849 public function setLogger(LoggerInterface $logger);
85850 }
85851 <?php
85852
85853 namespace Psr\Log;
85854
85855
85856
85857
85858 trait LoggerAwareTrait
85859 {
85860
85861
85862
85863
85864
85865 protected $logger;
85866
85867
85868
85869
85870
85871
85872 public function setLogger(LoggerInterface $logger)
85873 {
85874 $this->logger = $logger;
85875 }
85876 }
85877 <?php
85878
85879 namespace Psr\Log;
85880
85881
85882
85883
85884
85885
85886
85887
85888
85889
85890
85891
85892
85893
85894
85895
85896 interface LoggerInterface
85897 {
85898
85899
85900
85901
85902
85903
85904
85905
85906 public function emergency($message, array $context = array());
85907
85908
85909
85910
85911
85912
85913
85914
85915
85916
85917
85918
85919 public function alert($message, array $context = array());
85920
85921
85922
85923
85924
85925
85926
85927
85928
85929
85930
85931 public function critical($message, array $context = array());
85932
85933
85934
85935
85936
85937
85938
85939
85940
85941
85942 public function error($message, array $context = array());
85943
85944
85945
85946
85947
85948
85949
85950
85951
85952
85953
85954
85955 public function warning($message, array $context = array());
85956
85957
85958
85959
85960
85961
85962
85963
85964
85965 public function notice($message, array $context = array());
85966
85967
85968
85969
85970
85971
85972
85973
85974
85975
85976
85977 public function info($message, array $context = array());
85978
85979
85980
85981
85982
85983
85984
85985
85986
85987 public function debug($message, array $context = array());
85988
85989
85990
85991
85992
85993
85994
85995
85996
85997
85998
85999
86000 public function log($level, $message, array $context = array());
86001 }
86002 <?php
86003
86004 namespace Psr\Log;
86005
86006
86007
86008
86009
86010
86011
86012
86013
86014 trait LoggerTrait
86015 {
86016
86017
86018
86019
86020
86021
86022
86023
86024 public function emergency($message, array $context = array())
86025 {
86026 $this->log(LogLevel::EMERGENCY, $message, $context);
86027 }
86028
86029
86030
86031
86032
86033
86034
86035
86036
86037
86038
86039
86040 public function alert($message, array $context = array())
86041 {
86042 $this->log(LogLevel::ALERT, $message, $context);
86043 }
86044
86045
86046
86047
86048
86049
86050
86051
86052
86053
86054
86055 public function critical($message, array $context = array())
86056 {
86057 $this->log(LogLevel::CRITICAL, $message, $context);
86058 }
86059
86060
86061
86062
86063
86064
86065
86066
86067
86068
86069 public function error($message, array $context = array())
86070 {
86071 $this->log(LogLevel::ERROR, $message, $context);
86072 }
86073
86074
86075
86076
86077
86078
86079
86080
86081
86082
86083
86084
86085 public function warning($message, array $context = array())
86086 {
86087 $this->log(LogLevel::WARNING, $message, $context);
86088 }
86089
86090
86091
86092
86093
86094
86095
86096
86097
86098 public function notice($message, array $context = array())
86099 {
86100 $this->log(LogLevel::NOTICE, $message, $context);
86101 }
86102
86103
86104
86105
86106
86107
86108
86109
86110
86111
86112
86113 public function info($message, array $context = array())
86114 {
86115 $this->log(LogLevel::INFO, $message, $context);
86116 }
86117
86118
86119
86120
86121
86122
86123
86124
86125
86126 public function debug($message, array $context = array())
86127 {
86128 $this->log(LogLevel::DEBUG, $message, $context);
86129 }
86130
86131
86132
86133
86134
86135
86136
86137
86138
86139
86140
86141
86142 abstract public function log($level, $message, array $context = array());
86143 }
86144 <?php
86145
86146 namespace Psr\Log;
86147
86148
86149
86150
86151
86152
86153
86154
86155
86156 class NullLogger extends AbstractLogger
86157 {
86158
86159
86160
86161
86162
86163
86164
86165
86166
86167
86168
86169 public function log($level, $message, array $context = array())
86170 {
86171
86172  }
86173 }
86174 <?php
86175
86176 namespace Psr\Log\Test;
86177
86178 use Psr\Log\LoggerInterface;
86179 use Psr\Log\LogLevel;
86180 use PHPUnit\Framework\TestCase;
86181
86182
86183
86184
86185
86186
86187
86188 abstract class LoggerInterfaceTest extends TestCase
86189 {
86190
86191
86192
86193 abstract public function getLogger();
86194
86195
86196
86197
86198
86199
86200
86201
86202
86203
86204 abstract public function getLogs();
86205
86206 public function testImplements()
86207 {
86208 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
86209 }
86210
86211
86212
86213
86214 public function testLogsAtAllLevels($level, $message)
86215 {
86216 $logger = $this->getLogger();
86217 $logger->{$level}($message, array('user' => 'Bob'));
86218 $logger->log($level, $message, array('user' => 'Bob'));
86219
86220 $expected = array(
86221 $level.' message of level '.$level.' with context: Bob',
86222 $level.' message of level '.$level.' with context: Bob',
86223 );
86224 $this->assertEquals($expected, $this->getLogs());
86225 }
86226
86227 public function provideLevelsAndMessages()
86228 {
86229 return array(
86230 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
86231 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
86232 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
86233 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
86234 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
86235 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
86236 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
86237 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
86238 );
86239 }
86240
86241
86242
86243
86244 public function testThrowsOnInvalidLevel()
86245 {
86246 $logger = $this->getLogger();
86247 $logger->log('invalid level', 'Foo');
86248 }
86249
86250 public function testContextReplacement()
86251 {
86252 $logger = $this->getLogger();
86253 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
86254
86255 $expected = array('info {Message {nothing} Bob Bar a}');
86256 $this->assertEquals($expected, $this->getLogs());
86257 }
86258
86259 public function testObjectCastToString()
86260 {
86261 if (method_exists($this, 'createPartialMock')) {
86262 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
86263 } else {
86264 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
86265 }
86266 $dummy->expects($this->once())
86267 ->method('__toString')
86268 ->will($this->returnValue('DUMMY'));
86269
86270 $this->getLogger()->warning($dummy);
86271
86272 $expected = array('warning DUMMY');
86273 $this->assertEquals($expected, $this->getLogs());
86274 }
86275
86276 public function testContextCanContainAnything()
86277 {
86278 $closed = fopen('php://memory', 'r');
86279 fclose($closed);
86280
86281 $context = array(
86282 'bool' => true,
86283 'null' => null,
86284 'string' => 'Foo',
86285 'int' => 0,
86286 'float' => 0.5,
86287 'nested' => array('with object' => new DummyTest),
86288 'object' => new \DateTime,
86289 'resource' => fopen('php://memory', 'r'),
86290 'closed' => $closed,
86291 );
86292
86293 $this->getLogger()->warning('Crazy context data', $context);
86294
86295 $expected = array('warning Crazy context data');
86296 $this->assertEquals($expected, $this->getLogs());
86297 }
86298
86299 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
86300 {
86301 $logger = $this->getLogger();
86302 $logger->warning('Random message', array('exception' => 'oops'));
86303 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
86304
86305 $expected = array(
86306 'warning Random message',
86307 'critical Uncaught Exception!'
86308 );
86309 $this->assertEquals($expected, $this->getLogs());
86310 }
86311 }
86312
86313 class DummyTest
86314 {
86315 public function __toString()
86316 {
86317 return 'DummyTest';
86318 }
86319 }
86320 <?php
86321
86322 namespace Psr\Log\Test;
86323
86324 use Psr\Log\AbstractLogger;
86325
86326
86327
86328
86329
86330
86331
86332
86333
86334
86335
86336
86337
86338
86339
86340
86341
86342
86343
86344
86345
86346
86347
86348
86349
86350
86351
86352
86353
86354
86355
86356
86357
86358
86359
86360
86361
86362
86363
86364
86365
86366
86367
86368
86369
86370
86371
86372
86373
86374
86375
86376 class TestLogger extends AbstractLogger
86377 {
86378
86379
86380
86381 public $records = [];
86382
86383 public $recordsByLevel = [];
86384
86385
86386
86387
86388 public function log($level, $message, array $context = [])
86389 {
86390 $record = [
86391 'level' => $level,
86392 'message' => $message,
86393 'context' => $context,
86394 ];
86395
86396 $this->recordsByLevel[$record['level']][] = $record;
86397 $this->records[] = $record;
86398 }
86399
86400 public function hasRecords($level)
86401 {
86402 return isset($this->recordsByLevel[$level]);
86403 }
86404
86405 public function hasRecord($record, $level)
86406 {
86407 if (is_string($record)) {
86408 $record = ['message' => $record];
86409 }
86410 return $this->hasRecordThatPasses(function ($rec) use ($record) {
86411 if ($rec['message'] !== $record['message']) {
86412 return false;
86413 }
86414 if (isset($record['context']) && $rec['context'] !== $record['context']) {
86415 return false;
86416 }
86417 return true;
86418 }, $level);
86419 }
86420
86421 public function hasRecordThatContains($message, $level)
86422 {
86423 return $this->hasRecordThatPasses(function ($rec) use ($message) {
86424 return strpos($rec['message'], $message) !== false;
86425 }, $level);
86426 }
86427
86428 public function hasRecordThatMatches($regex, $level)
86429 {
86430 return $this->hasRecordThatPasses(function ($rec) use ($regex) {
86431 return preg_match($regex, $rec['message']) > 0;
86432 }, $level);
86433 }
86434
86435 public function hasRecordThatPasses(callable $predicate, $level)
86436 {
86437 if (!isset($this->recordsByLevel[$level])) {
86438 return false;
86439 }
86440 foreach ($this->recordsByLevel[$level] as $i => $rec) {
86441 if (call_user_func($predicate, $rec, $i)) {
86442 return true;
86443 }
86444 }
86445 return false;
86446 }
86447
86448 public function __call($method, $args)
86449 {
86450 if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
86451 $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
86452 $level = strtolower($matches[2]);
86453 if (method_exists($this, $genericMethod)) {
86454 $args[] = $level;
86455 return call_user_func_array([$this, $genericMethod], $args);
86456 }
86457 }
86458 throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
86459 }
86460
86461 public function reset()
86462 {
86463 $this->records = [];
86464 $this->recordsByLevel = [];
86465 }
86466 }
86467 <?php
86468
86469
86470
86471 require_once __DIR__ . '/composer/autoload_real.php';
86472
86473 return ComposerAutoloaderInitComposerPhar1572625217::getLoader();
86474 <?php
86475
86476
86477
86478 $vendorDir = dirname(dirname(__FILE__));
86479 $baseDir = dirname($vendorDir);
86480
86481 return array(
86482 );
86483 <?php
86484
86485
86486
86487 $vendorDir = dirname(dirname(__FILE__));
86488 $baseDir = dirname($vendorDir);
86489
86490 return array(
86491 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
86492 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
86493 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
86494 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
86495 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
86496 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
86497 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
86498 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
86499 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
86500 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
86501 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
86502 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
86503 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
86504 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
86505 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
86506 'Composer\\' => array($baseDir . '/src/Composer'),
86507 );
86508 <?php
86509
86510
86511
86512 $vendorDir = dirname(dirname(__FILE__));
86513 $baseDir = dirname($vendorDir);
86514
86515 return array(
86516 );
86517 <?php
86518
86519
86520
86521 $vendorDir = dirname(dirname(__FILE__));
86522 $baseDir = dirname($vendorDir);
86523
86524 return array(
86525 '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
86526 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
86527 );
86528 <?php
86529
86530
86531
86532 class ComposerAutoloaderInitComposerPhar1572625217
86533 {
86534 private static $loader;
86535
86536 public static function loadClassLoader($class)
86537 {
86538 if ('Composer\Autoload\ClassLoader' === $class) {
86539 require __DIR__ . '/ClassLoader.php';
86540 }
86541 }
86542
86543 public static function getLoader()
86544 {
86545 if (null !== self::$loader) {
86546 return self::$loader;
86547 }
86548
86549 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1572625217', 'loadClassLoader'), true, true);
86550 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
86551 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1572625217', 'loadClassLoader'));
86552
86553 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
86554 if ($useStaticLoader) {
86555 require_once __DIR__ . '/autoload_static.php';
86556
86557 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1572625217::getInitializer($loader));
86558 } else {
86559 $map = require __DIR__ . '/autoload_namespaces.php';
86560 foreach ($map as $namespace => $path) {
86561 $loader->set($namespace, $path);
86562 }
86563
86564 $map = require __DIR__ . '/autoload_psr4.php';
86565 foreach ($map as $namespace => $path) {
86566 $loader->setPsr4($namespace, $path);
86567 }
86568
86569 $classMap = require __DIR__ . '/autoload_classmap.php';
86570 if ($classMap) {
86571 $loader->addClassMap($classMap);
86572 }
86573 }
86574
86575 $loader->register(true);
86576
86577 if ($useStaticLoader) {
86578 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1572625217::$files;
86579 } else {
86580 $includeFiles = require __DIR__ . '/autoload_files.php';
86581 }
86582 foreach ($includeFiles as $fileIdentifier => $file) {
86583 composerRequireComposerPhar1572625217($fileIdentifier, $file);
86584 }
86585
86586 return $loader;
86587 }
86588 }
86589
86590 function composerRequireComposerPhar1572625217($fileIdentifier, $file)
86591 {
86592 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
86593 require $file;
86594
86595 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
86596 }
86597 }
86598 <?php
86599
86600
86601
86602 namespace Composer\Autoload;
86603
86604 class ComposerStaticInitComposerPhar1572625217
86605 {
86606 public static $files = array (
86607 '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
86608 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
86609 );
86610
86611 public static $prefixLengthsPsr4 = array (
86612 'S' => 
86613 array (
86614 'Symfony\\Polyfill\\Mbstring\\' => 26,
86615 'Symfony\\Polyfill\\Ctype\\' => 23,
86616 'Symfony\\Component\\Process\\' => 26,
86617 'Symfony\\Component\\Finder\\' => 25,
86618 'Symfony\\Component\\Filesystem\\' => 29,
86619 'Symfony\\Component\\Debug\\' => 24,
86620 'Symfony\\Component\\Console\\' => 26,
86621 'Seld\\PharUtils\\' => 15,
86622 'Seld\\JsonLint\\' => 14,
86623 ),
86624 'P' => 
86625 array (
86626 'Psr\\Log\\' => 8,
86627 ),
86628 'J' => 
86629 array (
86630 'JsonSchema\\' => 11,
86631 ),
86632 'C' => 
86633 array (
86634 'Composer\\XdebugHandler\\' => 23,
86635 'Composer\\Spdx\\' => 14,
86636 'Composer\\Semver\\' => 16,
86637 'Composer\\CaBundle\\' => 18,
86638 'Composer\\' => 9,
86639 ),
86640 );
86641
86642 public static $prefixDirsPsr4 = array (
86643 'Symfony\\Polyfill\\Mbstring\\' => 
86644 array (
86645 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
86646 ),
86647 'Symfony\\Polyfill\\Ctype\\' => 
86648 array (
86649 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
86650 ),
86651 'Symfony\\Component\\Process\\' => 
86652 array (
86653 0 => __DIR__ . '/..' . '/symfony/process',
86654 ),
86655 'Symfony\\Component\\Finder\\' => 
86656 array (
86657 0 => __DIR__ . '/..' . '/symfony/finder',
86658 ),
86659 'Symfony\\Component\\Filesystem\\' => 
86660 array (
86661 0 => __DIR__ . '/..' . '/symfony/filesystem',
86662 ),
86663 'Symfony\\Component\\Debug\\' => 
86664 array (
86665 0 => __DIR__ . '/..' . '/symfony/debug',
86666 ),
86667 'Symfony\\Component\\Console\\' => 
86668 array (
86669 0 => __DIR__ . '/..' . '/symfony/console',
86670 ),
86671 'Seld\\PharUtils\\' => 
86672 array (
86673 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
86674 ),
86675 'Seld\\JsonLint\\' => 
86676 array (
86677 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
86678 ),
86679 'Psr\\Log\\' => 
86680 array (
86681 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
86682 ),
86683 'JsonSchema\\' => 
86684 array (
86685 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
86686 ),
86687 'Composer\\XdebugHandler\\' => 
86688 array (
86689 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
86690 ),
86691 'Composer\\Spdx\\' => 
86692 array (
86693 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
86694 ),
86695 'Composer\\Semver\\' => 
86696 array (
86697 0 => __DIR__ . '/..' . '/composer/semver/src',
86698 ),
86699 'Composer\\CaBundle\\' => 
86700 array (
86701 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
86702 ),
86703 'Composer\\' => 
86704 array (
86705 0 => __DIR__ . '/../..' . '/src/Composer',
86706 ),
86707 );
86708
86709 public static function getInitializer(ClassLoader $loader)
86710 {
86711 return \Closure::bind(function () use ($loader) {
86712 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1572625217::$prefixLengthsPsr4;
86713 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1572625217::$prefixDirsPsr4;
86714
86715 }, null, ClassLoader::class);
86716 }
86717 }
86718 <?php
86719
86720
86721
86722
86723
86724
86725
86726
86727
86728
86729
86730 namespace Composer\Autoload;
86731
86732
86733
86734
86735
86736
86737
86738
86739
86740
86741
86742
86743
86744
86745
86746
86747
86748
86749
86750
86751
86752
86753
86754
86755
86756
86757
86758
86759
86760 class ClassLoader
86761 {
86762
86763  private $prefixLengthsPsr4 = array();
86764 private $prefixDirsPsr4 = array();
86765 private $fallbackDirsPsr4 = array();
86766
86767
86768  private $prefixesPsr0 = array();
86769 private $fallbackDirsPsr0 = array();
86770
86771 private $useIncludePath = false;
86772 private $classMap = array();
86773 private $classMapAuthoritative = false;
86774 private $missingClasses = array();
86775 private $apcuPrefix;
86776
86777 public function getPrefixes()
86778 {
86779 if (!empty($this->prefixesPsr0)) {
86780 return call_user_func_array('array_merge', $this->prefixesPsr0);
86781 }
86782
86783 return array();
86784 }
86785
86786 public function getPrefixesPsr4()
86787 {
86788 return $this->prefixDirsPsr4;
86789 }
86790
86791 public function getFallbackDirs()
86792 {
86793 return $this->fallbackDirsPsr0;
86794 }
86795
86796 public function getFallbackDirsPsr4()
86797 {
86798 return $this->fallbackDirsPsr4;
86799 }
86800
86801 public function getClassMap()
86802 {
86803 return $this->classMap;
86804 }
86805
86806
86807
86808
86809 public function addClassMap(array $classMap)
86810 {
86811 if ($this->classMap) {
86812 $this->classMap = array_merge($this->classMap, $classMap);
86813 } else {
86814 $this->classMap = $classMap;
86815 }
86816 }
86817
86818
86819
86820
86821
86822
86823
86824
86825
86826 public function add($prefix, $paths, $prepend = false)
86827 {
86828 if (!$prefix) {
86829 if ($prepend) {
86830 $this->fallbackDirsPsr0 = array_merge(
86831 (array) $paths,
86832 $this->fallbackDirsPsr0
86833 );
86834 } else {
86835 $this->fallbackDirsPsr0 = array_merge(
86836 $this->fallbackDirsPsr0,
86837 (array) $paths
86838 );
86839 }
86840
86841 return;
86842 }
86843
86844 $first = $prefix[0];
86845 if (!isset($this->prefixesPsr0[$first][$prefix])) {
86846 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
86847
86848 return;
86849 }
86850 if ($prepend) {
86851 $this->prefixesPsr0[$first][$prefix] = array_merge(
86852 (array) $paths,
86853 $this->prefixesPsr0[$first][$prefix]
86854 );
86855 } else {
86856 $this->prefixesPsr0[$first][$prefix] = array_merge(
86857 $this->prefixesPsr0[$first][$prefix],
86858 (array) $paths
86859 );
86860 }
86861 }
86862
86863
86864
86865
86866
86867
86868
86869
86870
86871
86872
86873 public function addPsr4($prefix, $paths, $prepend = false)
86874 {
86875 if (!$prefix) {
86876
86877  if ($prepend) {
86878 $this->fallbackDirsPsr4 = array_merge(
86879 (array) $paths,
86880 $this->fallbackDirsPsr4
86881 );
86882 } else {
86883 $this->fallbackDirsPsr4 = array_merge(
86884 $this->fallbackDirsPsr4,
86885 (array) $paths
86886 );
86887 }
86888 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
86889
86890  $length = strlen($prefix);
86891 if ('\\' !== $prefix[$length - 1]) {
86892 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
86893 }
86894 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
86895 $this->prefixDirsPsr4[$prefix] = (array) $paths;
86896 } elseif ($prepend) {
86897
86898  $this->prefixDirsPsr4[$prefix] = array_merge(
86899 (array) $paths,
86900 $this->prefixDirsPsr4[$prefix]
86901 );
86902 } else {
86903
86904  $this->prefixDirsPsr4[$prefix] = array_merge(
86905 $this->prefixDirsPsr4[$prefix],
86906 (array) $paths
86907 );
86908 }
86909 }
86910
86911
86912
86913
86914
86915
86916
86917
86918 public function set($prefix, $paths)
86919 {
86920 if (!$prefix) {
86921 $this->fallbackDirsPsr0 = (array) $paths;
86922 } else {
86923 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
86924 }
86925 }
86926
86927
86928
86929
86930
86931
86932
86933
86934
86935
86936 public function setPsr4($prefix, $paths)
86937 {
86938 if (!$prefix) {
86939 $this->fallbackDirsPsr4 = (array) $paths;
86940 } else {
86941 $length = strlen($prefix);
86942 if ('\\' !== $prefix[$length - 1]) {
86943 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
86944 }
86945 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
86946 $this->prefixDirsPsr4[$prefix] = (array) $paths;
86947 }
86948 }
86949
86950
86951
86952
86953
86954
86955 public function setUseIncludePath($useIncludePath)
86956 {
86957 $this->useIncludePath = $useIncludePath;
86958 }
86959
86960
86961
86962
86963
86964
86965
86966 public function getUseIncludePath()
86967 {
86968 return $this->useIncludePath;
86969 }
86970
86971
86972
86973
86974
86975
86976
86977 public function setClassMapAuthoritative($classMapAuthoritative)
86978 {
86979 $this->classMapAuthoritative = $classMapAuthoritative;
86980 }
86981
86982
86983
86984
86985
86986
86987 public function isClassMapAuthoritative()
86988 {
86989 return $this->classMapAuthoritative;
86990 }
86991
86992
86993
86994
86995
86996
86997 public function setApcuPrefix($apcuPrefix)
86998 {
86999 $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
87000 }
87001
87002
87003
87004
87005
87006
87007 public function getApcuPrefix()
87008 {
87009 return $this->apcuPrefix;
87010 }
87011
87012
87013
87014
87015
87016
87017 public function register($prepend = false)
87018 {
87019 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
87020 }
87021
87022
87023
87024
87025 public function unregister()
87026 {
87027 spl_autoload_unregister(array($this, 'loadClass'));
87028 }
87029
87030
87031
87032
87033
87034
87035
87036 public function loadClass($class)
87037 {
87038 if ($file = $this->findFile($class)) {
87039 includeFile($file);
87040
87041 return true;
87042 }
87043 }
87044
87045
87046
87047
87048
87049
87050
87051
87052 public function findFile($class)
87053 {
87054
87055  if (isset($this->classMap[$class])) {
87056 return $this->classMap[$class];
87057 }
87058 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
87059 return false;
87060 }
87061 if (null !== $this->apcuPrefix) {
87062 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
87063 if ($hit) {
87064 return $file;
87065 }
87066 }
87067
87068 $file = $this->findFileWithExtension($class, '.php');
87069
87070
87071  if (false === $file && defined('HHVM_VERSION')) {
87072 $file = $this->findFileWithExtension($class, '.hh');
87073 }
87074
87075 if (null !== $this->apcuPrefix) {
87076 apcu_add($this->apcuPrefix.$class, $file);
87077 }
87078
87079 if (false === $file) {
87080
87081  $this->missingClasses[$class] = true;
87082 }
87083
87084 return $file;
87085 }
87086
87087 private function findFileWithExtension($class, $ext)
87088 {
87089
87090  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
87091
87092 $first = $class[0];
87093 if (isset($this->prefixLengthsPsr4[$first])) {
87094 $subPath = $class;
87095 while (false !== $lastPos = strrpos($subPath, '\\')) {
87096 $subPath = substr($subPath, 0, $lastPos);
87097 $search = $subPath . '\\';
87098 if (isset($this->prefixDirsPsr4[$search])) {
87099 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
87100 foreach ($this->prefixDirsPsr4[$search] as $dir) {
87101 if (file_exists($file = $dir . $pathEnd)) {
87102 return $file;
87103 }
87104 }
87105 }
87106 }
87107 }
87108
87109
87110  foreach ($this->fallbackDirsPsr4 as $dir) {
87111 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
87112 return $file;
87113 }
87114 }
87115
87116
87117  if (false !== $pos = strrpos($class, '\\')) {
87118
87119  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
87120 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
87121 } else {
87122
87123  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
87124 }
87125
87126 if (isset($this->prefixesPsr0[$first])) {
87127 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
87128 if (0 === strpos($class, $prefix)) {
87129 foreach ($dirs as $dir) {
87130 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
87131 return $file;
87132 }
87133 }
87134 }
87135 }
87136 }
87137
87138
87139  foreach ($this->fallbackDirsPsr0 as $dir) {
87140 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
87141 return $file;
87142 }
87143 }
87144
87145
87146  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
87147 return $file;
87148 }
87149
87150 return false;
87151 }
87152 }
87153
87154
87155
87156
87157
87158
87159 function includeFile($file)
87160 {
87161 include $file;
87162 }
87163 ##
87164 ## Bundle of CA Root Certificates
87165 ##
87166 ## Certificate data from Mozilla as of: Wed Aug 28 03:12:10 2019 GMT
87167 ##
87168 ## This is a bundle of X.509 certificates of public Certificate Authorities
87169 ## (CA). These were automatically extracted from Mozilla's root certificates
87170 ## file (certdata.txt).  This file can be found in the mozilla source tree:
87171 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
87172 ##
87173 ## It contains the certificates in PEM format and therefore
87174 ## can be directly used with curl / libcurl / php_curl, or with
87175 ## an Apache+mod_ssl webserver for SSL client authentication.
87176 ## Just configure this file as the SSLCACertificateFile.
87177 ##
87178 ## Conversion done with mk-ca-bundle.pl version 1.27.
87179 ## SHA256: fffa309937c3be940649293f749b8207fabc6eb224e50e4bb3f2c5e44e0d6a6b
87180 ##
87181
87182
87183 GlobalSign Root CA
87184 ==================
87185 -----BEGIN CERTIFICATE-----
87186 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
87187 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
87188 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
87189 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
87190 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
87191 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
87192 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
87193 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
87194 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
87195 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
87196 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
87197 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
87198 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
87199 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
87200 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
87201 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
87202 -----END CERTIFICATE-----
87203
87204 GlobalSign Root CA - R2
87205 =======================
87206 -----BEGIN CERTIFICATE-----
87207 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
87208 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
87209 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
87210 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
87211 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
87212 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
87213 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
87214 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
87215 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
87216 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
87217 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
87218 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
87219 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
87220 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
87221 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
87222 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
87223 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
87224 -----END CERTIFICATE-----
87225
87226 Verisign Class 3 Public Primary Certification Authority - G3
87227 ============================================================
87228 -----BEGIN CERTIFICATE-----
87229 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
87230 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
87231 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
87232 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
87233 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
87234 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
87235 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
87236 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
87237 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
87238 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
87239 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
87240 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
87241 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
87242 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
87243 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
87244 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
87245 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
87246 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
87247 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
87248 -----END CERTIFICATE-----
87249
87250 Entrust.net Premium 2048 Secure Server CA
87251 =========================================
87252 -----BEGIN CERTIFICATE-----
87253 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
87254 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
87255 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
87256 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
87257 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
87258 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
87259 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
87260 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
87261 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
87262 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
87263 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
87264 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
87265 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
87266 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
87267 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
87268 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
87269 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
87270 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
87271 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
87272 -----END CERTIFICATE-----
87273
87274 Baltimore CyberTrust Root
87275 =========================
87276 -----BEGIN CERTIFICATE-----
87277 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
87278 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
87279 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
87280 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
87281 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
87282 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
87283 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
87284 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
87285 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
87286 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
87287 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
87288 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
87289 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
87290 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
87291 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
87292 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
87293 -----END CERTIFICATE-----
87294
87295 AddTrust External Root
87296 ======================
87297 -----BEGIN CERTIFICATE-----
87298 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
87299 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
87300 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
87301 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
87302 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
87303 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
87304 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
87305 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
87306 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
87307 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
87308 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
87309 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
87310 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
87311 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
87312 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
87313 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
87314 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
87315 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
87316 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
87317 -----END CERTIFICATE-----
87318
87319 Entrust Root Certification Authority
87320 ====================================
87321 -----BEGIN CERTIFICATE-----
87322 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
87323 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
87324 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
87325 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
87326 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
87327 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
87328 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
87329 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
87330 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
87331 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
87332 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
87333 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
87334 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
87335 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
87336 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
87337 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
87338 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
87339 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
87340 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
87341 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
87342 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
87343 -----END CERTIFICATE-----
87344
87345 GeoTrust Global CA
87346 ==================
87347 -----BEGIN CERTIFICATE-----
87348 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
87349 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
87350 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
87351 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
87352 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
87353 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
87354 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
87355 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
87356 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
87357 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
87358 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
87359 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
87360 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
87361 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
87362 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
87363 Mw==
87364 -----END CERTIFICATE-----
87365
87366 GeoTrust Universal CA
87367 =====================
87368 -----BEGIN CERTIFICATE-----
87369 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
87370 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
87371 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
87372 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
87373 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
87374 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
87375 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
87376 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
87377 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
87378 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
87379 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
87380 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
87381 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
87382 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
87383 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
87384 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
87385 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
87386 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
87387 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
87388 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
87389 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
87390 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
87391 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
87392 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
87393 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
87394 -----END CERTIFICATE-----
87395
87396 GeoTrust Universal CA 2
87397 =======================
87398 -----BEGIN CERTIFICATE-----
87399 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
87400 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
87401 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
87402 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
87403 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
87404 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
87405 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
87406 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
87407 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
87408 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
87409 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
87410 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
87411 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
87412 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
87413 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
87414 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
87415 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
87416 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
87417 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
87418 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
87419 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
87420 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
87421 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
87422 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
87423 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
87424 -----END CERTIFICATE-----
87425
87426 Comodo AAA Services root
87427 ========================
87428 -----BEGIN CERTIFICATE-----
87429 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
87430 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
87431 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
87432 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
87433 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
87434 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
87435 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
87436 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
87437 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
87438 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
87439 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
87440 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
87441 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
87442 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
87443 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
87444 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
87445 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
87446 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
87447 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
87448 -----END CERTIFICATE-----
87449
87450 QuoVadis Root CA
87451 ================
87452 -----BEGIN CERTIFICATE-----
87453 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
87454 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
87455 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
87456 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
87457 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
87458 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
87459 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
87460 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
87461 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
87462 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
87463 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
87464 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
87465 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
87466 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
87467 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
87468 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
87469 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
87470 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
87471 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
87472 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
87473 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
87474 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
87475 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
87476 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
87477 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
87478 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
87479 5nrQNiOKSnQ2+Q==
87480 -----END CERTIFICATE-----
87481
87482 QuoVadis Root CA 2
87483 ==================
87484 -----BEGIN CERTIFICATE-----
87485 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
87486 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
87487 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
87488 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
87489 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
87490 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
87491 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
87492 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
87493 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
87494 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
87495 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
87496 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
87497 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
87498 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
87499 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
87500 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
87501 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
87502 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
87503 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
87504 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
87505 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
87506 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
87507 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
87508 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
87509 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
87510 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
87511 -----END CERTIFICATE-----
87512
87513 QuoVadis Root CA 3
87514 ==================
87515 -----BEGIN CERTIFICATE-----
87516 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
87517 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
87518 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
87519 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
87520 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
87521 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
87522 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
87523 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
87524 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
87525 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
87526 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
87527 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
87528 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
87529 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
87530 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
87531 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
87532 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
87533 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
87534 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
87535 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
87536 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
87537 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
87538 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
87539 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
87540 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
87541 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
87542 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
87543 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
87544 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
87545 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
87546 -----END CERTIFICATE-----
87547
87548 Security Communication Root CA
87549 ==============================
87550 -----BEGIN CERTIFICATE-----
87551 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
87552 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
87553 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
87554 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
87555 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
87556 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
87557 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
87558 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
87559 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
87560 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
87561 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
87562 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
87563 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
87564 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
87565 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
87566 FL39vmwLAw==
87567 -----END CERTIFICATE-----
87568
87569 Sonera Class 2 Root CA
87570 ======================
87571 -----BEGIN CERTIFICATE-----
87572 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
87573 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
87574 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
87575 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
87576 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
87577 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
87578 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
87579 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
87580 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
87581 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
87582 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
87583 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
87584 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
87585 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
87586 llpwrN9M
87587 -----END CERTIFICATE-----
87588
87589 XRamp Global CA Root
87590 ====================
87591 -----BEGIN CERTIFICATE-----
87592 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
87593 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
87594 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
87595 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
87596 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
87597 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
87598 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
87599 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
87600 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
87601 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
87602 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
87603 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
87604 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
87605 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
87606 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
87607 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
87608 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
87609 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
87610 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
87611 -----END CERTIFICATE-----
87612
87613 Go Daddy Class 2 CA
87614 ===================
87615 -----BEGIN CERTIFICATE-----
87616 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
87617 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
87618 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
87619 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
87620 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
87621 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
87622 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
87623 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
87624 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
87625 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
87626 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
87627 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
87628 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
87629 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
87630 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
87631 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
87632 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
87633 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
87634 vZ8=
87635 -----END CERTIFICATE-----
87636
87637 Starfield Class 2 CA
87638 ====================
87639 -----BEGIN CERTIFICATE-----
87640 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
87641 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
87642 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
87643 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
87644 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
87645 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
87646 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
87647 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
87648 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
87649 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
87650 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
87651 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
87652 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
87653 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
87654 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
87655 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
87656 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
87657 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
87658 QBFGmh95DmK/D5fs4C8fF5Q=
87659 -----END CERTIFICATE-----
87660
87661 Taiwan GRCA
87662 ===========
87663 -----BEGIN CERTIFICATE-----
87664 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
87665 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
87666 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
87667 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
87668 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
87669 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
87670 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
87671 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
87672 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
87673 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
87674 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
87675 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
87676 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
87677 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
87678 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
87679 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
87680 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
87681 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
87682 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
87683 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
87684 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
87685 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
87686 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
87687 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
87688 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
87689 -----END CERTIFICATE-----
87690
87691 DigiCert Assured ID Root CA
87692 ===========================
87693 -----BEGIN CERTIFICATE-----
87694 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
87695 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
87696 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
87697 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
87698 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
87699 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
87700 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
87701 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
87702 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
87703 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
87704 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
87705 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
87706 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
87707 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
87708 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
87709 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
87710 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
87711 -----END CERTIFICATE-----
87712
87713 DigiCert Global Root CA
87714 =======================
87715 -----BEGIN CERTIFICATE-----
87716 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
87717 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
87718 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
87719 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
87720 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
87721 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
87722 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
87723 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
87724 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
87725 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
87726 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
87727 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
87728 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
87729 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
87730 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
87731 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
87732 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
87733 -----END CERTIFICATE-----
87734
87735 DigiCert High Assurance EV Root CA
87736 ==================================
87737 -----BEGIN CERTIFICATE-----
87738 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
87739 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
87740 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
87741 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
87742 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
87743 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
87744 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
87745 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
87746 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
87747 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
87748 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
87749 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
87750 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
87751 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
87752 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
87753 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
87754 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
87755 -----END CERTIFICATE-----
87756
87757 Certplus Class 2 Primary CA
87758 ===========================
87759 -----BEGIN CERTIFICATE-----
87760 MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
87761 BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
87762 OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
87763 dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
87764 ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
87765 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
87766 Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
87767 YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
87768 e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
87769 CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
87770 YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
87771 L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
87772 P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
87773 TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
87774 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
87775 //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
87776 l7+ijrRU
87777 -----END CERTIFICATE-----
87778
87779 DST Root CA X3
87780 ==============
87781 -----BEGIN CERTIFICATE-----
87782 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
87783 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
87784 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
87785 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
87786 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
87787 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
87788 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
87789 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
87790 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
87791 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
87792 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
87793 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
87794 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
87795 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
87796 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
87797 -----END CERTIFICATE-----
87798
87799 SwissSign Gold CA - G2
87800 ======================
87801 -----BEGIN CERTIFICATE-----
87802 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
87803 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
87804 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
87805 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
87806 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
87807 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
87808 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
87809 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
87810 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
87811 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
87812 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
87813 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
87814 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
87815 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
87816 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
87817 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
87818 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
87819 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
87820 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
87821 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
87822 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
87823 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
87824 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
87825 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
87826 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
87827 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
87828 -----END CERTIFICATE-----
87829
87830 SwissSign Silver CA - G2
87831 ========================
87832 -----BEGIN CERTIFICATE-----
87833 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
87834 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
87835 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
87836 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
87837 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
87838 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
87839 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
87840 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
87841 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
87842 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
87843 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
87844 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
87845 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
87846 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
87847 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
87848 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
87849 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
87850 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
87851 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
87852 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
87853 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
87854 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
87855 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
87856 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
87857 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
87858 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
87859 -----END CERTIFICATE-----
87860
87861 GeoTrust Primary Certification Authority
87862 ========================================
87863 -----BEGIN CERTIFICATE-----
87864 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
87865 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
87866 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
87867 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
87868 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
87869 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
87870 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
87871 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
87872 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
87873 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
87874 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
87875 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
87876 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
87877 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
87878 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
87879 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
87880 -----END CERTIFICATE-----
87881
87882 thawte Primary Root CA
87883 ======================
87884 -----BEGIN CERTIFICATE-----
87885 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
87886 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
87887 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
87888 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
87889 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
87890 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
87891 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
87892 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
87893 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
87894 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
87895 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
87896 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
87897 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
87898 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
87899 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
87900 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
87901 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
87902 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
87903 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
87904 -----END CERTIFICATE-----
87905
87906 VeriSign Class 3 Public Primary Certification Authority - G5
87907 ============================================================
87908 -----BEGIN CERTIFICATE-----
87909 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
87910 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
87911 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
87912 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
87913 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
87914 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
87915 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
87916 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
87917 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
87918 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
87919 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
87920 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
87921 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
87922 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
87923 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
87924 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
87925 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
87926 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
87927 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
87928 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
87929 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
87930 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
87931 -----END CERTIFICATE-----
87932
87933 SecureTrust CA
87934 ==============
87935 -----BEGIN CERTIFICATE-----
87936 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
87937 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
87938 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
87939 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
87940 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
87941 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
87942 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
87943 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
87944 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
87945 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
87946 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
87947 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
87948 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
87949 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
87950 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
87951 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
87952 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
87953 -----END CERTIFICATE-----
87954
87955 Secure Global CA
87956 ================
87957 -----BEGIN CERTIFICATE-----
87958 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
87959 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
87960 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
87961 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
87962 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
87963 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
87964 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
87965 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
87966 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
87967 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
87968 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
87969 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
87970 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
87971 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
87972 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
87973 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
87974 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
87975 -----END CERTIFICATE-----
87976
87977 COMODO Certification Authority
87978 ==============================
87979 -----BEGIN CERTIFICATE-----
87980 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
87981 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
87982 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
87983 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
87984 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
87985 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
87986 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
87987 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
87988 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
87989 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
87990 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
87991 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
87992 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
87993 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
87994 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
87995 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
87996 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
87997 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
87998 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
87999 -----END CERTIFICATE-----
88000
88001 Network Solutions Certificate Authority
88002 =======================================
88003 -----BEGIN CERTIFICATE-----
88004 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
88005 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
88006 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
88007 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
88008 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
88009 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
88010 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
88011 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
88012 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
88013 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
88014 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
88015 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
88016 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
88017 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
88018 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
88019 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
88020 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
88021 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
88022 -----END CERTIFICATE-----
88023
88024 COMODO ECC Certification Authority
88025 ==================================
88026 -----BEGIN CERTIFICATE-----
88027 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
88028 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
88029 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
88030 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
88031 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
88032 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
88033 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
88034 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
88035 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
88036 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
88037 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
88038 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
88039 -----END CERTIFICATE-----
88040
88041 OISTE WISeKey Global Root GA CA
88042 ===============================
88043 -----BEGIN CERTIFICATE-----
88044 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
88045 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
88046 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
88047 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
88048 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
88049 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
88050 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
88051 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
88052 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
88053 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
88054 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
88055 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
88056 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
88057 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
88058 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
88059 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
88060 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
88061 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
88062 -----END CERTIFICATE-----
88063
88064 Certigna
88065 ========
88066 -----BEGIN CERTIFICATE-----
88067 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
88068 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
88069 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
88070 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
88071 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
88072 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
88073 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
88074 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
88075 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
88076 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
88077 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
88078 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
88079 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
88080 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
88081 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
88082 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
88083 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
88084 -----END CERTIFICATE-----
88085
88086 Deutsche Telekom Root CA 2
88087 ==========================
88088 -----BEGIN CERTIFICATE-----
88089 MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
88090 RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
88091 A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
88092 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
88093 A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
88094 b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
88095 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
88096 KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
88097 AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
88098 Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
88099 jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
88100 HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
88101 E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
88102 zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
88103 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
88104 dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
88105 Cm26OWMohpLzGITY+9HPBVZkVw==
88106 -----END CERTIFICATE-----
88107
88108 Cybertrust Global Root
88109 ======================
88110 -----BEGIN CERTIFICATE-----
88111 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
88112 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
88113 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
88114 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
88115 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
88116 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
88117 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
88118 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
88119 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
88120 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
88121 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
88122 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
88123 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
88124 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
88125 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
88126 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
88127 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
88128 -----END CERTIFICATE-----
88129
88130 ePKI Root Certification Authority
88131 =================================
88132 -----BEGIN CERTIFICATE-----
88133 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
88134 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
88135 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
88136 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
88137 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
88138 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
88139 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
88140 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
88141 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
88142 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
88143 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
88144 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
88145 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
88146 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
88147 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
88148 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
88149 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
88150 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
88151 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
88152 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
88153 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
88154 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
88155 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
88156 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
88157 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
88158 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
88159 -----END CERTIFICATE-----
88160
88161 certSIGN ROOT CA
88162 ================
88163 -----BEGIN CERTIFICATE-----
88164 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
88165 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
88166 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
88167 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
88168 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
88169 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
88170 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
88171 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
88172 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
88173 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
88174 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
88175 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
88176 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
88177 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
88178 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
88179 -----END CERTIFICATE-----
88180
88181 GeoTrust Primary Certification Authority - G3
88182 =============================================
88183 -----BEGIN CERTIFICATE-----
88184 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
88185 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
88186 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
88187 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
88188 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
88189 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
88190 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
88191 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
88192 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
88193 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
88194 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
88195 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
88196 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
88197 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
88198 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
88199 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
88200 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
88201 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
88202 -----END CERTIFICATE-----
88203
88204 thawte Primary Root CA - G2
88205 ===========================
88206 -----BEGIN CERTIFICATE-----
88207 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
88208 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
88209 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
88210 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
88211 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
88212 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
88213 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
88214 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
88215 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
88216 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
88217 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
88218 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
88219 -----END CERTIFICATE-----
88220
88221 thawte Primary Root CA - G3
88222 ===========================
88223 -----BEGIN CERTIFICATE-----
88224 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
88225 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
88226 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
88227 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
88228 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
88229 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
88230 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
88231 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
88232 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
88233 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
88234 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
88235 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
88236 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
88237 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
88238 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
88239 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
88240 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
88241 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
88242 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
88243 -----END CERTIFICATE-----
88244
88245 GeoTrust Primary Certification Authority - G2
88246 =============================================
88247 -----BEGIN CERTIFICATE-----
88248 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
88249 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
88250 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
88251 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
88252 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
88253 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
88254 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
88255 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
88256 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
88257 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
88258 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
88259 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
88260 npaqBA+K
88261 -----END CERTIFICATE-----
88262
88263 VeriSign Universal Root Certification Authority
88264 ===============================================
88265 -----BEGIN CERTIFICATE-----
88266 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
88267 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
88268 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
88269 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
88270 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
88271 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
88272 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
88273 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
88274 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
88275 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
88276 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
88277 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
88278 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
88279 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
88280 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
88281 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
88282 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
88283 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
88284 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
88285 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
88286 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
88287 mJO37M2CYfE45k+XmCpajQ==
88288 -----END CERTIFICATE-----
88289
88290 VeriSign Class 3 Public Primary Certification Authority - G4
88291 ============================================================
88292 -----BEGIN CERTIFICATE-----
88293 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
88294 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
88295 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
88296 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
88297 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
88298 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
88299 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
88300 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
88301 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
88302 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
88303 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
88304 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
88305 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
88306 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
88307 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
88308 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
88309 -----END CERTIFICATE-----
88310
88311 NetLock Arany (Class Gold) Főtanúsítvány
88312 ========================================
88313 -----BEGIN CERTIFICATE-----
88314 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
88315 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
88316 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
88317 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
88318 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
88319 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
88320 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
88321 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
88322 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
88323 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
88324 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
88325 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
88326 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
88327 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
88328 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
88329 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
88330 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
88331 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
88332 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
88333 -----END CERTIFICATE-----
88334
88335 Staat der Nederlanden Root CA - G2
88336 ==================================
88337 -----BEGIN CERTIFICATE-----
88338 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
88339 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
88340 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
88341 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
88342 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
88343 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
88344 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
88345 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
88346 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
88347 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
88348 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
88349 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
88350 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
88351 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
88352 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
88353 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
88354 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
88355 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
88356 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
88357 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
88358 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
88359 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
88360 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
88361 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
88362 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
88363 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
88364 66+KAQ==
88365 -----END CERTIFICATE-----
88366
88367 Hongkong Post Root CA 1
88368 =======================
88369 -----BEGIN CERTIFICATE-----
88370 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
88371 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
88372 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
88373 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
88374 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
88375 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
88376 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
88377 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
88378 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
88379 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
88380 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
88381 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
88382 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
88383 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
88384 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
88385 -----END CERTIFICATE-----
88386
88387 SecureSign RootCA11
88388 ===================
88389 -----BEGIN CERTIFICATE-----
88390 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
88391 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
88392 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
88393 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
88394 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
88395 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
88396 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
88397 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
88398 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
88399 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
88400 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
88401 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
88402 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
88403 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
88404 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
88405 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
88406 -----END CERTIFICATE-----
88407
88408 Microsec e-Szigno Root CA 2009
88409 ==============================
88410 -----BEGIN CERTIFICATE-----
88411 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
88412 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
88413 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
88414 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
88415 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
88416 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
88417 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
88418 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
88419 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
88420 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
88421 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
88422 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
88423 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
88424 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
88425 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
88426 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
88427 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
88428 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
88429 LXpUq3DDfSJlgnCW
88430 -----END CERTIFICATE-----
88431
88432 GlobalSign Root CA - R3
88433 =======================
88434 -----BEGIN CERTIFICATE-----
88435 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
88436 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
88437 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
88438 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
88439 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
88440 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
88441 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
88442 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
88443 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
88444 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
88445 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
88446 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
88447 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
88448 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
88449 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
88450 kpeDMdmztcpHWD9f
88451 -----END CERTIFICATE-----
88452
88453 Autoridad de Certificacion Firmaprofesional CIF A62634068
88454 =========================================================
88455 -----BEGIN CERTIFICATE-----
88456 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
88457 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
88458 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
88459 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
88460 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
88461 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
88462 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
88463 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
88464 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
88465 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
88466 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
88467 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
88468 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
88469 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
88470 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
88471 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
88472 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
88473 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
88474 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
88475 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
88476 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
88477 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
88478 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
88479 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
88480 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
88481 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
88482 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
88483 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
88484 -----END CERTIFICATE-----
88485
88486 Izenpe.com
88487 ==========
88488 -----BEGIN CERTIFICATE-----
88489 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
88490 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
88491 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
88492 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
88493 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
88494 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
88495 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
88496 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
88497 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
88498 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
88499 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
88500 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
88501 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
88502 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
88503 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
88504 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
88505 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
88506 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
88507 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
88508 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
88509 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
88510 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
88511 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
88512 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
88513 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
88514 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
88515 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
88516 -----END CERTIFICATE-----
88517
88518 Chambers of Commerce Root - 2008
88519 ================================
88520 -----BEGIN CERTIFICATE-----
88521 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
88522 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
88523 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
88524 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
88525 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
88526 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
88527 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
88528 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
88529 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
88530 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
88531 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
88532 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
88533 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
88534 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
88535 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
88536 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
88537 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
88538 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
88539 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
88540 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
88541 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
88542 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
88543 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
88544 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
88545 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
88546 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
88547 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
88548 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
88549 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
88550 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
88551 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
88552 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
88553 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
88554 -----END CERTIFICATE-----
88555
88556 Global Chambersign Root - 2008
88557 ==============================
88558 -----BEGIN CERTIFICATE-----
88559 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
88560 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
88561 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
88562 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
88563 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
88564 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
88565 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
88566 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
88567 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
88568 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
88569 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
88570 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
88571 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
88572 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
88573 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
88574 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
88575 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
88576 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
88577 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
88578 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
88579 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
88580 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
88581 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
88582 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
88583 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
88584 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
88585 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
88586 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
88587 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
88588 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
88589 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
88590 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
88591 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
88592 -----END CERTIFICATE-----
88593
88594 Go Daddy Root Certificate Authority - G2
88595 ========================================
88596 -----BEGIN CERTIFICATE-----
88597 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
88598 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
88599 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
88600 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
88601 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
88602 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
88603 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
88604 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
88605 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
88606 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
88607 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
88608 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
88609 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
88610 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
88611 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
88612 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
88613 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
88614 -----END CERTIFICATE-----
88615
88616 Starfield Root Certificate Authority - G2
88617 =========================================
88618 -----BEGIN CERTIFICATE-----
88619 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
88620 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
88621 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
88622 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
88623 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
88624 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
88625 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
88626 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
88627 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
88628 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
88629 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
88630 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
88631 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
88632 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
88633 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
88634 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
88635 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
88636 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
88637 -----END CERTIFICATE-----
88638
88639 Starfield Services Root Certificate Authority - G2
88640 ==================================================
88641 -----BEGIN CERTIFICATE-----
88642 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
88643 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
88644 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
88645 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
88646 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
88647 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
88648 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
88649 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
88650 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
88651 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
88652 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
88653 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
88654 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
88655 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
88656 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
88657 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
88658 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
88659 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
88660 -----END CERTIFICATE-----
88661
88662 AffirmTrust Commercial
88663 ======================
88664 -----BEGIN CERTIFICATE-----
88665 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
88666 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
88667 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
88668 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
88669 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
88670 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
88671 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
88672 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
88673 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
88674 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
88675 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
88676 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
88677 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
88678 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
88679 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
88680 -----END CERTIFICATE-----
88681
88682 AffirmTrust Networking
88683 ======================
88684 -----BEGIN CERTIFICATE-----
88685 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
88686 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
88687 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
88688 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
88689 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
88690 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
88691 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
88692 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
88693 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
88694 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
88695 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
88696 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
88697 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
88698 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
88699 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
88700 -----END CERTIFICATE-----
88701
88702 AffirmTrust Premium
88703 ===================
88704 -----BEGIN CERTIFICATE-----
88705 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
88706 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
88707 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
88708 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
88709 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
88710 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
88711 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
88712 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
88713 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
88714 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
88715 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
88716 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
88717 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
88718 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
88719 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
88720 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
88721 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
88722 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
88723 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
88724 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
88725 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
88726 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
88727 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
88728 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
88729 -----END CERTIFICATE-----
88730
88731 AffirmTrust Premium ECC
88732 =======================
88733 -----BEGIN CERTIFICATE-----
88734 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
88735 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
88736 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
88737 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
88738 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
88739 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
88740 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
88741 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
88742 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
88743 eQ==
88744 -----END CERTIFICATE-----
88745
88746 Certum Trusted Network CA
88747 =========================
88748 -----BEGIN CERTIFICATE-----
88749 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
88750 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
88751 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
88752 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
88753 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
88754 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
88755 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
88756 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
88757 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
88758 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
88759 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
88760 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
88761 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
88762 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
88763 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
88764 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
88765 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
88766 -----END CERTIFICATE-----
88767
88768 TWCA Root Certification Authority
88769 =================================
88770 -----BEGIN CERTIFICATE-----
88771 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
88772 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
88773 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
88774 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
88775 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
88776 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
88777 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
88778 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
88779 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
88780 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
88781 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
88782 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
88783 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
88784 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
88785 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
88786 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
88787 -----END CERTIFICATE-----
88788
88789 Security Communication RootCA2
88790 ==============================
88791 -----BEGIN CERTIFICATE-----
88792 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
88793 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
88794 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
88795 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
88796 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
88797 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
88798 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
88799 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
88800 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
88801 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
88802 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
88803 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
88804 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
88805 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
88806 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
88807 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
88808 -----END CERTIFICATE-----
88809
88810 EC-ACC
88811 ======
88812 -----BEGIN CERTIFICATE-----
88813 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
88814 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
88815 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
88816 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
88817 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
88818 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
88819 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
88820 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
88821 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
88822 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
88823 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
88824 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
88825 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
88826 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
88827 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
88828 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
88829 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
88830 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
88831 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
88832 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
88833 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
88834 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
88835 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
88836 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
88837 5EI=
88838 -----END CERTIFICATE-----
88839
88840 Hellenic Academic and Research Institutions RootCA 2011
88841 =======================================================
88842 -----BEGIN CERTIFICATE-----
88843 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
88844 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
88845 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
88846 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
88847 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
88848 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
88849 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
88850 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
88851 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
88852 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
88853 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
88854 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
88855 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
88856 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
88857 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
88858 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
88859 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
88860 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
88861 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
88862 -----END CERTIFICATE-----
88863
88864 Actalis Authentication Root CA
88865 ==============================
88866 -----BEGIN CERTIFICATE-----
88867 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
88868 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
88869 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
88870 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
88871 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
88872 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
88873 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
88874 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
88875 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
88876 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
88877 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
88878 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
88879 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
88880 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
88881 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
88882 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
88883 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
88884 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
88885 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
88886 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
88887 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
88888 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
88889 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
88890 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
88891 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
88892 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
88893 -----END CERTIFICATE-----
88894
88895 Trustis FPS Root CA
88896 ===================
88897 -----BEGIN CERTIFICATE-----
88898 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
88899 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
88900 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
88901 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
88902 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
88903 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
88904 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
88905 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
88906 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
88907 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
88908 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
88909 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
88910 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
88911 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
88912 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
88913 iB6XzCGcKQENZetX2fNXlrtIzYE=
88914 -----END CERTIFICATE-----
88915
88916 Buypass Class 2 Root CA
88917 =======================
88918 -----BEGIN CERTIFICATE-----
88919 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
88920 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
88921 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
88922 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
88923 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
88924 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
88925 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
88926 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
88927 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
88928 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
88929 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
88930 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
88931 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
88932 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
88933 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
88934 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
88935 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
88936 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
88937 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
88938 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
88939 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
88940 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
88941 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
88942 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
88943 rJgWVqA=
88944 -----END CERTIFICATE-----
88945
88946 Buypass Class 3 Root CA
88947 =======================
88948 -----BEGIN CERTIFICATE-----
88949 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
88950 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
88951 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
88952 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
88953 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
88954 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
88955 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
88956 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
88957 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
88958 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
88959 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
88960 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
88961 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
88962 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
88963 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
88964 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
88965 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
88966 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
88967 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
88968 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
88969 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
88970 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
88971 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
88972 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
88973 Cp/HuZc=
88974 -----END CERTIFICATE-----
88975
88976 T-TeleSec GlobalRoot Class 3
88977 ============================
88978 -----BEGIN CERTIFICATE-----
88979 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
88980 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
88981 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
88982 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
88983 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
88984 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
88985 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
88986 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
88987 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
88988 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
88989 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
88990 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
88991 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
88992 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
88993 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
88994 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
88995 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
88996 -----END CERTIFICATE-----
88997
88998 EE Certification Centre Root CA
88999 ===============================
89000 -----BEGIN CERTIFICATE-----
89001 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
89002 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
89003 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
89004 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
89005 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
89006 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
89007 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
89008 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
89009 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
89010 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
89011 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
89012 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
89013 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
89014 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
89015 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
89016 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
89017 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
89018 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
89019 dcGWxZ0=
89020 -----END CERTIFICATE-----
89021
89022 D-TRUST Root Class 3 CA 2 2009
89023 ==============================
89024 -----BEGIN CERTIFICATE-----
89025 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
89026 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
89027 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
89028 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
89029 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
89030 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
89031 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
89032 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
89033 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
89034 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
89035 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
89036 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
89037 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
89038 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
89039 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
89040 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
89041 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
89042 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
89043 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
89044 -----END CERTIFICATE-----
89045
89046 D-TRUST Root Class 3 CA 2 EV 2009
89047 =================================
89048 -----BEGIN CERTIFICATE-----
89049 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
89050 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
89051 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
89052 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
89053 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
89054 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
89055 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
89056 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
89057 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
89058 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
89059 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
89060 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
89061 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
89062 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
89063 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
89064 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
89065 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
89066 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
89067 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
89068 w9y4AyHqnxbxLFS1
89069 -----END CERTIFICATE-----
89070
89071 CA Disig Root R2
89072 ================
89073 -----BEGIN CERTIFICATE-----
89074 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
89075 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
89076 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
89077 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
89078 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
89079 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
89080 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
89081 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
89082 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
89083 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
89084 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
89085 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
89086 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
89087 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
89088 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
89089 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
89090 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
89091 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
89092 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
89093 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
89094 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
89095 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
89096 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
89097 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
89098 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
89099 -----END CERTIFICATE-----
89100
89101 ACCVRAIZ1
89102 =========
89103 -----BEGIN CERTIFICATE-----
89104 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
89105 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
89106 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
89107 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
89108 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
89109 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
89110 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
89111 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
89112 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
89113 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
89114 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
89115 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
89116 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
89117 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
89118 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
89119 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
89120 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
89121 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
89122 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
89123 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
89124 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
89125 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
89126 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
89127 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
89128 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
89129 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
89130 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
89131 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
89132 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
89133 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
89134 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
89135 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
89136 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
89137 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
89138 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
89139 EfbRD0tVNEYqi4Y7
89140 -----END CERTIFICATE-----
89141
89142 TWCA Global Root CA
89143 ===================
89144 -----BEGIN CERTIFICATE-----
89145 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
89146 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
89147 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
89148 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
89149 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
89150 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
89151 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
89152 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
89153 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
89154 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
89155 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
89156 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
89157 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
89158 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
89159 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
89160 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
89161 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
89162 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
89163 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
89164 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
89165 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
89166 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
89167 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
89168 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
89169 -----END CERTIFICATE-----
89170
89171 TeliaSonera Root CA v1
89172 ======================
89173 -----BEGIN CERTIFICATE-----
89174 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
89175 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
89176 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
89177 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
89178 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
89179 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
89180 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
89181 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
89182 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
89183 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
89184 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
89185 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
89186 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
89187 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
89188 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
89189 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
89190 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
89191 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
89192 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
89193 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
89194 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
89195 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
89196 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
89197 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
89198 -----END CERTIFICATE-----
89199
89200 E-Tugra Certification Authority
89201 ===============================
89202 -----BEGIN CERTIFICATE-----
89203 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
89204 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
89205 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
89206 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
89207 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
89208 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
89209 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
89210 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
89211 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
89212 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
89213 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
89214 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
89215 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
89216 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
89217 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
89218 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
89219 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
89220 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
89221 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
89222 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
89223 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
89224 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
89225 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
89226 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
89227 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
89228 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
89229 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
89230 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
89231 C7TbO6Orb1wdtn7os4I07QZcJA==
89232 -----END CERTIFICATE-----
89233
89234 T-TeleSec GlobalRoot Class 2
89235 ============================
89236 -----BEGIN CERTIFICATE-----
89237 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
89238 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
89239 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
89240 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
89241 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
89242 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
89243 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
89244 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
89245 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
89246 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
89247 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
89248 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
89249 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
89250 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
89251 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
89252 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
89253 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
89254 -----END CERTIFICATE-----
89255
89256 Atos TrustedRoot 2011
89257 =====================
89258 -----BEGIN CERTIFICATE-----
89259 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
89260 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
89261 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
89262 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
89263 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
89264 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
89265 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
89266 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
89267 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
89268 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
89269 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
89270 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
89271 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
89272 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
89273 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
89274 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
89275 -----END CERTIFICATE-----
89276
89277 QuoVadis Root CA 1 G3
89278 =====================
89279 -----BEGIN CERTIFICATE-----
89280 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
89281 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
89282 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
89283 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
89284 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
89285 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
89286 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
89287 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
89288 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
89289 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
89290 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
89291 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
89292 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
89293 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89294 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
89295 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
89296 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
89297 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
89298 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
89299 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
89300 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
89301 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
89302 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
89303 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
89304 hMJKzRwuJIczYOXD
89305 -----END CERTIFICATE-----
89306
89307 QuoVadis Root CA 2 G3
89308 =====================
89309 -----BEGIN CERTIFICATE-----
89310 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
89311 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
89312 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
89313 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
89314 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
89315 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
89316 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
89317 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
89318 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
89319 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
89320 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
89321 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
89322 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
89323 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89324 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
89325 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
89326 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
89327 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
89328 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
89329 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
89330 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
89331 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
89332 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
89333 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
89334 O3jtZsSOeWmD3n+M
89335 -----END CERTIFICATE-----
89336
89337 QuoVadis Root CA 3 G3
89338 =====================
89339 -----BEGIN CERTIFICATE-----
89340 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
89341 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
89342 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
89343 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
89344 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
89345 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
89346 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
89347 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
89348 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
89349 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
89350 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
89351 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
89352 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
89353 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89354 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
89355 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
89356 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
89357 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
89358 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
89359 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
89360 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
89361 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
89362 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
89363 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
89364 PpxxVJkES/1Y+Zj0
89365 -----END CERTIFICATE-----
89366
89367 DigiCert Assured ID Root G2
89368 ===========================
89369 -----BEGIN CERTIFICATE-----
89370 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
89371 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
89372 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
89373 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
89374 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
89375 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
89376 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
89377 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
89378 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
89379 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
89380 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
89381 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
89382 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
89383 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
89384 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
89385 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
89386 IhNzbM8m9Yop5w==
89387 -----END CERTIFICATE-----
89388
89389 DigiCert Assured ID Root G3
89390 ===========================
89391 -----BEGIN CERTIFICATE-----
89392 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
89393 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
89394 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
89395 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
89396 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
89397 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
89398 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
89399 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
89400 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
89401 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
89402 1vUhZscv6pZjamVFkpUBtA==
89403 -----END CERTIFICATE-----
89404
89405 DigiCert Global Root G2
89406 =======================
89407 -----BEGIN CERTIFICATE-----
89408 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
89409 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
89410 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
89411 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
89412 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
89413 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
89414 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
89415 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
89416 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
89417 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
89418 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
89419 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
89420 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
89421 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
89422 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
89423 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
89424 MrY=
89425 -----END CERTIFICATE-----
89426
89427 DigiCert Global Root G3
89428 =======================
89429 -----BEGIN CERTIFICATE-----
89430 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
89431 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
89432 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
89433 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
89434 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
89435 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
89436 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
89437 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
89438 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
89439 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
89440 VOKa5Vt8sycX
89441 -----END CERTIFICATE-----
89442
89443 DigiCert Trusted Root G4
89444 ========================
89445 -----BEGIN CERTIFICATE-----
89446 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
89447 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
89448 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
89449 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
89450 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
89451 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
89452 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
89453 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
89454 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
89455 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
89456 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
89457 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
89458 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
89459 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
89460 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
89461 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
89462 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
89463 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
89464 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
89465 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
89466 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
89467 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
89468 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
89469 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
89470 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
89471 82Z+
89472 -----END CERTIFICATE-----
89473
89474 COMODO RSA Certification Authority
89475 ==================================
89476 -----BEGIN CERTIFICATE-----
89477 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
89478 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
89479 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
89480 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
89481 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
89482 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
89483 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
89484 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
89485 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
89486 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
89487 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
89488 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
89489 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
89490 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
89491 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
89492 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
89493 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
89494 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
89495 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
89496 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
89497 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
89498 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
89499 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
89500 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
89501 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
89502 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
89503 LaZRfyHBNVOFBkpdn627G190
89504 -----END CERTIFICATE-----
89505
89506 USERTrust RSA Certification Authority
89507 =====================================
89508 -----BEGIN CERTIFICATE-----
89509 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
89510 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
89511 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
89512 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
89513 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
89514 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
89515 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
89516 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
89517 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
89518 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
89519 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
89520 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
89521 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
89522 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
89523 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
89524 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
89525 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
89526 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
89527 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
89528 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
89529 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
89530 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
89531 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
89532 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
89533 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
89534 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
89535 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
89536 -----END CERTIFICATE-----
89537
89538 USERTrust ECC Certification Authority
89539 =====================================
89540 -----BEGIN CERTIFICATE-----
89541 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
89542 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
89543 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
89544 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
89545 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
89546 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
89547 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
89548 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
89549 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
89550 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
89551 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
89552 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
89553 -----END CERTIFICATE-----
89554
89555 GlobalSign ECC Root CA - R4
89556 ===========================
89557 -----BEGIN CERTIFICATE-----
89558 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
89559 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89560 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
89561 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89562 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
89563 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
89564 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
89565 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
89566 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
89567 -----END CERTIFICATE-----
89568
89569 GlobalSign ECC Root CA - R5
89570 ===========================
89571 -----BEGIN CERTIFICATE-----
89572 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
89573 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89574 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
89575 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
89576 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
89577 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
89578 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
89579 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
89580 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
89581 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
89582 -----END CERTIFICATE-----
89583
89584 Staat der Nederlanden Root CA - G3
89585 ==================================
89586 -----BEGIN CERTIFICATE-----
89587 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
89588 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
89589 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
89590 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
89591 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
89592 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
89593 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
89594 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
89595 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
89596 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
89597 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
89598 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
89599 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
89600 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
89601 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
89602 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
89603 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
89604 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
89605 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
89606 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
89607 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
89608 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
89609 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
89610 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
89611 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
89612 -----END CERTIFICATE-----
89613
89614 Staat der Nederlanden EV Root CA
89615 ================================
89616 -----BEGIN CERTIFICATE-----
89617 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
89618 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
89619 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
89620 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
89621 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
89622 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
89623 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
89624 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
89625 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
89626 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
89627 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
89628 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
89629 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
89630 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
89631 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
89632 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
89633 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
89634 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
89635 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
89636 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
89637 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
89638 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
89639 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
89640 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
89641 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
89642 -----END CERTIFICATE-----
89643
89644 IdenTrust Commercial Root CA 1
89645 ==============================
89646 -----BEGIN CERTIFICATE-----
89647 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
89648 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
89649 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
89650 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
89651 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
89652 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
89653 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
89654 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
89655 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
89656 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
89657 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
89658 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
89659 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
89660 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
89661 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
89662 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
89663 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
89664 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
89665 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
89666 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
89667 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
89668 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
89669 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
89670 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
89671 cGzM7vRX+Bi6hG6H
89672 -----END CERTIFICATE-----
89673
89674 IdenTrust Public Sector Root CA 1
89675 =================================
89676 -----BEGIN CERTIFICATE-----
89677 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
89678 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
89679 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
89680 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
89681 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
89682 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
89683 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
89684 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
89685 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
89686 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
89687 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
89688 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
89689 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
89690 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
89691 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
89692 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
89693 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
89694 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
89695 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
89696 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
89697 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
89698 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
89699 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
89700 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
89701 3Wl9af0AVqW3rLatt8o+Ae+c
89702 -----END CERTIFICATE-----
89703
89704 Entrust Root Certification Authority - G2
89705 =========================================
89706 -----BEGIN CERTIFICATE-----
89707 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
89708 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
89709 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
89710 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
89711 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
89712 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
89713 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
89714 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
89715 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
89716 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
89717 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
89718 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
89719 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
89720 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
89721 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
89722 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
89723 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
89724 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
89725 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
89726 e4pIb4tF9g==
89727 -----END CERTIFICATE-----
89728
89729 Entrust Root Certification Authority - EC1
89730 ==========================================
89731 -----BEGIN CERTIFICATE-----
89732 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
89733 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
89734 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
89735 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
89736 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
89737 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
89738 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
89739 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
89740 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
89741 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
89742 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
89743 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
89744 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
89745 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
89746 -----END CERTIFICATE-----
89747
89748 CFCA EV ROOT
89749 ============
89750 -----BEGIN CERTIFICATE-----
89751 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
89752 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
89753 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
89754 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
89755 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
89756 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
89757 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
89758 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
89759 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
89760 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
89761 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
89762 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
89763 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
89764 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
89765 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
89766 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
89767 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
89768 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
89769 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
89770 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
89771 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
89772 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
89773 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
89774 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
89775 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
89776 -----END CERTIFICATE-----
89777
89778 OISTE WISeKey Global Root GB CA
89779 ===============================
89780 -----BEGIN CERTIFICATE-----
89781 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
89782 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
89783 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
89784 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
89785 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
89786 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
89787 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
89788 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
89789 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
89790 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
89791 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
89792 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
89793 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
89794 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
89795 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
89796 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
89797 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
89798 -----END CERTIFICATE-----
89799
89800 SZAFIR ROOT CA2
89801 ===============
89802 -----BEGIN CERTIFICATE-----
89803 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
89804 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
89805 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
89806 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
89807 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
89808 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
89809 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
89810 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
89811 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
89812 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
89813 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
89814 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
89815 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
89816 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
89817 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
89818 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
89819 -----END CERTIFICATE-----
89820
89821 Certum Trusted Network CA 2
89822 ===========================
89823 -----BEGIN CERTIFICATE-----
89824 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
89825 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
89826 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
89827 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
89828 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
89829 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
89830 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
89831 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
89832 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
89833 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
89834 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
89835 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
89836 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
89837 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
89838 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
89839 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89840 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
89841 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
89842 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
89843 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
89844 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
89845 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
89846 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
89847 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
89848 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
89849 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
89850 zAYspsbiDrW5viSP
89851 -----END CERTIFICATE-----
89852
89853 Hellenic Academic and Research Institutions RootCA 2015
89854 =======================================================
89855 -----BEGIN CERTIFICATE-----
89856 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
89857 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
89858 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
89859 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
89860 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
89861 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
89862 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
89863 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
89864 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
89865 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
89866 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
89867 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
89868 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
89869 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
89870 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
89871 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
89872 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89873 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
89874 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
89875 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
89876 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
89877 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
89878 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
89879 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
89880 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
89881 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
89882 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
89883 p/UsQu0yrbYhnr68
89884 -----END CERTIFICATE-----
89885
89886 Hellenic Academic and Research Institutions ECC RootCA 2015
89887 ===========================================================
89888 -----BEGIN CERTIFICATE-----
89889 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
89890 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
89891 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
89892 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
89893 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
89894 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
89895 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
89896 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
89897 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
89898 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
89899 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
89900 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
89901 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
89902 -----END CERTIFICATE-----
89903
89904 ISRG Root X1
89905 ============
89906 -----BEGIN CERTIFICATE-----
89907 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
89908 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
89909 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
89910 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
89911 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
89912 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
89913 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
89914 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
89915 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
89916 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
89917 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
89918 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
89919 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
89920 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
89921 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
89922 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
89923 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
89924 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
89925 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
89926 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
89927 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
89928 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
89929 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
89930 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
89931 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
89932 -----END CERTIFICATE-----
89933
89934 AC RAIZ FNMT-RCM
89935 ================
89936 -----BEGIN CERTIFICATE-----
89937 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
89938 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
89939 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
89940 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
89941 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
89942 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
89943 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
89944 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
89945 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
89946 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
89947 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
89948 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
89949 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
89950 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
89951 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
89952 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
89953 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
89954 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
89955 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
89956 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
89957 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
89958 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
89959 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
89960 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
89961 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
89962 -----END CERTIFICATE-----
89963
89964 Amazon Root CA 1
89965 ================
89966 -----BEGIN CERTIFICATE-----
89967 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
89968 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
89969 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
89970 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
89971 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
89972 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
89973 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
89974 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
89975 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
89976 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
89977 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
89978 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
89979 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
89980 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
89981 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
89982 -----END CERTIFICATE-----
89983
89984 Amazon Root CA 2
89985 ================
89986 -----BEGIN CERTIFICATE-----
89987 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
89988 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
89989 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
89990 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
89991 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
89992 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
89993 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
89994 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
89995 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
89996 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
89997 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
89998 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
89999 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
90000 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
90001 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
90002 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
90003 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
90004 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
90005 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
90006 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
90007 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
90008 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
90009 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
90010 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
90011 -----END CERTIFICATE-----
90012
90013 Amazon Root CA 3
90014 ================
90015 -----BEGIN CERTIFICATE-----
90016 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
90017 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
90018 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
90019 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
90020 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
90021 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
90022 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
90023 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
90024 -----END CERTIFICATE-----
90025
90026 Amazon Root CA 4
90027 ================
90028 -----BEGIN CERTIFICATE-----
90029 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
90030 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
90031 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
90032 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
90033 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
90034 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
90035 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
90036 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
90037 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
90038 -----END CERTIFICATE-----
90039
90040 LuxTrust Global Root 2
90041 ======================
90042 -----BEGIN CERTIFICATE-----
90043 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
90044 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
90045 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
90046 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
90047 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
90048 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
90049 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
90050 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
90051 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
90052 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
90053 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
90054 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
90055 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
90056 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
90057 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
90058 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
90059 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
90060 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
90061 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
90062 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
90063 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
90064 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
90065 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
90066 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
90067 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
90068 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
90069 -----END CERTIFICATE-----
90070
90071 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
90072 =============================================
90073 -----BEGIN CERTIFICATE-----
90074 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
90075 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
90076 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
90077 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
90078 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
90079 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
90080 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
90081 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
90082 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
90083 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
90084 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
90085 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
90086 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
90087 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
90088 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
90089 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
90090 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
90091 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
90092 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
90093 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
90094 -----END CERTIFICATE-----
90095
90096 GDCA TrustAUTH R5 ROOT
90097 ======================
90098 -----BEGIN CERTIFICATE-----
90099 MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
90100 BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
90101 DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
90102 YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
90103 IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
90104 AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
90105 AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
90106 OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
90107 pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
90108 9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
90109 xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
90110 R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
90111 D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
90112 oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
90113 9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
90114 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
90115 p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
90116 H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
90117 6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
90118 +PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
90119 HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
90120 F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
90121 8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
90122 /EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
90123 aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
90124 -----END CERTIFICATE-----
90125
90126 TrustCor RootCert CA-1
90127 ======================
90128 -----BEGIN CERTIFICATE-----
90129 MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP
90130 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
90131 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
90132 dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx
90133 MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu
90134 YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe
90135 VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy
90136 dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq
90137 jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4
90138 pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0
90139 JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h
90140 gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw
90141 /Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j
90142 BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
90143 AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5
90144 mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
90145 ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C
90146 qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P
90147 3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk=
90148 -----END CERTIFICATE-----
90149
90150 TrustCor RootCert CA-2
90151 ======================
90152 -----BEGIN CERTIFICATE-----
90153 MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w
90154 DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT
90155 eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0
90156 eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy
90157 MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h
90158 bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
90159 cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0
90160 IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb
90161 ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk
90162 RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1
90163 oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb
90164 XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1
90165 /p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q
90166 jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP
90167 eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg
90168 rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
90169 8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU
90170 2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD
90171 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h
90172 Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp
90173 kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv
90174 2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3
90175 S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw
90176 PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv
90177 DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU
90178 RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE
90179 xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX
90180 RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ
90181 -----END CERTIFICATE-----
90182
90183 TrustCor ECA-1
90184 ==============
90185 -----BEGIN CERTIFICATE-----
90186 MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP
90187 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
90188 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
90189 dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw
90190 N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5
90191 MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y
90192 IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG
90193 SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR
90194 MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23
90195 xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc
90196 p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+
90197 fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj
90198 YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL
90199 f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
90200 AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u
90201 /ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
90202 hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs
90203 J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC
90204 jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g==
90205 -----END CERTIFICATE-----
90206
90207 SSL.com Root Certification Authority RSA
90208 ========================================
90209 -----BEGIN CERTIFICATE-----
90210 MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
90211 BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
90212 MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
90213 MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
90214 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
90215 LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
90216 ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
90217 Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
90218 P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
90219 oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
90220 k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
90221 fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
90222 gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
90223 UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
90224 1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
90225 bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
90226 HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
90227 AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
90228 dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
90229 ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
90230 u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
90231 erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
90232 MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
90233 vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
90234 Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
90235 wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
90236 WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
90237 -----END CERTIFICATE-----
90238
90239 SSL.com Root Certification Authority ECC
90240 ========================================
90241 -----BEGIN CERTIFICATE-----
90242 MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
90243 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
90244 BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
90245 MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
90246 BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
90247 bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
90248 BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
90249 8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
90250 hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
90251 jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
90252 e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
90253 5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
90254 -----END CERTIFICATE-----
90255
90256 SSL.com EV Root Certification Authority RSA R2
90257 ==============================================
90258 -----BEGIN CERTIFICATE-----
90259 MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
90260 DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
90261 MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
90262 MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
90263 DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
90264 VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
90265 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
90266 hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
90267 cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
90268 Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
90269 B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
90270 CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
90271 9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
90272 RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
90273 JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
90274 +qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
90275 HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
90276 qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
90277 ++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
90278 Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
90279 guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
90280 OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
90281 CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
90282 lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
90283 rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
90284 hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
90285 9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
90286 -----END CERTIFICATE-----
90287
90288 SSL.com EV Root Certification Authority ECC
90289 ===========================================
90290 -----BEGIN CERTIFICATE-----
90291 MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
90292 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
90293 BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
90294 MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
90295 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
90296 LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
90297 BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
90298 3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
90299 BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
90300 5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
90301 N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
90302 m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
90303 -----END CERTIFICATE-----
90304
90305 GlobalSign Root CA - R6
90306 =======================
90307 -----BEGIN CERTIFICATE-----
90308 MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
90309 R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
90310 b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
90311 YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
90312 U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
90313 grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
90314 3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
90315 vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
90316 PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
90317 azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
90318 WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
90319 CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
90320 0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
90321 b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
90322 AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
90323 HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
90324 nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
90325 lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
90326 BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
90327 Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
90328 3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
90329 0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
90330 uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
90331 oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
90332 JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
90333 -----END CERTIFICATE-----
90334
90335 OISTE WISeKey Global Root GC CA
90336 ===============================
90337 -----BEGIN CERTIFICATE-----
90338 MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
90339 SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
90340 MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
90341 Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
90342 ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
90343 bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
90344 VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
90345 NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
90346 BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
90347 AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
90348 AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
90349 -----END CERTIFICATE-----
90350
90351 GTS Root R1
90352 ===========
90353 -----BEGIN CERTIFICATE-----
90354 MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
90355 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
90356 b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
90357 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi
90358 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx
90359 9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r
90360 aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW
90361 r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM
90362 LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly
90363 4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr
90364 06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
90365 wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om
90366 3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu
90367 JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
90368 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM
90369 BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
90370 d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv
90371 fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm
90372 ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b
90373 gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq
90374 4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr
90375 tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo
90376 pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0
90377 sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql
90378 CFF1pkgl
90379 -----END CERTIFICATE-----
90380
90381 GTS Root R2
90382 ===========
90383 -----BEGIN CERTIFICATE-----
90384 MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
90385 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
90386 b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
90387 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi
90388 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk
90389 k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo
90390 7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI
90391 m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm
90392 dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu
90393 ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz
90394 cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
90395 Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl
90396 aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy
90397 5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
90398 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM
90399 BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
90400 vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ
90401 +YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw
90402 c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da
90403 WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r
90404 n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu
90405 Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ
90406 7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs
90407 gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld
90408 o/DUhgkC
90409 -----END CERTIFICATE-----
90410
90411 GTS Root R3
90412 ===========
90413 -----BEGIN CERTIFICATE-----
90414 MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
90415 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
90416 UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
90417 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq
90418 hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU
90419 Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej
90420 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP
90421 0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0
90422 glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa
90423 KaqW04MjyaR7YbPMAuhd
90424 -----END CERTIFICATE-----
90425
90426 GTS Root R4
90427 ===========
90428 -----BEGIN CERTIFICATE-----
90429 MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
90430 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
90431 UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
90432 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq
90433 hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa
90434 6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj
90435 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV
90436 2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI
90437 N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x
90438 zPKwTdb+mciUqXWi4w==
90439 -----END CERTIFICATE-----
90440
90441 UCA Global G2 Root
90442 ==================
90443 -----BEGIN CERTIFICATE-----
90444 MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG
90445 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x
90446 NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU
90447 cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
90448 MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT
90449 oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV
90450 8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS
90451 h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o
90452 LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/
90453 R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe
90454 KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa
90455 4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc
90456 OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97
90457 8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
90458 BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo
90459 5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
90460 1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A
90461 Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9
90462 yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX
90463 c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo
90464 jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk
90465 bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x
90466 ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn
90467 RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A==
90468 -----END CERTIFICATE-----
90469
90470 UCA Extended Validation Root
90471 ============================
90472 -----BEGIN CERTIFICATE-----
90473 MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
90474 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u
90475 IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G
90476 A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi
90477 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs
90478 iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF
90479 Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu
90480 eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR
90481 59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH
90482 0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR
90483 el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv
90484 B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth
90485 WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS
90486 NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS
90487 3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL
90488 BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
90489 ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM
90490 aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4
90491 dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb
90492 +7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW
90493 F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi
90494 GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc
90495 GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi
90496 djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr
90497 dhh2n1ax
90498 -----END CERTIFICATE-----
90499
90500 Certigna Root CA
90501 ================
90502 -----BEGIN CERTIFICATE-----
90503 MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE
90504 BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ
90505 MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda
90506 MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz
90507 MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
90508 DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX
90509 stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz
90510 KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8
90511 JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16
90512 XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq
90513 4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej
90514 wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ
90515 lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI
90516 jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/
90517 /TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
90518 HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
90519 1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy
90520 dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h
90521 LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl
90522 cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt
90523 OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP
90524 TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq
90525 7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3
90526 4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd
90527 8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS
90528 6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY
90529 tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
90530 aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
90531 E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
90532 -----END CERTIFICATE-----
90533
90534 emSign Root CA - G1
90535 ===================
90536 -----BEGIN CERTIFICATE-----
90537 MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
90538 MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
90539 ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
90540 ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
90541 aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
90542 IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
90543 LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
90544 cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
90545 DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
90546 6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
90547 hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
90548 MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
90549 vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
90550 NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
90551 +Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
90552 U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
90553 iN66zB+Afko=
90554 -----END CERTIFICATE-----
90555
90556 emSign ECC Root CA - G3
90557 =======================
90558 -----BEGIN CERTIFICATE-----
90559 MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
90560 A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
90561 MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
90562 MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
90563 ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
90564 RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
90565 58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
90566 MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
90567 AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
90568 CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
90569 jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
90570 -----END CERTIFICATE-----
90571
90572 emSign Root CA - C1
90573 ===================
90574 -----BEGIN CERTIFICATE-----
90575 MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
90576 EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
90577 Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
90578 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
90579 ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
90580 ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
90581 Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
90582 OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
90583 I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
90584 lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
90585 XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
90586 ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
90587 /6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
90588 NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
90589 wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
90590 BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
90591 -----END CERTIFICATE-----
90592
90593 emSign ECC Root CA - C3
90594 =======================
90595 -----BEGIN CERTIFICATE-----
90596 MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
90597 A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
90598 Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
90599 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
90600 ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
90601 6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
90602 SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
90603 B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
90604 MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
90605 ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
90606 -----END CERTIFICATE-----
90607
90608 Hongkong Post Root CA 3
90609 =======================
90610 -----BEGIN CERTIFICATE-----
90611 MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
90612 A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
90613 Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
90614 MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
90615 bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
90616 SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
90617 iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
90618 jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
90619 5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
90620 sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
90621 0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
90622 JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
90623 y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
90624 +bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
90625 xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
90626 AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
90627 i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
90628 AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
90629 W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
90630 y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
90631 +BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
90632 eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
90633 9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
90634 nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
90635 hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
90636 60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
90637 dBb9HxEGmpv0
90638 -----END CERTIFICATE-----
90639 <?php
90640
90641 if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
90642     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
90643 }
90644
90645 setlocale(LC_ALL, 'C');
90646 require __DIR__.'/../src/bootstrap.php';
90647
90648 use Composer\Console\Application;
90649 use Composer\XdebugHandler\XdebugHandler;
90650
90651 error_reporting(-1);
90652
90653 // Restart without xdebug
90654 $xdebug = new XdebugHandler('Composer', '--ansi');
90655 $xdebug->check();
90656 unset($xdebug);
90657
90658 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '4.0', '>=')) {
90659     echo 'HHVM 4.0 has dropped support for Composer, please use PHP instead. Aborting.'.PHP_EOL;
90660     exit(1);
90661 }
90662
90663 if (function_exists('ini_set')) {
90664     @ini_set('display_errors', 1);
90665
90666     $memoryInBytes = function ($value) {
90667         $unit = strtolower(substr($value, -1, 1));
90668         $value = (int) $value;
90669         switch($unit) {
90670             case 'g':
90671                 $value *= 1024;
90672                 // no break (cumulative multiplier)
90673             case 'm':
90674                 $value *= 1024;
90675                 // no break (cumulative multiplier)
90676             case 'k':
90677                 $value *= 1024;
90678         }
90679
90680         return $value;
90681     };
90682
90683     $memoryLimit = trim(ini_get('memory_limit'));
90684     // Increase memory_limit if it is lower than 1.5GB
90685     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
90686         @ini_set('memory_limit', '1536M');
90687     }
90688     // Set user defined memory limit
90689     if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
90690         @ini_set('memory_limit', $memoryLimit);
90691     }
90692     unset($memoryInBytes, $memoryLimit);
90693 }
90694
90695 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
90696
90697 // run the command application
90698 $application = new Application();
90699 $application->run();
90700
90701 Copyright (c) Nils Adermann, Jordi Boggiano
90702
90703 Permission is hereby granted, free of charge, to any person obtaining a copy
90704 of this software and associated documentation files (the "Software"), to deal
90705 in the Software without restriction, including without limitation the rights
90706 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
90707 copies of the Software, and to permit persons to whom the Software is furnished
90708 to do so, subject to the following conditions:
90709
90710 The above copyright notice and this permission notice shall be included in all
90711 copies or substantial portions of the Software.
90712
90713 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
90714 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
90715 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
90716 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
90717 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90718 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
90719 THE SOFTWARE.
90720
90721 Ã4\ 5+½À\vcZ¿\*t¨ç\90¢¯Ú|\ 2\0\0\0GBMB