]> git.mxchange.org Git - friendica.git/blob - bin/composer.phar
test again
[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 -\96\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Èi\0\0lY×^Èi\0\0åOÖƤ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.phpú\1a\0\0lY×^ú\1a\0\05\ 5\ 1̤\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpç\13\0\0lY×^ç\13\0\0³\9bî\1d¤\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpØ\ 2\0\0lY×^Ø\ 2\0\0ö÷;\87¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpä\14\0\0lY×^ä\14\0\0Õ\15­\7f¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÜ\v\0\0lY×^Ü\v\0\0\1a\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpg\19\0\0lY×^g\19\0\0öN\ 6\ 1\0\0\0\0\0\01\0\0\0src/Composer/Command/CheckPlatformReqsCommand.php\7f\ f\0\0lY×^\7f\ f\0\0\8d\84\7fǤ\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php½\ 5\0\0lY×^½\ 5\0\0°\ 2\b\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.phpÎQ\0\0lY×^ÎQ\0\0xþÎ\f¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.phpª;\0\0lY×^ª;\0\0ò\e×h¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.phpø\ 2\0\0lY×^ø\ 2\0\0ªe\11á¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpøO\0\0lY×^øO\0\0:>ñs¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.phpã\v\0\0lY×^ã\v\0\0© ]\86¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.php  \0\0lY×^  \0\0X?!\93¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/FundCommand.php,
28 \0\0lY×^,
29 \0\0ï\8e¶9¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpz       \0\0lY×^z \0\0³çå?¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.php\ 4\ f\0\0lY×^\ 4\ f\0\0qLB\8e¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.phpçU\0\0lY×^çU\0\0\83ä\1d\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpT\14\0\0lY×^T\14\0\0Þùõ\9b¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.phpò\ e\0\0lY×^ò\ e\0\0´\18È\1c¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php\ f\f\0\0lY×^\ f\f\0\0ا\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.php\12\ 3\0\0lY×^\12\ 3\0\0_¤éS¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.phpá\18\0\0lY×^á\18\0\0½í\9d\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php¯)\0\0lY×^¯)\0\0!`\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php³\ f\0\0lY×^³\ f\0\0·\7fü¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.php¯\ 5\0\0lY×^¯\ 5\0\0?=\10Ѥ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpU      \0\0lY×^U \0\0\85ß\ f\ f¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.php\ 46\0\0lY×^\ 46\0\0\ f¿æ÷¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.php\83\82\0\0lY×^\83\82\0\0O\91\8f ¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.phpP\16\0\0lY×^P\16\0\0:±çú¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php\13\ e\0\0lY×^\13\ e\0\0ò\82Bɤ\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.phpñ#\0\0lY×^ñ#\0\0p\F\19¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.phpk\14\0\0lY×^k\14\0\0y\828K¤\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.php~\v\0\0lY×^~\v\0\0\96ãÀ\ f¤\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.php×$\0\0lY×^×$\0\0ÝܾS¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0lY×^\ e\ 2\0\0³\f[/¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php¹\14\0\0lY×^¹\14\0\0\94\©-¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.phpY8\0\0lY×^Y8\0\0·î\80²¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0lY×^3\ 6\0\0Ú\81Eu¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.php6\10\0\0lY×^6\10\0\0à\95\f\9e¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0lY×^\ 2\17\0\0õÝv\7f¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.phpµ\ 3\0\0lY×^µ\ 3\0\0\19᫤¤\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0lY×^C\ 2\0\0´\õ*¤\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0lY×^÷\ 2\0\0ïÎà÷¤\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0lY×^ý\ 2\0\0\193#\86¤\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0lY×^Ó\0\0\0Ùâ&ä¤\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0lY×^¹\ 1\0\0&¢e
30 ¤\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0lY×^I\ 2\0\0FûÂɤ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.php'\ 4\0\0lY×^'\ 4\0\0Qúɯ¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0lY×^­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php¯"\0\0lY×^¯"\0\0\r ¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.phpú\17\0\0lY×^ú\17\0\0\16]D5¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0lY×^\83\ 4\0\0åVP\84¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php?\19\0\0lY×^?\19\0\0¬\91\9cü¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php\18\ 5\0\0lY×^\18\ 5\0\0tZÅɤ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
31 \0\0lY×^ª
32 \0\0\82\e¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpÊ\1e\0\0lY×^Ê\1e\0\0D¦õZ¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\11\ 6\0\0lY×^\11\ 6\0\0\9bCü$¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0lY×^i\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0lY×^á\ 6\0\0\89rôv¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.php\ 5\ 4\0\0lY×^\ 5\ 4\0\0\8fGd7¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.phpf:\0\0lY×^f:\0\0Nø1´¤\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\99\ 1\0\0lY×^\99\ 1\0\0X\12g6¤\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpô\a\0\0lY×^ô\a\0\0×|Ŧ¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.php×\13\0\0lY×^×\13\0\0Vmì\9f¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.phpÆ      \0\0lY×^Æ \0\0G s0¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0lY×^Ì\0\0\0¯à¨¿¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.php`\15\0\0lY×^`\15\0\0#ÏX\14¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0lY×^Ê\ 1\0\0gs!l¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0lY×^Ñ\0\0\0\9c¿¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.phpG\1c\0\0lY×^G\1c\0\0ä\11OФ\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
33 \ 1\0\0lY×^
34 \ 1\0\0.-\1e\8b¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php\82\v\0\0lY×^\82\v\0\0Ü\81Ii¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php³6\0\0lY×^³6\0\0¦Ü(9¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0lY×^ó\ 6\0\0}Úo¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php\94\b\0\0lY×^\94\b\0\0ßis̤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpT\15\0\0lY×^T\15\0\0®\1f\18\96¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0lY×^u\e\0\0z\84\15\87¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.php\9e\a\0\0lY×^\9e\a\0\0Öüñ9¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0lY×^å\0\0\0ÞÉ\1fç¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0lY×^\9e\a\0\06      3U¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpM\14\0\0lY×^M\14\0\0\1a\v!`¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0lY×^ã\0\0\0Í\92X?¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0lY×^=\ 2\0\0ZÎÈÞ¤\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0lY×^Ô\0\0\0`§ôö¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php¡\16\0\0lY×^¡\16\0\0(   à>¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0lY×^§\ 4\0\0W$;á¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.php\81\15\0\0lY×^\81\15\0\0®Û#s¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0lY×^ \ 2\0\0±\99jï¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.php\07\0\0lY×^\07\0\0\97Øa¡¤\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0lY×^©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0lY×^v\0\0\0wZ8S¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0lY×^f\0\0\0ËíM\9d¤\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.php_=\0\0lY×^_=\0\0x"\10Ť\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\95\12\0\0lY×^\95\12\0\0\ eìÏA¤\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php¾\ 6\0\0lY×^¾\ 6\0\0X~d\1e¤\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php\1f\19\0\0lY×^\1f\19\0\0\1füw·¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0lY×^ì\ 5\0\0\0Õ\9d\ e¤\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0lY×^À\ 4\0\0F`sʤ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.phpè¡\0\0lY×^è¡\0\0â\9aL\92¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php
35 \12\0\0lY×^
36 \12\0\0t¤{ø¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0lY×^Ë\0\0\0À5\9a¨¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0lY×^-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0lY×^\ e\ 6\0\0lÔzi¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0lY×^Þ\0\0\0ì\9f@G¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0lY×^ã\ 2\0\0^\83\93ʤ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php%\14\0\0lY×^%\14\0\0\f»\8f̤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.phpÊ\a\0\0lY×^Ê\a\0\0Ùti·¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0lY×^+\ 5\0\0À·M}¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0lY×^e\ 3\0\0;° \1a¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0lY×^¸\ 1\0\0dbØs¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpø\f\0\0lY×^ø\f\0\0\95\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0lY×^¢\a\0\0È\82¶Ñ¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php¢\ 6\0\0lY×^¢\ 6\0\0L´a:¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0lY×^\1d\ 6\0\0*0@P¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php:\a\0\0lY×^:\a\0\0\82´UV¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.phpL\15\0\0lY×^L\15\0\0\ers\12¤\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.phpb\ 6\0\0lY×^b\ 6\0\0\12ÝN\9a¤\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.php\934\0\0lY×^\934\0\0Í®\ 5\9a¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0lY×^\\ 1\0\0.Xóܤ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.phpî\17\0\0lY×^î\17\0\0-\81×&¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php      \ 2\0\0lY×^ \ 2\0\0yY+¦¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0lY×^Þ\ 5\0\0\f²²¹¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.phpÝ\f\0\0lY×^Ý\f\0\0í<´B¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0lY×^\a\ 1\0\0ñ´>\v¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0lY×^\96\ 6\0\0y¶=Ƥ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0lY×^\1f\ 1\0\0\8bSZ0¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpr\ 3\0\0lY×^r\ 3\0\03\91Mh¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\v\ 5\0\0lY×^\v\ 5\0\0\r\95¦S¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php?\ 6\0\0lY×^?\ 6\0\0®\97      u¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.phpX\ 5\0\0lY×^X\ 5\0\0¤k\9d\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php\11\ e\0\0lY×^\11\ e\0\0D|\9fȤ\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Comparer/Comparer.phpR\b\0\0lY×^R\b\0\0Ïسî¤\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.php¦\a\0\0lY×^¦\a\0\0p[\ 3Ö¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.php\e\ 2\0\0lY×^\e\ 2\0\0Î\12«>¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpb\f\0\0lY×^b\f\0\0s\95°\9b¤\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0lY×^\88\ 5\0\0å¶Y«¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0lY×^\82\ 1\0\0\ eé~\8b¤\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0lY×^d\ 1\0\0¤ôLn¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0lY×^\82\ 1\0\0ób`ý¤\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0lY×^i\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0lY×^X\ 1\0\0\ 2}`y¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.php½\1e\0\0lY×^½\1e\0\0c
37 @\8f¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0lY×^E\ 2\0\0xb\13¾¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0lY×^ù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0lY×^²\0\0\0¦}úΤ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.phpë\19\0\0lY×^ë\19\0\0Û\8a\v\9b¤\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.php.B\0\0lY×^.B\0\0åpHD¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php\r"\0\0lY×^\r"\0\0mW\ f\8f¤\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0lY×^É\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php\\b\0\0lY×^\\b\0\0xåp¨¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f  \0\0lY×^\1f \0\0      _\80ø¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0lY×^\11\ 5\0\0\ 2\8eÎ_¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0lY×^¹\ 3\0\0"maV¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpì!\0\0lY×^ì!\0\0X\ e]Ô¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.php¥\ 5\0\0lY×^¥\ 5\0\0ô´\16à¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.php¨\ e\0\0lY×^¨\ e\0\0ý5½,¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0lY×^W\0\0\0æ_¨1¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0lY×^\97\0\0\0ûOâ>¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0lY×^\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0lY×^â\ 2\0\0³ÆÇW¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpö\0\0\0lY×^ö\0\0\0á1=z¤\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0lY×^ô\0\0\0)'*ؤ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.phpª$\0\0lY×^ª$\0\0m\89\83ä¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Plugin/PreCommandRunEvent.phpõ\ 1\0\0lY×^õ\ 1\0\0:ðd\1e¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0lY×^`\ 2\0\0\09-Τ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0lY×^\1e\ 5\0\0'.³è¤\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php¬\ e\0\0lY×^¬\ e\0\0\19\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.phpí\b\0\0lY×^í\b\0\0q9OS¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php\8a\ f\0\0lY×^\8a\ f\0\0\13äÝ÷¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php0U\0\0lY×^0U\0\0Ã7L\86¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0lY×^;\b\0\0¤¯S\1f¤\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0lY×^\85\0\0\0±\9f_\1c¤\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.phpp\ 5\0\0lY×^p\ 5\0\0#\18ù\7f¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0lY×^£\0\0\0/ö~>¤\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0lY×^£\0\0\0V
38 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0lY×^\87\0\0\0\18£9p¤\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0lY×^n\0\0\0à\93ë\98¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0lY×^j\ 3\0\0¥ôò̤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.php\97\ e\0\0lY×^\97\ e\0\0ïãc\0¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0lY×^I\ 5\0\0c\b6³¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0lY×^Ä\ 1\0\0:T*ɤ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0lY×^í\ 6\0\0?ÈYT¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.php®        \0\0lY×^® \0\0\99ÖÛú¤\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0lY×^& \0\0òUb\b¤\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0lY×^q\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0lY×^q\ 1\0\0fºTò¤\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0lY×^\85\16\0\0÷$Li¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0lY×^°\ 3\0\0\9f\r¸\f¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ReleaseInfo.php\92\ 1\0\0lY×^\92\ 1\0\0o\93\8aä\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0lY×^ª\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php;!\0\0lY×^;!\0\0äö9\a¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php\13\13\0\0lY×^\13\13\0\0è0\e¹¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0lY×^Û\ 1\0\0\92\11âÁ¤\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.phpM\v\0\0lY×^M\v\0\0<(;\8c¤\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0lY×^o\0\0\0pÕ«ª¤\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.php\95 \0\0lY×^\95 \0\0$©Rç¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php³\13\0\0lY×^³\13\0\0ÐCk\ 3¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpë\ 5\0\0lY×^ë\ 5\0\0\9c´½X¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.php\90\12\0\0lY×^\90\12\0\0ù\13\96\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.php©4\0\0lY×^©4\0\0\14(ñ£¤\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.php¢*\0\0lY×^¢*\0\0\1c\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpå\ 5\0\0lY×^å\ 5\0\0@)\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpB\12\0\0lY×^B\12\0\0»\7f\83î¤\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.phpù        \0\0lY×^ù \0\0&½tÙ¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php¤\1c\0\0lY×^¤\1c\0\0\1e\11\1f\f¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
39 \0\0lY×^æ
40 \0\0eׯ-¤\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0lY×^÷\ 2\0\0ÇX[\89¤\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.phpØ,\0\0lY×^Ø,\0\0c÷Mð¤\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/VersionCacheInterface.php\94\0\0\0lY×^\94\0\0\0A?Rï¤\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0lY×^\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0lY×^\89\ 1\0\0\91/sï¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0lY×^W\0\0\0£VZt¤\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpº\ 4\0\0lY×^º\ 4\0\0ò\9d»¤¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0lY×^\9c\0\0\0§ÿÉ\r¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0lY×^P\ 4\0\0\87\8f\ 4¶¤\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0lY×^\9d\ 1\0\0\vîÊN¤\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpi\ 6\0\0lY×^i\ 6\0\0\92\1c¤\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0lY×^Ë\ 3\0\0>zx\96¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php*\15\0\0lY×^*\15\0\0,L\9a\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0lY×^±\ 4\0\0­½øؤ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.php÷\13\0\0lY×^÷\13\0\0v\95Í\ 4¤\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php»\ 4\0\0lY×^»\ 4\0\0O\9brk¤\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.phpm/\0\0lY×^m/\0\0Çë¡ú¤\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.php\98/\0\0lY×^\98/\0\0Í´î\9e¤\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.php|\r\0\0lY×^|\r\0\0`0tü¤\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php¬\r\0\0lY×^¬\r\0\0B3\vë¤\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Util/Hg.php¾\a\0\0lY×^¾\a\0\0\f\9d¤\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.phph\ 2\0\0lY×^h\ 2\0\0;F\b\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php|\14\0\0lY×^|\14\0\0¸|ää¤\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Util/PackageSorter.phpÞ\ 5\0\0lY×^Þ\ 5\0\0ê×ìY¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php¸2\0\0lY×^¸2\0\0Ás&}¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0lY×^ü\ 4\0\0s­fç¤\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.php$\r\0\0lY×^$\r\0\0¨Nó\1e¤\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.php-r\0\0lY×^-r\0\0(\\8dÀ¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpé\ 2\0\0lY×^é\ 2\0\0\93Vjf¤\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0lY×^\ 3\ 1\0\0¾7
41 ñ¤\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.php\ 6\10\0\0lY×^\ 6\10\0\0\85ù¤\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php,\14\0\0lY×^,\14\0\0Ì\r\9eĤ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpL
42 \0\0lY×^L
43 \0\0"\fi\1e¤\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Url.php£\a\0\0lY×^£\a\0\03\9cÉܤ\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Zip.php³\ 5\0\0lY×^³\ 5\0\0ä\8aΪ¤\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.phpð\ 1\0\0lY×^ð\ 1\0\0zÓf~¤\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0lY×^¹\ 1\0\0\15I}\9c¤\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.php\934\0\0lY×^\934\0\0²z\8d\96¤\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0lY×^ð\ f\0\0\81GÐà¤\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.jsonM\9d\0\0lY×^M\9d\0\0\ e\15_Τ\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.jsonä
44 \0\0lY×^ä
45 \0\0P\95ʪ¤\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.json\1c\9e\0\0lY×^\1c\9e\0\0¿T\87î¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Resources/bin/hiddeninput.exe\0$\0\0lY×^\0$\0\0\95\8d¥v¤\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php=X\0\0lY×^=X\0\0\8f S\92¤\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.phpî"\0\0lY×^î"\0\0x°jÕ¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpØ\a\0\0lY×^Ø\a\0\0¦Ú-:¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0lY×^Z\b\0\0»w\ 4\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpé\0\0\0lY×^é\0\0\0RÛÔe¤\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpÐ\b\0\0lY×^Ð\b\0\0\99\8e5°¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\8f\a\0\0lY×^\8f\a\0\0¿N\ f\95¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0lY×^ü\0\0\0±Q\aµ¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpÜ\r\0\0lY×^Ü\r\0\0\9dɤ\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¶\ e\0\0lY×^¶\ e\0\0·Ô;ݤ\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php¼\1e\0\0lY×^¼\1e\0\0òç\ 6\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ 1\1c\0\0lY×^\ 1\1c\0\0\7fb{<¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php°\ 1\0\0lY×^°\ 1\0\0\a!\0Ȥ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0lY×^Å\ 2\0\0ÒxÛ\¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0lY×^\12\ 3\0\0á\162é¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0lY×^z\ 2\0\0³,îL¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0lY×^Ô\ 1\0\0È÷ L¤\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0lY×^f\0\0\0¡ABª¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0lY×^¦\0\0\0Ö̽Z¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0lY×^¦\0\0\0\13Ë×H¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0lY×^\92\0\0\0ÍO\e¤\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/console/Exception/RuntimeException.php\96\0\0\0lY×^\96\0\0\0Ùí,6¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php6\ e\0\0lY×^6\ e\0\0?=¨\ 4¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0lY×^\8c\ 1\0\0òññÀ¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpF\10\0\0lY×^F\10\0\0\1d𦴤\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\84\ 1\0\0lY×^\84\ 1\0\0÷½\10\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.php@\ 5\0\0lY×^@\ 5\0\0G¨ýU¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpy\b\0\0lY×^y\b\0\0Ì8ÆФ\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpw\ 5\0\0lY×^w\ 5\0\0\ 1\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.php\ 3\1f\0\0lY×^\ 3\1f\0\0¹ÜÃ_¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpd\ 4\0\0lY×^d\ 4\0\0§×,¸¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php«\a\0\0lY×^«\a\0\0!\90§\97¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpå\0\0\0lY×^å\0\0\0\1f\8a \18¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÊ\a\0\0lY×^Ê\a\0\0áÏW"¤\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0lY×^c\ 1\0\0\ 6Ìø\83¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÓ      \0\0lY×^Ó \0\0©w\82\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phpl%\0\0lY×^l%\0\0 díÛ¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php]\e\0\0lY×^]\e\0\0ù»\89\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpN\14\0\0lY×^N\14\0\0ÿ§³l¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.phpl\1d\0\0lY×^l\1d\0\0Nt\bó¤\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.php\96
46 \0\0lY×^\96
47 \0\0-\fØ\1a¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.phpÄ*\0\0lY×^Ä*\0\0¾\99ØT¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\81\ 3\0\0lY×^\81\ 3\0\0å\16V^¤\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\ e\f\0\0lY×^\ e\f\0\0\9b\99¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÊ\0\0\0lY×^Ê\0\0\0az\1f\1c¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php 
48 \0\0lY×^ 
49 \0\0_ÍI"¤\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\ f\16\0\0lY×^\ f\16\0\0×ö\86\9b¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php)\v\0\0lY×^)\v\0\0¥Ñ\ 6\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.php£\v\0\0lY×^£\v\0\0\13f¡?¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\12\ 6\0\0lY×^\12\ 6\0\0D\r£\ 6¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\98\0\0\0lY×^\98\0\0\0­\ fO°¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\86\19\0\0lY×^\86\19\0\0¤U)¤¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php£\ 3\0\0lY×^£\ 3\0\0ÆB\8c\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\14\f\0\0lY×^\14\f\0\0\¢Ü=¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\9a\ 6\0\0lY×^\9a\ 6\0\0\9eµ\rè¤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0lY×^)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php0    \0\0lY×^0 \0\0\85\8d\r¸¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.php_\ 1\0\0lY×^_\ 1\0\0\8b >P¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.php±\a\0\0lY×^±\a\0\0nì!f¤\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpà\0\0\0lY×^à\0\0\0\87\86Æʤ\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0lY×^Ï\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\98  \0\0lY×^\98 \0\00p\ 4\b¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\17\ 3\0\0lY×^\17\ 3\0\0\0ì\ 6\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.php\9d\ 6\0\0lY×^\9d\ 6\0\0Ä\92Oç¤\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpx
50 \0\0lY×^x
51 \0\0W\16\80\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpè\ 2\0\0lY×^è\ 2\0\0/\1dÔ\8f¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.phpΠ    \0\0lY×^Π\0\0lF\ f\10¤\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpæ\ f\0\0lY×^æ\ f\0\0¼XÒA¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php\\ 5\0\0lY×^\\ 5\0\0wפ\ 4¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÏ\ 3\0\0lY×^Ï\ 3\0\0&nÅѤ\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.phpä\1f\0\0lY×^ä\1f\0\0­å (¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÏ\ 5\0\0lY×^Ï\ 5\0\0s\9e9i¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.phpª\ 6\0\0lY×^ª\ 6\0\0¬K\f\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0lY×^t\ 1\0\0=\0hܤ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.php,\ 3\0\0lY×^,\ 3\0\0Ë~\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.phpµ\1d\0\0lY×^µ\1d\0\01rEÓ¤\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\1dH\0\0lY×^\1dH\0\0¹:D#¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\96\ 1\0\0lY×^\96\ 1\0\0i\89æô¤\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0lY×^\98\ 1\0\0-
52 d2¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0lY×^\ 2\ 1\0\0®+Ãê¤\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.php\ e\a\0\0lY×^\ e\a\0\0\e\17\99Ĥ\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpW\ 2\0\0lY×^W\ 2\0\0?àèK¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php¼\16\0\0lY×^¼\16\0\0\11\15\fפ\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0lY×^~\0\0\0ë¨oâ¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\9a\ 1\0\0lY×^\9a\ 1\0\0\81ñJÀ¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\98\ 1\0\0lY×^\98\ 1\0\0nöêؤ\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php)3\0\0lY×^)3\0\0\81h5=¤\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.phpA\12\0\0lY×^A\12\0\0Ϥ¹l¤\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0lY×^\ 3\ 1\0\0ĹBV¤\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpx\b\0\0lY×^x\b\0\0~ò"\7f¤\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpO\ 5\0\0lY×^O\ 5\0\0\8d\9e¦*¤\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0lY×^)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0lY×^i\0\0\0$ ÿ\9b¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0lY×^¼\ 1\0\0pí\¶¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0lY×^\87\ 1\0\0\80ü#Ѥ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0lY×^¦\0\0\0jÙwM¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.phpc4\0\0lY×^c4\0\0\8b×@þ¤\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0lY×^)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.phpö\ 5\0\0lY×^ö\ 5\0\0\9fZµ1¤\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0lY×^\\v\0\0h\19\88\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\8f\19\0\0lY×^\8f\19\0\0HC\80\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php\9b\ 3\0\0lY×^\9b\ 3\0\0M\aþ\e¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php3\a\0\0lY×^3\a\0\075$·¤\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0lY×^\15\a\0\0\9f\1c`]¤\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0lY×^ô\a\0\0Þdè;¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8d\ 3\0\0lY×^\8d\ 3\0\0¾ü\9cµ¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php#\ 3\0\0lY×^#\ 3\0\0\16°\1fΤ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php|\ 3\0\0lY×^|\ 3\0\0ITÇͤ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0lY×^\84\0\0\0½¾s\9c¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¬\ 2\0\0lY×^¬\ 2\0\0w\1e\18\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0lY×^\84\0\0\0\1cGz-¤\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0lY×^)\ 1\0\0x\1f§e¤\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpº\ 2\0\0lY×^º\ 2\0\0\98þ\15\98¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0lY×^\a\ 6\0\0i¥:Ť\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpf\ 4\0\0lY×^f\ 4\0\0DÞcj¤\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 4\ f\0\0lY×^\ 4\ f\0\0ü(ÃϤ\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0lY×^Í\ 1\0\0\p4\86¤\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.phpc.\0\0lY×^c.\0\0:\885g¤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpL\ 5\0\0lY×^L\ 5\0\0jÍ9פ\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php]\ 2\0\0lY×^]\ 2\0\0ÎoÅƤ\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpx\ 2\0\0lY×^x\ 2\0\0\ fô\ 3\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpî\ 1\0\0lY×^î\ 1\0\0üÍ\9d\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpí\ 5\0\0lY×^í\ 5\0\0n\ 5õH¤\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php#\ 6\0\0lY×^#\ 6\0\0G?T½¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpZ\ 2\0\0lY×^Z\ 2\0\0(\1a&ø¤\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0lY×^5\ 2\0\0\9aí\1f\14¤\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0lY×^r\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0lY×^Ã\ 2\0\0\9a+µÞ¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php-\ 5\0\0lY×^-\ 5\0\0ºÎÒ_¤\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÐ\ 1\0\0lY×^Ð\ 1\0\0\12\82\b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\15   \0\0lY×^\15 \0\0ë]í»¤\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpe\ 2\0\0lY×^e\ 2\0\0\9f\92áé¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php+\ 6\0\0lY×^+\ 6\0\0õÝË ¤\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0lY×^)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.php>\v\0\0lY×^>\v\0\0_~u\f¤\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpr\ 4\0\0lY×^r\ 4\0\0þ\1dpN¤\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.php\ 6\ 3\0\0lY×^\ 6\ 3\0\0þ\0íù¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/polyfill-ctype/Ctype.phpH   \0\0lY×^H \0\0³\9dÕݤ\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/polyfill-ctype/LICENSE)\ 4\0\0lY×^)\ 4\0\0´`e0¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/polyfill-ctype/bootstrap.phpä\ 4\0\0lY×^ä\ 4\0\0\97o\ 6£¤\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0lY×^)\ 4\0\0\1f\93\ª¤\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.php\80G\0\0lY×^\80G\0\0É\96з¤\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php÷@\0\0lY×^÷@\0\0õ\10\9eؤ\ 1\0\0\0\0\0\0F\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpã\17\0\0lY×^ã\17\0\0öy_\95¤\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpfA\0\0lY×^fA\0\0Úf\94ߤ\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php)\18\0\0lY×^)\18\0\0\11p¼B¤\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0lY×^f\0\0\0]ö>T¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0lY×^¨\0\0\0ÐÀ+_¤\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0lY×^\94\0\0\0 ³ãñ¤\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0lY×^x\ 3\0\0¨Ìzy¤\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0lY×^\1f\ 4\0\0\7fï\ e«¤\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0lY×^\98\0\0\0¢\eØ:¤\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9d\ 4\0\0lY×^\9d\ 4\0\0ûus\80¤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0lY×^)\ 4\0\0NUN½¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpÏ\ 4\0\0lY×^Ï\ 4\0\0Î%h\1c¤\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpü\ 3\0\0lY×^ü\ 3\0\0\87jûü¤\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php½\a\0\0lY×^½\a\0\0æ\18\86\ 1¤\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0lY×^D\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.php>\b\0\0lY×^>\b\0\0ª\95ir¤\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.phpp\f\0\0lY×^p\f\0\0âU~ɤ\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php·R\0\0lY×^·R\0\0\8a\18`Õ¤\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpâ
53 \0\0lY×^â
54 \0\0\86\1eM¶¤\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpQ\ 6\0\0lY×^Q\ 6\0\0b-$m¤\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0lY×^"\ 4\0\0a\83sy¤\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0lY×^*\ 1\0\0\19\95pñ¤\ 1\0\0\0\0\0\05\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php_2\0\0lY×^_2\0\0\ 3\8a\96\ 1\0\0\0\0\0\00\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php'\11\0\0lY×^'\11\0\0T×5ã¤\ 1\0\0\0\0\0\0;\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php\1e\ 1\0\0lY×^\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\0lY×^>\0\0\0ÿq\9f\9f¤\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0lY×^ \ 4\0\0ºç\ 6©¤\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0lY×^ñ\ 1\0\0f\e\12\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php¡      \0\0lY×^¡ \0\0\86wÌl¤\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php\8f
55 \0\0lY×^\8f
56 \0\0ÍèÓ¯¤\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php§\r\0\0lY×^§\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\0lY×^¼\ 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\0lY×^]\ 3\0\0V\8eU<¤\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.phpã\f\0\0lY×^ã\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\0lY×^\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\0lY×^\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\0lY×^Ã\11\0\0©Å¼x¤\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php0 \0\0lY×^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\0lY×^\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\0lY×^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\0lY×^\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\0lY×^\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\0lY×^&\ f\0\04\98©T¤\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.phpS"\0\0lY×^S"\0\0¼¾õ:¤\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0lY×^è\ 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\0lY×^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\0lY×^\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\0lY×^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\0lY×^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\0lY×^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\0lY×^w\0\0\0N-ò[¤\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0lY×^Þ\ 2\0\0\r
57 ¤\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0lY×^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\0lY×^\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\0lY×^\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\0lY×^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\0lY×^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\0lY×^þ\ 5\0\0M\8f\84õ¤\ 1\0\0\0\0\0\0;\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php \ 2\0\0lY×^ \ 2\0\0f4÷³¤\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\9c\r\0\0lY×^\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\0lY×^\ 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\0lY×^á\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\0lY×^¥\ 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\0lY×^%\ 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\0lY×^,\ 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\0lY×^®\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\0lY×^\ 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\0lY×^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\0lY×^\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\0lY×^\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpv\ 5\0\0lY×^v\ 5\0\0õÍ\ 5\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0lY×^\1c\ 4\0\0\ 6Bhí¤\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpH\14\0\0lY×^H\14\0\0Í\89T\ 4¤\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0lY×^\1c\ 4\0\0\ 6Bhí¤\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0lY×^\ 2\ 4\0\0wl\83ï¤\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.phpî\ 2\0\0lY×^î\ 2\0\0Õ­w-¤\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.php\92\f\0\0lY×^\92\f\0\0I\ f&â¤\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0lY×^ß\0\0\00C,\87¤\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpä\ 1\0\0lY×^ä\ 1\0\0ïõ\82³¤\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php,\ 5\0\0lY×^,\ 5\0\0\ 2\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.php\82\ 6\0\0lY×^\82\ 6\0\0?n\1aݤ\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¸*\0\0lY×^¸*\0\0GLÇí¤\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0lY×^\1c\ 4\0\0*!^`¤\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.phpR\1e\0\0lY×^R\1e\0\0!Ã%\0¤\ 1\0\0\0\0\0\0&\0\0\0vendor/composer/xdebug-handler/LICENSE)\ 4\0\0lY×^)\ 4\0\0#Ô;^¤\ 1\0\0\0\0\0\00\0\0\0vendor/composer/xdebug-handler/src/PhpConfig.php´\ 2\0\0lY×^´\ 2\0\0*D\92\0¤\ 1\0\0\0\0\0\0.\0\0\0vendor/composer/xdebug-handler/src/Process.phpp   \0\0lY×^p \0\0i,i\91¤\ 1\0\0\0\0\0\0-\0\0\0vendor/composer/xdebug-handler/src/Status.php\ f
58 \0\0lY×^\ f
59 \0\0$\9fv-¤\ 1\0\0\0\0\0\04\0\0\0vendor/composer/xdebug-handler/src/XdebugHandler.php:!\0\0lY×^:!\0\0 ðU\r¤\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0lY×^=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0lY×^;\ 4\0\0ñ>3[¤\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0lY×^`\0\0\0 \88X1¤\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0lY×^û\0\0\0jðñ8¤\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0lY×^|\0\0\0$\13£\88¤\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0lY×^§\0\0\0T½úB¤\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÈ\ 2\0\0lY×^È\ 2\0\0\9a\1fx\1d¤\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpk\ 4\0\0lY×^k\ 4\0\0£}\89\92¤\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php \0\0\0lY×^ \0\0\0ÆDi¯¤\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/Test/DummyTest.phpp\0\0\0lY×^p\0\0\0\1a\15Î\ 5¤\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php \r\0\0lY×^ \r\0\0\1d$/Ò¤\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/Test/TestLogger.php<\b\0\0lY×^<\b\0\0þ(åI¤\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0lY×^\82\0\0\0®WÍ.¤\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0lY×^d\0\0\0Z¡¦H¤\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php÷\ 4\0\0lY×^÷\ 4\0\0Å*\9a\16¤\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0lY×^d\0\0\0Z¡¦H¤\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.php\1f\ 1\0\0lY×^\1f\ 1\0\0¥\0 ®¤\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpL\a\0\0lY×^L\a\0\0«ñ¹ô¤\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php§
60 \0\0lY×^§
61 \0\0¦é\8b¤¤\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php¨\18\0\0lY×^¨\18\0\0xää`¤\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pemÇi\ 3\0lY×^Çi\ 3\0\9f\87¤\ 1\0\0\0\0\0\0\f\0\0\0bin/composerÊ\ 6\0\0lY×^Ê\ 6\0\0\a\8f4K¤\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0lY×^.\ 4\0\0 Õ\b\ 3¤\ 1\0\0\0\0\0\0<?php
62
63
64
65
66
67
68
69
70
71
72
73 namespace Composer\Autoload;
74
75 use Composer\Config;
76 use Composer\EventDispatcher\EventDispatcher;
77 use Composer\Installer\InstallationManager;
78 use Composer\IO\IOInterface;
79 use Composer\Package\AliasPackage;
80 use Composer\Package\PackageInterface;
81 use Composer\Repository\InstalledRepositoryInterface;
82 use Composer\Util\Filesystem;
83 use Composer\Script\ScriptEvents;
84 use Composer\Util\PackageSorter;
85
86
87
88
89
90 class AutoloadGenerator
91 {
92
93
94
95 private $eventDispatcher;
96
97
98
99
100 private $io;
101
102
103
104
105 private $devMode = false;
106
107
108
109
110 private $classMapAuthoritative = false;
111
112
113
114
115 private $apcu = false;
116
117
118
119
120 private $runScripts = false;
121
122 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
123 {
124 $this->eventDispatcher = $eventDispatcher;
125 $this->io = $io;
126 }
127
128 public function setDevMode($devMode = true)
129 {
130 $this->devMode = (bool) $devMode;
131 }
132
133
134
135
136
137
138
139 public function setClassMapAuthoritative($classMapAuthoritative)
140 {
141 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
142 }
143
144
145
146
147
148
149 public function setApcu($apcu)
150 {
151 $this->apcu = (bool) $apcu;
152 }
153
154
155
156
157
158
159 public function setRunScripts($runScripts = true)
160 {
161 $this->runScripts = (bool) $runScripts;
162 }
163
164 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '')
165 {
166 if ($this->classMapAuthoritative) {
167
168  $scanPsrPackages = true;
169 }
170 if ($this->runScripts) {
171 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
172 'optimize' => (bool) $scanPsrPackages,
173 ));
174 }
175
176 $filesystem = new Filesystem();
177 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
178
179  
180  
181  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
182 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
183 $useGlobalIncludePath = (bool) $config->get('use-include-path');
184 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
185 $targetDir = $vendorPath.'/'.$targetDir;
186 $filesystem->ensureDirectoryExists($targetDir);
187
188 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
189 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
190 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
191
192 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
193 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
194
195 $namespacesFile = <<<EOF
196 <?php
197
198 // autoload_namespaces.php @generated by Composer
199
200 \$vendorDir = $vendorPathCode52;
201 \$baseDir = $appBaseDirCode;
202
203 return array(
204
205 EOF;
206
207 $psr4File = <<<EOF
208 <?php
209
210 // autoload_psr4.php @generated by Composer
211
212 \$vendorDir = $vendorPathCode52;
213 \$baseDir = $appBaseDirCode;
214
215 return array(
216
217 EOF;
218
219
220  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
221 $autoloads = $this->parseAutoloads($packageMap, $mainPackage, $this->devMode === false);
222
223
224  foreach ($autoloads['psr-0'] as $namespace => $paths) {
225 $exportedPaths = array();
226 foreach ($paths as $path) {
227 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
228 }
229 $exportedPrefix = var_export($namespace, true);
230 $namespacesFile .= "    $exportedPrefix => ";
231 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
232 }
233 $namespacesFile .= ");\n";
234
235
236  foreach ($autoloads['psr-4'] as $namespace => $paths) {
237 $exportedPaths = array();
238 foreach ($paths as $path) {
239 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
240 }
241 $exportedPrefix = var_export($namespace, true);
242 $psr4File .= "    $exportedPrefix => ";
243 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
244 }
245 $psr4File .= ");\n";
246
247 $classmapFile = <<<EOF
248 <?php
249
250 // autoload_classmap.php @generated by Composer
251
252 \$vendorDir = $vendorPathCode52;
253 \$baseDir = $appBaseDirCode;
254
255 return array(
256
257 EOF;
258
259
260  $targetDirLoader = null;
261 $mainAutoload = $mainPackage->getAutoload();
262 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
263 $levels = substr_count($filesystem->normalizePath($mainPackage->getTargetDir()), '/') + 1;
264 $prefixes = implode(', ', array_map(function ($prefix) {
265 return var_export($prefix, true);
266 }, array_keys($mainAutoload['psr-0'])));
267 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
268
269 $targetDirLoader = <<<EOF
270
271     public static function autoload(\$class)
272     {
273         \$dir = $baseDirFromTargetDirCode . '/';
274         \$prefixes = array($prefixes);
275         foreach (\$prefixes as \$prefix) {
276             if (0 !== strpos(\$class, \$prefix)) {
277                 continue;
278             }
279             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
280             if (!\$path = stream_resolve_include_path(\$path)) {
281                 return false;
282             }
283             require \$path;
284
285             return true;
286         }
287     }
288
289 EOF;
290 }
291
292 $blacklist = null;
293 if (!empty($autoloads['exclude-from-classmap'])) {
294 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
295 }
296
297 $classMap = array();
298 $ambiguousClasses = array();
299 $scannedFiles = array();
300 foreach ($autoloads['classmap'] as $dir) {
301 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, null, $classMap, $ambiguousClasses, $scannedFiles);
302 }
303
304 if ($scanPsrPackages) {
305 $namespacesToScan = array();
306
307
308  foreach (array('psr-4', 'psr-0') as $psrType) {
309 foreach ($autoloads[$psrType] as $namespace => $paths) {
310 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
311 }
312 }
313
314 krsort($namespacesToScan);
315
316 foreach ($namespacesToScan as $namespace => $groups) {
317 foreach ($groups as $group) {
318 foreach ($group['paths'] as $dir) {
319 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
320 if (!is_dir($dir)) {
321 continue;
322 }
323
324 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespace, $group['type'], $classMap, $ambiguousClasses, $scannedFiles);
325 }
326 }
327 }
328 }
329
330 foreach ($ambiguousClasses as $className => $ambigiousPaths) {
331 $cleanPath = str_replace(array('$vendorDir . \'', '$baseDir . \'', "',\n"), array($vendorPath, $basePath, ''), $classMap[$className]);
332
333 $this->io->writeError(
334 '<warning>Warning: Ambiguous class resolution, "'.$className.'"'.
335 ' was found '. (count($ambigiousPaths) + 1) .'x: in "'.$cleanPath.'" and "'. implode('", "', $ambigiousPaths) .'", the first will be used.</warning>'
336 );
337 }
338
339 ksort($classMap);
340 foreach ($classMap as $class => $code) {
341 $classmapFile .= '    '.var_export($class, true).' => '.$code;
342 }
343 $classmapFile .= ");\n";
344
345 if (!$suffix) {
346 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
347 $content = file_get_contents($vendorPath.'/autoload.php');
348 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
349 $suffix = $match[1];
350 }
351 }
352
353 if (!$suffix) {
354 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
355 }
356 }
357
358 $this->filePutContentsIfModified($targetDir.'/autoload_namespaces.php', $namespacesFile);
359 $this->filePutContentsIfModified($targetDir.'/autoload_psr4.php', $psr4File);
360 $this->filePutContentsIfModified($targetDir.'/autoload_classmap.php', $classmapFile);
361 $includePathFilePath = $targetDir.'/include_paths.php';
362 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
363 $this->filePutContentsIfModified($includePathFilePath, $includePathFileContents);
364 } elseif (file_exists($includePathFilePath)) {
365 unlink($includePathFilePath);
366 }
367 $includeFilesFilePath = $targetDir.'/autoload_files.php';
368 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
369 $this->filePutContentsIfModified($includeFilesFilePath, $includeFilesFileContents);
370 } elseif (file_exists($includeFilesFilePath)) {
371 unlink($includeFilesFilePath);
372 }
373 $this->filePutContentsIfModified($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
374 $this->filePutContentsIfModified($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
375 $this->filePutContentsIfModified($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
376
377 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
378 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
379
380 if ($this->runScripts) {
381 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
382 'optimize' => (bool) $scanPsrPackages,
383 ));
384 }
385
386 return count($classMap);
387 }
388
389 private function filePutContentsIfModified($path, $content)
390 {
391 $currentContent = @file_get_contents($path);
392 if (!$currentContent || ($currentContent != $content)) {
393 return file_put_contents($path, $content);
394 }
395
396 return 0;
397 }
398
399 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $autoloadType, array $classMap, array &$ambiguousClasses, array &$scannedFiles)
400 {
401 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter, $autoloadType, true, $scannedFiles) as $class => $path) {
402 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
403 if (!isset($classMap[$class])) {
404 $classMap[$class] = $pathCode;
405 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
406 $ambiguousClasses[$class][] = $path;
407 }
408 }
409
410 return $classMap;
411 }
412
413 private function generateClassMap($dir, $blacklist, $namespaceFilter, $autoloadType, $showAmbiguousWarning, array &$scannedFiles)
414 {
415 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter, $autoloadType, $scannedFiles);
416 }
417
418 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
419 {
420
421  $packageMap = array(array($mainPackage, ''));
422
423 foreach ($packages as $package) {
424 if ($package instanceof AliasPackage) {
425 continue;
426 }
427 $this->validatePackage($package);
428
429 $packageMap[] = array(
430 $package,
431 $installationManager->getInstallPath($package),
432 );
433 }
434
435 return $packageMap;
436 }
437
438
439
440
441
442
443 protected function validatePackage(PackageInterface $package)
444 {
445 $autoload = $package->getAutoload();
446 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
447 $name = $package->getName();
448 $package->getTargetDir();
449 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
450 }
451 if (!empty($autoload['psr-4'])) {
452 foreach ($autoload['psr-4'] as $namespace => $dirs) {
453 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
454 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
455 }
456 }
457 }
458 }
459
460
461
462
463
464
465
466
467
468 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage, $filterOutRequireDevPackages = false)
469 {
470 $mainPackageMap = array_shift($packageMap);
471 if ($filterOutRequireDevPackages) {
472 $packageMap = $this->filterPackageMap($packageMap, $mainPackage);
473 }
474 $sortedPackageMap = $this->sortPackageMap($packageMap);
475 $sortedPackageMap[] = $mainPackageMap;
476 array_unshift($packageMap, $mainPackageMap);
477
478 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
479 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
480 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
481 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
482 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
483
484 krsort($psr0);
485 krsort($psr4);
486
487 return array(
488 'psr-0' => $psr0,
489 'psr-4' => $psr4,
490 'classmap' => $classmap,
491 'files' => $files,
492 'exclude-from-classmap' => $exclude,
493 );
494 }
495
496
497
498
499
500
501
502 public function createLoader(array $autoloads)
503 {
504 $loader = new ClassLoader();
505
506 if (isset($autoloads['psr-0'])) {
507 foreach ($autoloads['psr-0'] as $namespace => $path) {
508 $loader->add($namespace, $path);
509 }
510 }
511
512 if (isset($autoloads['psr-4'])) {
513 foreach ($autoloads['psr-4'] as $namespace => $path) {
514 $loader->addPsr4($namespace, $path);
515 }
516 }
517
518 if (isset($autoloads['classmap'])) {
519 $blacklist = null;
520 if (!empty($autoloads['exclude-from-classmap'])) {
521 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
522 }
523
524 $scannedFiles = array();
525 foreach ($autoloads['classmap'] as $dir) {
526 try {
527 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, null, false, $scannedFiles));
528 } catch (\RuntimeException $e) {
529 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
530 }
531 }
532 }
533
534 return $loader;
535 }
536
537 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
538 {
539 $includePaths = array();
540
541 foreach ($packageMap as $item) {
542 list($package, $installPath) = $item;
543
544 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
545 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
546 }
547
548 foreach ($package->getIncludePaths() as $includePath) {
549 $includePath = trim($includePath, '/');
550 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
551 }
552 }
553
554 if (!$includePaths) {
555 return;
556 }
557
558 $includePathsCode = '';
559 foreach ($includePaths as $path) {
560 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
561 }
562
563 return <<<EOF
564 <?php
565
566 // include_paths.php @generated by Composer
567
568 \$vendorDir = $vendorPathCode;
569 \$baseDir = $appBaseDirCode;
570
571 return array(
572 $includePathsCode);
573
574 EOF;
575 }
576
577 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
578 {
579 $filesCode = '';
580 foreach ($files as $fileIdentifier => $functionFile) {
581 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
582 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
583 }
584
585 if (!$filesCode) {
586 return false;
587 }
588
589 return <<<EOF
590 <?php
591
592 // autoload_files.php @generated by Composer
593
594 \$vendorDir = $vendorPathCode;
595 \$baseDir = $appBaseDirCode;
596
597 return array(
598 $filesCode);
599
600 EOF;
601 }
602
603 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
604 {
605 if (!$filesystem->isAbsolutePath($path)) {
606 $path = $basePath . '/' . $path;
607 }
608 $path = $filesystem->normalizePath($path);
609
610 $baseDir = '';
611 if (strpos($path.'/', $vendorPath.'/') === 0) {
612 $path = substr($path, strlen($vendorPath));
613 $baseDir = '$vendorDir';
614
615 if ($path !== false) {
616 $baseDir .= " . ";
617 }
618 } else {
619 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
620 if (!$filesystem->isAbsolutePath($path)) {
621 $baseDir = '$baseDir . ';
622 $path = '/' . $path;
623 }
624 }
625
626 if (strpos($path, '.phar') !== false) {
627 $baseDir = "'phar://' . " . $baseDir;
628 }
629
630 return $baseDir . (($path !== false) ? var_export($path, true) : "");
631 }
632
633 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
634 {
635 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
636 if ("'" === $lastChar || '"' === $lastChar) {
637 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
638 } else {
639 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
640 }
641
642 return <<<AUTOLOAD
643 <?php
644
645 // autoload.php @generated by Composer
646
647 require_once $vendorPathToTargetDirCode;
648
649 return ComposerAutoloaderInit$suffix::getLoader();
650
651 AUTOLOAD;
652 }
653
654 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
655 {
656 $file = <<<HEADER
657 <?php
658
659 // autoload_real.php @generated by Composer
660
661 class ComposerAutoloaderInit$suffix
662 {
663     private static \$loader;
664
665     public static function loadClassLoader(\$class)
666     {
667         if ('Composer\\Autoload\\ClassLoader' === \$class) {
668             require __DIR__ . '/ClassLoader.php';
669         }
670     }
671
672     /**
673      * @return \Composer\Autoload\ClassLoader
674      */
675     public static function getLoader()
676     {
677         if (null !== self::\$loader) {
678             return self::\$loader;
679         }
680
681         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
682         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
683         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
684
685
686 HEADER;
687
688 if ($useIncludePath) {
689 $file .= <<<'INCLUDE_PATH'
690         $includePaths = require __DIR__ . '/include_paths.php';
691         $includePaths[] = get_include_path();
692         set_include_path(implode(PATH_SEPARATOR, $includePaths));
693
694
695 INCLUDE_PATH;
696 }
697
698 $file .= <<<STATIC_INIT
699         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
700         if (\$useStaticLoader) {
701             require_once __DIR__ . '/autoload_static.php';
702
703             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
704         } else {
705
706 STATIC_INIT;
707
708 if (!$this->classMapAuthoritative) {
709 $file .= <<<'PSR04'
710             $map = require __DIR__ . '/autoload_namespaces.php';
711             foreach ($map as $namespace => $path) {
712                 $loader->set($namespace, $path);
713             }
714
715             $map = require __DIR__ . '/autoload_psr4.php';
716             foreach ($map as $namespace => $path) {
717                 $loader->setPsr4($namespace, $path);
718             }
719
720
721 PSR04;
722 }
723
724 if ($useClassMap) {
725 $file .= <<<'CLASSMAP'
726             $classMap = require __DIR__ . '/autoload_classmap.php';
727             if ($classMap) {
728                 $loader->addClassMap($classMap);
729             }
730
731 CLASSMAP;
732 }
733
734 $file .= "        }\n\n";
735
736 if ($this->classMapAuthoritative) {
737 $file .= <<<'CLASSMAPAUTHORITATIVE'
738         $loader->setClassMapAuthoritative(true);
739
740 CLASSMAPAUTHORITATIVE;
741 }
742
743 if ($this->apcu) {
744 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
745 $file .= <<<APCU
746         \$loader->setApcuPrefix('$apcuPrefix');
747
748 APCU;
749 }
750
751 if ($useGlobalIncludePath) {
752 $file .= <<<'INCLUDEPATH'
753         $loader->setUseIncludePath(true);
754
755 INCLUDEPATH;
756 }
757
758 if ($targetDirLoader) {
759 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
760         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
761
762
763 REGISTER_TARGET_DIR_AUTOLOAD;
764 }
765
766 $file .= <<<REGISTER_LOADER
767         \$loader->register($prependAutoloader);
768
769
770 REGISTER_LOADER;
771
772 if ($useIncludeFiles) {
773 $file .= <<<INCLUDE_FILES
774         if (\$useStaticLoader) {
775             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
776         } else {
777             \$includeFiles = require __DIR__ . '/autoload_files.php';
778         }
779         foreach (\$includeFiles as \$fileIdentifier => \$file) {
780             composerRequire$suffix(\$fileIdentifier, \$file);
781         }
782
783
784 INCLUDE_FILES;
785 }
786
787 $file .= <<<METHOD_FOOTER
788         return \$loader;
789     }
790
791 METHOD_FOOTER;
792
793 $file .= $targetDirLoader;
794
795 if ($useIncludeFiles) {
796 return $file . <<<FOOTER
797 }
798
799 function composerRequire$suffix(\$fileIdentifier, \$file)
800 {
801     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
802         require \$file;
803
804         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
805     }
806 }
807
808 FOOTER;
809 }
810
811 return $file . <<<FOOTER
812 }
813
814 FOOTER;
815 }
816
817 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
818 {
819 $staticPhpVersion = 50600;
820
821 $file = <<<HEADER
822 <?php
823
824 // autoload_static.php @generated by Composer
825
826 namespace Composer\Autoload;
827
828 class ComposerStaticInit$suffix
829 {
830
831 HEADER;
832
833 $loader = new ClassLoader();
834
835 $map = require $targetDir . '/autoload_namespaces.php';
836 foreach ($map as $namespace => $path) {
837 $loader->set($namespace, $path);
838 }
839
840 $map = require $targetDir . '/autoload_psr4.php';
841 foreach ($map as $namespace => $path) {
842 $loader->setPsr4($namespace, $path);
843 }
844
845 $classMap = require $targetDir . '/autoload_classmap.php';
846 if ($classMap) {
847 $loader->addClassMap($classMap);
848 }
849
850 $filesystem = new Filesystem();
851
852 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
853 $vendorPharPathCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
854 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
855 $appBaseDirPharCode = ' => \'phar://\' . ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
856
857 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
858 $absoluteVendorPharPathCode = ' => ' . substr(var_export(rtrim('phar://' . $vendorDir, '\\/') . '/', true), 0, -1);
859 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
860 $absoluteAppBaseDirPharCode = ' => ' . substr(var_export(rtrim('phar://' . $baseDir, '\\/') . '/', true), 0, -1);
861
862 $initializer = '';
863 $prefix = "\0Composer\Autoload\ClassLoader\0";
864 $prefixLen = strlen($prefix);
865 if (file_exists($targetDir . '/autoload_files.php')) {
866 $maps = array('files' => require $targetDir . '/autoload_files.php');
867 } else {
868 $maps = array();
869 }
870
871 foreach ((array) $loader as $prop => $value) {
872 if ($value && 0 === strpos($prop, $prefix)) {
873 $maps[substr($prop, $prefixLen)] = $value;
874 }
875 }
876
877 foreach ($maps as $prop => $value) {
878 if (count($value) > 32767) {
879
880  
881  $staticPhpVersion = 70000;
882 }
883 $value = strtr(
884 var_export($value, true),
885 array(
886 $absoluteVendorPathCode => $vendorPathCode,
887 $absoluteVendorPharPathCode => $vendorPharPathCode,
888 $absoluteAppBaseDirCode => $appBaseDirCode,
889 $absoluteAppBaseDirPharCode => $appBaseDirPharCode,
890 )
891 );
892 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
893
894 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
895 if ('files' !== $prop) {
896 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
897 }
898 }
899
900 return $file . <<<INITIALIZER
901     public static function getInitializer(ClassLoader \$loader)
902     {
903         return \Closure::bind(function () use (\$loader) {
904 $initializer
905         }, null, ClassLoader::class);
906     }
907 }
908
909 INITIALIZER;
910 }
911
912 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
913 {
914 $autoloads = array();
915
916 foreach ($packageMap as $item) {
917 list($package, $installPath) = $item;
918
919 $autoload = $package->getAutoload();
920 if ($this->devMode && $package === $mainPackage) {
921 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
922 }
923
924
925  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
926 continue;
927 }
928 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
929 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
930 }
931
932 foreach ($autoload[$type] as $namespace => $paths) {
933 foreach ((array) $paths as $path) {
934 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
935
936  if ($package === $mainPackage) {
937 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
938 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
939 } else {
940
941  $path = $package->getTargetDir() . '/' . $path;
942 }
943 }
944
945 if ($type === 'exclude-from-classmap') {
946
947  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
948
949
950  $path = str_replace('\\*\\*', '.+?', $path);
951 $path = str_replace('\\*', '[^/]+?', $path);
952
953
954  $updir = null;
955 $path = preg_replace_callback(
956 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
957 function ($matches) use (&$updir) {
958 if (isset($matches[1])) {
959
960  $updir = str_replace('\\.', '.', $matches[1]);
961 }
962
963 return '';
964 },
965 $path
966 );
967 if (empty($installPath)) {
968 $installPath = strtr(getcwd(), '\\', '/');
969 }
970
971 $resolvedPath = realpath($installPath . '/' . $updir);
972 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path . '($|/)';
973 continue;
974 }
975
976 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
977
978 if ($type === 'files') {
979 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
980 continue;
981 } elseif ($type === 'classmap') {
982 $autoloads[] = $relativePath;
983 continue;
984 }
985
986 $autoloads[$namespace][] = $relativePath;
987 }
988 }
989 }
990
991 return $autoloads;
992 }
993
994 protected function getFileIdentifier(PackageInterface $package, $path)
995 {
996 return md5($package->getName() . ':' . $path);
997 }
998
999
1000
1001
1002
1003
1004
1005
1006 protected function filterPackageMap(array $packageMap, PackageInterface $mainPackage)
1007 {
1008 $packages = array();
1009 $include = array();
1010 $replacedBy = array();
1011
1012 foreach ($packageMap as $item) {
1013 $package = $item[0];
1014 $name = $package->getName();
1015 $packages[$name] = $package;
1016 foreach ($package->getReplaces() as $replace) {
1017 $replacedBy[$replace->getTarget()] = $name;
1018 }
1019 }
1020
1021 $add = function (PackageInterface $package) use (&$add, $packages, &$include, $replacedBy) {
1022 foreach ($package->getRequires() as $link) {
1023 $target = $link->getTarget();
1024 if (isset($replacedBy[$target])) {
1025 $target = $replacedBy[$target];
1026 }
1027 if (!isset($include[$target])) {
1028 $include[$target] = true;
1029 if (isset($packages[$target])) {
1030 $add($packages[$target]);
1031 }
1032 }
1033 }
1034 };
1035 $add($mainPackage);
1036
1037 return array_filter(
1038 $packageMap,
1039 function ($item) use ($include) {
1040 $package = $item[0];
1041 foreach ($package->getNames() as $name) {
1042 if (isset($include[$name])) {
1043 return true;
1044 }
1045 }
1046
1047 return false;
1048 }
1049 );
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060 protected function sortPackageMap(array $packageMap)
1061 {
1062 $packages = array();
1063 $paths = array();
1064
1065 foreach ($packageMap as $item) {
1066 list($package, $path) = $item;
1067 $name = $package->getName();
1068 $packages[$name] = $package;
1069 $paths[$name] = $path;
1070 }
1071
1072 $sortedPackages = PackageSorter::sortPackages($packages);
1073
1074 $sortedPackageMap = array();
1075
1076 foreach ($sortedPackages as $package) {
1077 $name = $package->getName();
1078 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1079 }
1080
1081 return $sortedPackageMap;
1082 }
1083
1084
1085
1086
1087
1088
1089
1090 protected function safeCopy($source, $target)
1091 {
1092 if (!file_exists($target) || !file_exists($source) || !$this->filesAreEqual($source, $target)) {
1093 $source = fopen($source, 'r');
1094 $target = fopen($target, 'w+');
1095
1096 stream_copy_to_stream($source, $target);
1097 fclose($source);
1098 fclose($target);
1099 }
1100 }
1101
1102
1103
1104
1105
1106 private function filesAreEqual($a, $b)
1107 {
1108
1109  if (filesize($a) !== filesize($b)) {
1110 return false;
1111 }
1112
1113
1114  $ah = fopen($a, 'rb');
1115 $bh = fopen($b, 'rb');
1116
1117 $result = true;
1118 while (!feof($ah)) {
1119 if (fread($ah, 8192) != fread($bh, 8192)) {
1120 $result = false;
1121 break;
1122 }
1123 }
1124
1125 fclose($ah);
1126 fclose($bh);
1127
1128 return $result;
1129 }
1130 }
1131 <?php
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149 namespace Composer\Autoload;
1150
1151 use Symfony\Component\Finder\Finder;
1152 use Composer\IO\IOInterface;
1153 use Composer\Util\Filesystem;
1154
1155
1156
1157
1158
1159
1160
1161 class ClassMapGenerator
1162 {
1163
1164
1165
1166
1167
1168
1169 public static function dump($dirs, $file)
1170 {
1171 $maps = array();
1172
1173 foreach ($dirs as $dir) {
1174 $maps = array_merge($maps, static::createMap($dir));
1175 }
1176
1177 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1178 }
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null, $autoloadType = null, &$scannedFiles = array())
1193 {
1194 if (is_string($path)) {
1195 $basePath = $path;
1196 if (is_file($path)) {
1197 $path = array(new \SplFileInfo($path));
1198 } elseif (is_dir($path)) {
1199 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1200 } else {
1201 throw new \RuntimeException(
1202 'Could not scan for classes inside "'.$path.
1203 '" which does not appear to be a file nor a folder'
1204 );
1205 }
1206 } elseif (null !== $autoloadType) {
1207 throw new \RuntimeException('Path must be a string when specifying an autoload type');
1208 }
1209
1210 $map = array();
1211 $filesystem = new Filesystem();
1212 $cwd = realpath(getcwd());
1213
1214 foreach ($path as $file) {
1215 $filePath = $file->getPathname();
1216 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1217 continue;
1218 }
1219
1220 if (!$filesystem->isAbsolutePath($filePath)) {
1221 $filePath = $cwd . '/' . $filePath;
1222 $filePath = $filesystem->normalizePath($filePath);
1223 } else {
1224 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1225 }
1226
1227 $realPath = realpath($filePath);
1228
1229
1230  
1231  if (isset($scannedFiles[$realPath])) {
1232 continue;
1233 }
1234
1235
1236  if ($blacklist && preg_match($blacklist, strtr($realPath, '\\', '/'))) {
1237 continue;
1238 }
1239
1240  if ($blacklist && preg_match($blacklist, strtr($filePath, '\\', '/'))) {
1241 continue;
1242 }
1243
1244 $classes = self::findClasses($filePath);
1245 if (null !== $autoloadType) {
1246 list($classes, $validClasses) = self::filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath, $io);
1247
1248
1249  if ($validClasses) {
1250 $scannedFiles[$realPath] = true;
1251 }
1252 } else {
1253
1254  $scannedFiles[$realPath] = true;
1255 }
1256
1257 foreach ($classes as $class) {
1258
1259  
1260  if ( null !== $namespace && '' !== $namespace && 0 !== strpos($class, $namespace)) {
1261 continue;
1262 }
1263
1264 if (!isset($map[$class])) {
1265 $map[$class] = $filePath;
1266 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1267 $io->writeError(
1268 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1269 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1270 );
1271 }
1272 }
1273 }
1274
1275 return $map;
1276 }
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289 private static function filterByNamespace($classes, $filePath, $baseNamespace, $namespaceType, $basePath, $io)
1290 {
1291 $validClasses = array();
1292 $rejectedClasses = array();
1293
1294 $realSubPath = substr($filePath, strlen($basePath) + 1);
1295 $realSubPath = substr($realSubPath, 0, strrpos($realSubPath, '.'));
1296
1297 foreach ($classes as $class) {
1298
1299  if ('' !== $baseNamespace && 0 !== strpos($class, $baseNamespace)) {
1300 continue;
1301 }
1302
1303  if ('psr-0' === $namespaceType) {
1304 $namespaceLength = strrpos($class, '\\');
1305 if (false !== $namespaceLength) {
1306 $namespace = substr($class, 0, $namespaceLength + 1);
1307 $className = substr($class, $namespaceLength + 1);
1308 $subPath = str_replace('\\', DIRECTORY_SEPARATOR, $namespace)
1309 . str_replace('_', DIRECTORY_SEPARATOR, $className);
1310 }
1311 else {
1312 $subPath = str_replace('_', DIRECTORY_SEPARATOR, $class);
1313 }
1314 } elseif ('psr-4' === $namespaceType) {
1315 $subNamespace = ('' !== $baseNamespace) ? substr($class, strlen($baseNamespace)) : $class;
1316 $subPath = str_replace('\\', DIRECTORY_SEPARATOR, $subNamespace);
1317 } else {
1318 throw new \RuntimeException("namespaceType must be psr-0 or psr-4, $namespaceType given");
1319 }
1320 if ($subPath === $realSubPath) {
1321 $validClasses[] = $class;
1322 } else {
1323 $rejectedClasses[] = $class;
1324 }
1325 }
1326
1327  if (empty($validClasses)) {
1328 foreach ($rejectedClasses as $class) {
1329 trigger_error(
1330 "Class $class located in ".preg_replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. It will not autoload anymore in Composer v2.0.",
1331 E_USER_DEPRECATED
1332 );
1333 }
1334
1335
1336  
1337  }
1338
1339
1340  
1341  return array($classes, $validClasses);
1342 }
1343
1344
1345
1346
1347
1348
1349
1350
1351 private static function findClasses($path)
1352 {
1353 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1354 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1355 $extraTypes .= '|enum';
1356 }
1357
1358
1359  
1360  $contents = @php_strip_whitespace($path);
1361 if (!$contents) {
1362 if (!file_exists($path)) {
1363 $message = 'File at "%s" does not exist, check your classmap definitions';
1364 } elseif (!is_readable($path)) {
1365 $message = 'File at "%s" is not readable, check its permissions';
1366 } elseif ('' === trim(file_get_contents($path))) {
1367
1368  return array();
1369 } else {
1370 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1371 }
1372 $error = error_get_last();
1373 if (isset($error['message'])) {
1374 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1375 }
1376 throw new \RuntimeException(sprintf($message, $path));
1377 }
1378
1379
1380  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1381 return array();
1382 }
1383
1384
1385  $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
1386
1387  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1388
1389  if (substr($contents, 0, 2) !== '<?') {
1390 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1391 if ($replacements === 0) {
1392 return array();
1393 }
1394 }
1395
1396  $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
1397
1398  $pos = strrpos($contents, '?>');
1399 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1400 $contents = substr($contents, 0, $pos);
1401 }
1402
1403  if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
1404 $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
1405 }
1406
1407 preg_match_all('{
1408             (?:
1409                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1410                | \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*+ [\{;]
1411             )
1412         }ix', $contents, $matches);
1413
1414 $classes = array();
1415 $namespace = '';
1416
1417 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1418 if (!empty($matches['ns'][$i])) {
1419 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1420 } else {
1421 $name = $matches['name'][$i];
1422
1423  if ($name === 'extends' || $name === 'implements') {
1424 continue;
1425 }
1426 if ($name[0] === ':') {
1427
1428  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1429 } elseif ($matches['type'][$i] === 'enum') {
1430
1431  
1432  
1433  
1434  $name = rtrim($name, ':');
1435 }
1436 $classes[] = ltrim($namespace . $name, '\\');
1437 }
1438 }
1439
1440 return $classes;
1441 }
1442 }
1443 <?php
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455 namespace Composer;
1456
1457 use Composer\IO\IOInterface;
1458 use Composer\Util\Filesystem;
1459 use Composer\Util\Silencer;
1460 use Symfony\Component\Finder\Finder;
1461
1462
1463
1464
1465
1466
1467 class Cache
1468 {
1469 private static $cacheCollected = false;
1470 private $io;
1471 private $root;
1472 private $enabled = true;
1473 private $whitelist;
1474 private $filesystem;
1475
1476
1477
1478
1479
1480
1481
1482 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1483 {
1484 $this->io = $io;
1485 $this->root = rtrim($cacheDir, '/\\') . '/';
1486 $this->whitelist = $whitelist;
1487 $this->filesystem = $filesystem ?: new Filesystem();
1488
1489 if (!self::isUsable($cacheDir)) {
1490 $this->enabled = false;
1491
1492 return;
1493 }
1494
1495 if (
1496 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1497 || !is_writable($this->root)
1498 ) {
1499 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1500 $this->enabled = false;
1501 }
1502 }
1503
1504 public static function isUsable($path)
1505 {
1506 return !preg_match('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path);
1507 }
1508
1509 public function isEnabled()
1510 {
1511 return $this->enabled;
1512 }
1513
1514 public function getRoot()
1515 {
1516 return $this->root;
1517 }
1518
1519 public function read($file)
1520 {
1521 if ($this->enabled) {
1522 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1523 if (file_exists($this->root . $file)) {
1524 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1525
1526 return file_get_contents($this->root . $file);
1527 }
1528 }
1529
1530 return false;
1531 }
1532
1533 public function write($file, $contents)
1534 {
1535 if ($this->enabled) {
1536 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1537
1538 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1539
1540 try {
1541 return file_put_contents($this->root . $file, $contents);
1542 } catch (\ErrorException $e) {
1543 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1544 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1545
1546  unlink($this->root . $file);
1547
1548 $message = sprintf(
1549 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1550 $this->root . $file,
1551 $m[1],
1552 $m[2],
1553 @disk_free_space($this->root . dirname($file))
1554 );
1555
1556 $this->io->writeError($message);
1557
1558 return false;
1559 }
1560
1561 throw $e;
1562 }
1563 }
1564
1565 return false;
1566 }
1567
1568
1569
1570
1571 public function copyFrom($file, $source)
1572 {
1573 if ($this->enabled) {
1574 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1575 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1576
1577 if (!file_exists($source)) {
1578 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1579 } elseif ($this->io->isDebug()) {
1580 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1581 }
1582
1583 return copy($source, $this->root . $file);
1584 }
1585
1586 return false;
1587 }
1588
1589
1590
1591
1592 public function copyTo($file, $target)
1593 {
1594 if ($this->enabled) {
1595 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1596 if (file_exists($this->root . $file)) {
1597 try {
1598 touch($this->root . $file, filemtime($this->root . $file), time());
1599 } catch (\ErrorException $e) {
1600
1601  
1602  Silencer::call('touch', $this->root . $file);
1603 }
1604
1605 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1606
1607 return copy($this->root . $file, $target);
1608 }
1609 }
1610
1611 return false;
1612 }
1613
1614 public function gcIsNecessary()
1615 {
1616 return (!self::$cacheCollected && !mt_rand(0, 50));
1617 }
1618
1619 public function remove($file)
1620 {
1621 if ($this->enabled) {
1622 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1623 if (file_exists($this->root . $file)) {
1624 return $this->filesystem->unlink($this->root . $file);
1625 }
1626 }
1627
1628 return false;
1629 }
1630
1631 public function clear()
1632 {
1633 if ($this->enabled) {
1634 $this->filesystem->emptyDirectory($this->root);
1635 return true;
1636 }
1637
1638 return false;
1639 }
1640
1641 public function gc($ttl, $maxSize)
1642 {
1643 if ($this->enabled) {
1644 $expire = new \DateTime();
1645 $expire->modify('-'.$ttl.' seconds');
1646
1647 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1648 foreach ($finder as $file) {
1649 $this->filesystem->unlink($file->getPathname());
1650 }
1651
1652 $totalSize = $this->filesystem->size($this->root);
1653 if ($totalSize > $maxSize) {
1654 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1655 while ($totalSize > $maxSize && $iterator->valid()) {
1656 $filepath = $iterator->current()->getPathname();
1657 $totalSize -= $this->filesystem->size($filepath);
1658 $this->filesystem->unlink($filepath);
1659 $iterator->next();
1660 }
1661 }
1662
1663 self::$cacheCollected = true;
1664
1665 return true;
1666 }
1667
1668 return false;
1669 }
1670
1671 public function sha1($file)
1672 {
1673 if ($this->enabled) {
1674 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1675 if (file_exists($this->root . $file)) {
1676 return sha1_file($this->root . $file);
1677 }
1678 }
1679
1680 return false;
1681 }
1682
1683 public function sha256($file)
1684 {
1685 if ($this->enabled) {
1686 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1687 if (file_exists($this->root . $file)) {
1688 return hash_file('sha256', $this->root . $file);
1689 }
1690 }
1691
1692 return false;
1693 }
1694
1695 protected function getFinder()
1696 {
1697 return Finder::create()->in($this->root)->files();
1698 }
1699 }
1700 <?php
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712 namespace Composer\Command;
1713
1714 use Symfony\Component\Console\Input\InputInterface;
1715 use Symfony\Component\Console\Output\OutputInterface;
1716
1717
1718
1719
1720 class AboutCommand extends BaseCommand
1721 {
1722 protected function configure()
1723 {
1724 $this
1725 ->setName('about')
1726 ->setDescription('Shows the short information about Composer.')
1727 ->setHelp(
1728 <<<EOT
1729 <info>php composer.phar about</info>
1730 EOT
1731 )
1732 ;
1733 }
1734
1735 protected function execute(InputInterface $input, OutputInterface $output)
1736 {
1737 $this->getIO()->write(
1738 <<<EOT
1739 <info>Composer - Dependency Manager for PHP</info>
1740 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1741 See https://getcomposer.org/ for more information.</comment>
1742 EOT
1743 );
1744
1745 return 0;
1746 }
1747 }
1748 <?php
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760 namespace Composer\Command;
1761
1762 use Composer\Factory;
1763 use Composer\IO\IOInterface;
1764 use Composer\Config;
1765 use Composer\Composer;
1766 use Composer\Repository\CompositeRepository;
1767 use Composer\Repository\RepositoryFactory;
1768 use Composer\Script\ScriptEvents;
1769 use Composer\Plugin\CommandEvent;
1770 use Composer\Plugin\PluginEvents;
1771 use Composer\Util\Filesystem;
1772 use Symfony\Component\Console\Input\InputArgument;
1773 use Symfony\Component\Console\Input\InputInterface;
1774 use Symfony\Component\Console\Input\InputOption;
1775 use Symfony\Component\Console\Output\OutputInterface;
1776
1777
1778
1779
1780
1781
1782 class ArchiveCommand extends BaseCommand
1783 {
1784 protected function configure()
1785 {
1786 $this
1787 ->setName('archive')
1788 ->setDescription('Creates an archive of this composer package.')
1789 ->setDefinition(array(
1790 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1791 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1792 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1793 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1794 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1795 .' Note that the format will be appended.'),
1796 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1797 ))
1798 ->setHelp(
1799 <<<EOT
1800 The <info>archive</info> command creates an archive of the specified format
1801 containing the files and directories of the Composer project or the specified
1802 package in the specified version and writes it to the specified directory.
1803
1804 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1805
1806 Read more at https://getcomposer.org/doc/03-cli.md#archive
1807 EOT
1808 )
1809 ;
1810 }
1811
1812 protected function execute(InputInterface $input, OutputInterface $output)
1813 {
1814 $composer = $this->getComposer(false);
1815 $config = null;
1816
1817 if ($composer) {
1818 $config = $composer->getConfig();
1819 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1820 $eventDispatcher = $composer->getEventDispatcher();
1821 $eventDispatcher->dispatch($commandEvent->getName(), $commandEvent);
1822 $eventDispatcher->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1823 }
1824
1825 if (!$config) {
1826 $config = Factory::createConfig();
1827 }
1828
1829 if (null === $input->getOption('format')) {
1830 $input->setOption('format', $config->get('archive-format'));
1831 }
1832 if (null === $input->getOption('dir')) {
1833 $input->setOption('dir', $config->get('archive-dir'));
1834 }
1835
1836 $returnCode = $this->archive(
1837 $this->getIO(),
1838 $config,
1839 $input->getArgument('package'),
1840 $input->getArgument('version'),
1841 $input->getOption('format'),
1842 $input->getOption('dir'),
1843 $input->getOption('file'),
1844 $input->getOption('ignore-filters'),
1845 $composer
1846 );
1847
1848 if (0 === $returnCode && $composer) {
1849 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1850 }
1851
1852 return $returnCode;
1853 }
1854
1855 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1856 {
1857 if ($composer) {
1858 $archiveManager = $composer->getArchiveManager();
1859 } else {
1860 $factory = new Factory;
1861 $downloadManager = $factory->createDownloadManager($io, $config);
1862 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1863 }
1864
1865 if ($packageName) {
1866 $package = $this->selectPackage($io, $packageName, $version);
1867
1868 if (!$package) {
1869 return 1;
1870 }
1871 } else {
1872 $package = $this->getComposer()->getPackage();
1873 }
1874
1875 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1876 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1877 $fs = new Filesystem;
1878 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1879
1880 $io->writeError('Created: ', false);
1881 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1882
1883 return 0;
1884 }
1885
1886 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1887 {
1888 $io->writeError('<info>Searching for the specified package.</info>');
1889
1890 if ($composer = $this->getComposer(false)) {
1891 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1892 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1893 } else {
1894 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1895 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1896 $repo = new CompositeRepository($defaultRepos);
1897 }
1898
1899 $packages = $repo->findPackages($packageName, $version);
1900
1901 if (count($packages) > 1) {
1902 $package = reset($packages);
1903 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1904 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1905 return $p->getPrettyString();
1906 }, $packages)).'.');
1907 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1908 } elseif ($packages) {
1909 $package = reset($packages);
1910 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1911 } else {
1912 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1913
1914 return false;
1915 }
1916
1917 return $package;
1918 }
1919 }
1920 <?php
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932 namespace Composer\Command;
1933
1934 use Composer\Composer;
1935 use Composer\Config;
1936 use Composer\Console\Application;
1937 use Composer\Factory;
1938 use Composer\IO\IOInterface;
1939 use Composer\IO\NullIO;
1940 use Composer\Plugin\PreCommandRunEvent;
1941 use Composer\Plugin\PluginEvents;
1942 use Symfony\Component\Console\Input\InputInterface;
1943 use Symfony\Component\Console\Output\OutputInterface;
1944 use Symfony\Component\Console\Command\Command;
1945
1946
1947
1948
1949
1950
1951
1952 abstract class BaseCommand extends Command
1953 {
1954
1955
1956
1957 private $composer;
1958
1959
1960
1961
1962 private $io;
1963
1964
1965
1966
1967
1968
1969
1970 public function getComposer($required = true, $disablePlugins = null)
1971 {
1972 if (null === $this->composer) {
1973 $application = $this->getApplication();
1974 if ($application instanceof Application) {
1975
1976 $this->composer = $application->getComposer($required, $disablePlugins);
1977 } elseif ($required) {
1978 throw new \RuntimeException(
1979 'Could not create a Composer\Composer instance, you must inject '.
1980 'one if this command is not used with a Composer\Console\Application instance'
1981 );
1982 }
1983 }
1984
1985 return $this->composer;
1986 }
1987
1988
1989
1990
1991 public function setComposer(Composer $composer)
1992 {
1993 $this->composer = $composer;
1994 }
1995
1996
1997
1998
1999 public function resetComposer()
2000 {
2001 $this->composer = null;
2002 $this->getApplication()->resetComposer();
2003 }
2004
2005
2006
2007
2008
2009
2010
2011
2012 public function isProxyCommand()
2013 {
2014 return false;
2015 }
2016
2017
2018
2019
2020 public function getIO()
2021 {
2022 if (null === $this->io) {
2023 $application = $this->getApplication();
2024 if ($application instanceof Application) {
2025
2026 $this->io = $application->getIO();
2027 } else {
2028 $this->io = new NullIO();
2029 }
2030 }
2031
2032 return $this->io;
2033 }
2034
2035
2036
2037
2038 public function setIO(IOInterface $io)
2039 {
2040 $this->io = $io;
2041 }
2042
2043
2044
2045
2046 protected function initialize(InputInterface $input, OutputInterface $output)
2047 {
2048
2049  $disablePlugins = $input->hasParameterOption('--no-plugins');
2050 $composer = $this->getComposer(false, $disablePlugins);
2051 if (null === $composer) {
2052 $composer = Factory::createGlobal($this->getIO(), $disablePlugins);
2053 }
2054 if ($composer) {
2055 $preCommandRunEvent = new PreCommandRunEvent(PluginEvents::PRE_COMMAND_RUN, $input, $this->getName());
2056 $composer->getEventDispatcher()->dispatch($preCommandRunEvent->getName(), $preCommandRunEvent);
2057 }
2058
2059 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
2060 $input->setOption('no-progress', true);
2061 }
2062
2063 parent::initialize($input, $output);
2064 }
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
2076 {
2077 $preferSource = false;
2078 $preferDist = false;
2079
2080 switch ($config->get('preferred-install')) {
2081 case 'source':
2082 $preferSource = true;
2083 break;
2084 case 'dist':
2085 $preferDist = true;
2086 break;
2087 case 'auto':
2088 default:
2089
2090  break;
2091 }
2092
2093 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
2094 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
2095 $preferDist = $input->getOption('prefer-dist');
2096 }
2097
2098 return array($preferSource, $preferDist);
2099 }
2100 }
2101 <?php
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113 namespace Composer\Command;
2114
2115 use Composer\DependencyResolver\Pool;
2116 use Composer\Package\Link;
2117 use Composer\Package\PackageInterface;
2118 use Composer\Repository\ArrayRepository;
2119 use Composer\Repository\CompositeRepository;
2120 use Composer\Repository\PlatformRepository;
2121 use Composer\Repository\RepositoryFactory;
2122 use Composer\Plugin\CommandEvent;
2123 use Composer\Plugin\PluginEvents;
2124 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
2125 use Composer\Package\Version\VersionParser;
2126 use Symfony\Component\Console\Helper\Table;
2127 use Symfony\Component\Console\Input\InputArgument;
2128 use Symfony\Component\Console\Input\InputInterface;
2129 use Symfony\Component\Console\Input\InputOption;
2130 use Symfony\Component\Console\Output\OutputInterface;
2131
2132
2133
2134
2135
2136
2137 class BaseDependencyCommand extends BaseCommand
2138 {
2139 const ARGUMENT_PACKAGE = 'package';
2140 const ARGUMENT_CONSTRAINT = 'constraint';
2141 const OPTION_RECURSIVE = 'recursive';
2142 const OPTION_TREE = 'tree';
2143
2144 protected $colors;
2145
2146
2147
2148
2149 protected function configure()
2150 {
2151 $this->setDefinition(array(
2152 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
2153 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
2154 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
2155 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
2156 ));
2157 }
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
2168 {
2169
2170  $composer = $this->getComposer();
2171 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
2172 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
2173
2174
2175  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
2176 $repository = new CompositeRepository(array(
2177 new ArrayRepository(array($composer->getPackage())),
2178 $composer->getRepositoryManager()->getLocalRepository(),
2179 new PlatformRepository(array(), $platformOverrides),
2180 ));
2181 $pool = new Pool();
2182 $pool->addRepository($repository);
2183
2184
2185  list($needle, $textConstraint) = array_pad(
2186 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
2187 2,
2188 $input->getArgument(self::ARGUMENT_CONSTRAINT)
2189 );
2190
2191
2192  $packages = $pool->whatProvides(strtolower($needle));
2193 if (empty($packages)) {
2194 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
2195 }
2196
2197
2198  
2199  if (!$repository->findPackage($needle, $textConstraint)) {
2200 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2201 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2202 $repository->addRepository(new ArrayRepository(array(clone $match)));
2203 }
2204 }
2205
2206
2207  $needles = array($needle);
2208 if ($inverted) {
2209 foreach ($packages as $package) {
2210 $needles = array_merge($needles, array_map(function (Link $link) {
2211 return $link->getTarget();
2212 }, $package->getReplaces()));
2213 }
2214 }
2215
2216
2217  if ('*' !== $textConstraint) {
2218 $versionParser = new VersionParser();
2219 $constraint = $versionParser->parseConstraints($textConstraint);
2220 } else {
2221 $constraint = null;
2222 }
2223
2224
2225  $renderTree = $input->getOption(self::OPTION_TREE);
2226 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2227
2228
2229  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2230 if (empty($results)) {
2231 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2232 $this->getIO()->writeError(sprintf(
2233 '<info>There is no installed package depending on "%s"%s</info>',
2234 $needle,
2235 $extra
2236 ));
2237 } elseif ($renderTree) {
2238 $this->initStyles($output);
2239 $root = $packages[0];
2240 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2241 $this->printTree($results);
2242 } else {
2243 $this->printTable($output, $results);
2244 }
2245
2246 return 0;
2247 }
2248
2249
2250
2251
2252
2253
2254
2255 protected function printTable(OutputInterface $output, $results)
2256 {
2257 $table = array();
2258 $doubles = array();
2259 do {
2260 $queue = array();
2261 $rows = array();
2262 foreach ($results as $result) {
2263
2264
2265
2266
2267 list($package, $link, $children) = $result;
2268 $unique = (string) $link;
2269 if (isset($doubles[$unique])) {
2270 continue;
2271 }
2272 $doubles[$unique] = true;
2273 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2274 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2275 if ($children) {
2276 $queue = array_merge($queue, $children);
2277 }
2278 }
2279 $results = $queue;
2280 $table = array_merge($rows, $table);
2281 } while (!empty($results));
2282
2283
2284  $renderer = new Table($output);
2285 $renderer->setStyle('compact');
2286 $rendererStyle = $renderer->getStyle();
2287 if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
2288 $rendererStyle->setVerticalBorderChars('');
2289 } else {
2290 $rendererStyle->setVerticalBorderChar('');
2291 }
2292 $rendererStyle->setCellRowContentFormat('%s  ');
2293 $renderer->setRows($table)->render();
2294 }
2295
2296
2297
2298
2299
2300
2301 protected function initStyles(OutputInterface $output)
2302 {
2303 $this->colors = array(
2304 'green',
2305 'yellow',
2306 'cyan',
2307 'magenta',
2308 'blue',
2309 );
2310
2311 foreach ($this->colors as $color) {
2312 $style = new OutputFormatterStyle($color);
2313 $output->getFormatter()->setStyle($color, $style);
2314 }
2315 }
2316
2317
2318
2319
2320
2321
2322
2323
2324 protected function printTree($results, $prefix = '', $level = 1)
2325 {
2326 $count = count($results);
2327 $idx = 0;
2328 foreach ($results as $result) {
2329
2330
2331
2332
2333
2334 list($package, $link, $children) = $result;
2335
2336 $color = $this->colors[$level % count($this->colors)];
2337 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2338 $isLast = (++$idx == $count);
2339 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2340 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2341 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2342 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2343 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2344 if ($children) {
2345 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2346 }
2347 }
2348 }
2349
2350 private function writeTreeLine($line)
2351 {
2352 $io = $this->getIO();
2353 if (!$io->isDecorated()) {
2354 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2355 }
2356
2357 $io->write($line);
2358 }
2359 }
2360 <?php
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372 namespace Composer\Command;
2373
2374 use Composer\Package\Link;
2375 use Composer\Package\PackageInterface;
2376 use Composer\Semver\Constraint\Constraint;
2377 use Symfony\Component\Console\Helper\Table;
2378 use Symfony\Component\Console\Input\InputInterface;
2379 use Symfony\Component\Console\Input\InputOption;
2380 use Symfony\Component\Console\Output\OutputInterface;
2381 use Composer\Repository\PlatformRepository;
2382
2383 class CheckPlatformReqsCommand extends BaseCommand
2384 {
2385 protected function configure()
2386 {
2387 $this->setName('check-platform-reqs')
2388 ->setDescription('Check that platform requirements are satisfied.')
2389 ->setDefinition(array(
2390 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables checking of require-dev packages requirements.'),
2391 ))
2392 ->setHelp(
2393 <<<EOT
2394 Checks that your PHP and extensions versions match the platform requirements of the installed packages.
2395
2396 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.
2397
2398 <info>php composer.phar check-platform-reqs</info>
2399
2400 EOT
2401 );
2402 }
2403
2404 protected function execute(InputInterface $input, OutputInterface $output)
2405 {
2406 $composer = $this->getComposer();
2407
2408 $requires = $composer->getPackage()->getRequires();
2409 if ($input->getOption('no-dev')) {
2410 $dependencies = $composer->getLocker()->getLockedRepository(!$input->getOption('no-dev'))->getPackages();
2411 } else {
2412 $dependencies = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
2413
2414  if (!$dependencies) {
2415 $dependencies = $composer->getLocker()->getLockedRepository(true)->getPackages();
2416 }
2417 $requires += $composer->getPackage()->getDevRequires();
2418 }
2419 foreach ($requires as $require => $link) {
2420 $requires[$require] = array($link);
2421 }
2422
2423 foreach ($dependencies as $package) {
2424 foreach ($package->getRequires() as $require => $link) {
2425 $requires[$require][] = $link;
2426 }
2427 }
2428
2429 ksort($requires);
2430
2431 $platformRepo = new PlatformRepository(array(), array());
2432 $currentPlatformPackages = $platformRepo->getPackages();
2433 $currentPlatformPackageMap = array();
2434
2435
2436
2437
2438 foreach ($currentPlatformPackages as $currentPlatformPackage) {
2439 $currentPlatformPackageMap[$currentPlatformPackage->getName()] = $currentPlatformPackage;
2440 }
2441
2442 $results = array();
2443
2444 $exitCode = 0;
2445
2446
2447
2448
2449 foreach ($requires as $require => $links) {
2450 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $require)) {
2451 if (isset($currentPlatformPackageMap[$require])) {
2452 $pass = true;
2453 $version = $currentPlatformPackageMap[$require]->getVersion();
2454
2455 foreach ($links as $link) {
2456 if (!$link->getConstraint()->matches(new Constraint('=', $version))) {
2457 $results[] = array(
2458 $currentPlatformPackageMap[$require]->getPrettyName(),
2459 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2460 $link,
2461 '<error>failed</error>',
2462 );
2463 $pass = false;
2464
2465 $exitCode = max($exitCode, 1);
2466 }
2467 }
2468
2469 if ($pass) {
2470 $results[] = array(
2471 $currentPlatformPackageMap[$require]->getPrettyName(),
2472 $currentPlatformPackageMap[$require]->getPrettyVersion(),
2473 null,
2474 '<info>success</info>',
2475 );
2476 }
2477 } else {
2478 $results[] = array(
2479 $require,
2480 'n/a',
2481 $links[0],
2482 '<error>missing</error>',
2483 );
2484
2485 $exitCode = max($exitCode, 2);
2486 }
2487 }
2488 }
2489
2490 $this->printTable($output, $results);
2491
2492 return $exitCode;
2493 }
2494
2495 protected function printTable(OutputInterface $output, $results)
2496 {
2497 $table = array();
2498 $rows = array();
2499 foreach ($results as $result) {
2500
2501
2502
2503 list($platformPackage, $version, $link, $status) = $result;
2504 $rows[] = array(
2505 $platformPackage,
2506 $version,
2507 $link ? sprintf('%s %s %s (%s)', $link->getSource(), $link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()) : '',
2508 $status,
2509 );
2510 }
2511 $table = array_merge($rows, $table);
2512
2513
2514  $renderer = new Table($output);
2515 $renderer->setStyle('compact');
2516 $rendererStyle = $renderer->getStyle();
2517 if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
2518 $rendererStyle->setVerticalBorderChars('');
2519 } else {
2520 $rendererStyle->setVerticalBorderChar('');
2521 }
2522 $rendererStyle->setCellRowContentFormat('%s  ');
2523 $renderer->setRows($table)->render();
2524 }
2525 }
2526 <?php
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538 namespace Composer\Command;
2539
2540 use Composer\Cache;
2541 use Composer\Factory;
2542 use Symfony\Component\Console\Input\InputInterface;
2543 use Symfony\Component\Console\Output\OutputInterface;
2544
2545
2546
2547
2548 class ClearCacheCommand extends BaseCommand
2549 {
2550 protected function configure()
2551 {
2552 $this
2553 ->setName('clear-cache')
2554 ->setAliases(array('clearcache', 'cc'))
2555 ->setDescription('Clears composer\'s internal package cache.')
2556 ->setHelp(
2557 <<<EOT
2558 The <info>clear-cache</info> deletes all cached packages from composer's
2559 cache directory.
2560
2561 Read more at https://getcomposer.org/doc/03-cli.md#clear-cache-clearcache-cc
2562 EOT
2563 )
2564 ;
2565 }
2566
2567 protected function execute(InputInterface $input, OutputInterface $output)
2568 {
2569 $config = Factory::createConfig();
2570 $io = $this->getIO();
2571
2572 $cachePaths = array(
2573 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2574 'cache-repo-dir' => $config->get('cache-repo-dir'),
2575 'cache-files-dir' => $config->get('cache-files-dir'),
2576 'cache-dir' => $config->get('cache-dir'),
2577 );
2578
2579 foreach ($cachePaths as $key => $cachePath) {
2580 $cachePath = realpath($cachePath);
2581 if (!$cachePath) {
2582 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2583
2584 continue;
2585 }
2586 $cache = new Cache($io, $cachePath);
2587 if (!$cache->isEnabled()) {
2588 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2589
2590 continue;
2591 }
2592
2593 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2594 $cache->clear();
2595 }
2596
2597 $io->writeError('<info>All caches cleared.</info>');
2598
2599 return 0;
2600 }
2601 }
2602 <?php
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614 namespace Composer\Command;
2615
2616 use Composer\Util\Platform;
2617 use Composer\Util\Silencer;
2618 use Symfony\Component\Console\Input\InputInterface;
2619 use Symfony\Component\Console\Input\InputArgument;
2620 use Symfony\Component\Console\Input\InputOption;
2621 use Symfony\Component\Console\Output\OutputInterface;
2622 use Composer\Config;
2623 use Composer\Config\JsonConfigSource;
2624 use Composer\Factory;
2625 use Composer\IO\IOInterface;
2626 use Composer\Json\JsonFile;
2627 use Composer\Semver\VersionParser;
2628 use Composer\Package\BasePackage;
2629
2630
2631
2632
2633
2634 class ConfigCommand extends BaseCommand
2635 {
2636
2637
2638
2639 protected $config;
2640
2641
2642
2643
2644 protected $configFile;
2645
2646
2647
2648
2649 protected $configSource;
2650
2651
2652
2653
2654 protected $authConfigFile;
2655
2656
2657
2658
2659 protected $authConfigSource;
2660
2661
2662
2663
2664 protected function configure()
2665 {
2666 $this
2667 ->setName('config')
2668 ->setDescription('Sets config options.')
2669 ->setDefinition(array(
2670 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2671 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2672 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2673 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2674 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2675 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2676 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2677 new InputArgument('setting-key', null, 'Setting key'),
2678 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2679 ))
2680 ->setHelp(
2681 <<<EOT
2682 This command allows you to edit composer config settings and repositories
2683 in either the local composer.json file or the global config.json file.
2684
2685 Additionally it lets you edit most properties in the local composer.json.
2686
2687 To set a config setting:
2688
2689     <comment>%command.full_name% bin-dir bin/</comment>
2690
2691 To read a config setting:
2692
2693     <comment>%command.full_name% bin-dir</comment>
2694     Outputs: <info>bin</info>
2695
2696 To edit the global config.json file:
2697
2698     <comment>%command.full_name% --global</comment>
2699
2700 To add a repository:
2701
2702     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2703
2704 To remove a repository (repo is a short alias for repositories):
2705
2706     <comment>%command.full_name% --unset repo.foo</comment>
2707
2708 To disable packagist:
2709
2710     <comment>%command.full_name% repo.packagist false</comment>
2711
2712 You can alter repositories in the global config.json file by passing in the
2713 <info>--global</info> option.
2714
2715 To add or edit suggested packages you can use:
2716
2717     <comment>%command.full_name% suggest.package reason for the suggestion</comment>
2718
2719 To add or edit extra properties you can use:
2720
2721     <comment>%command.full_name% extra.property value</comment>
2722
2723 To edit the file in an external editor:
2724
2725     <comment>%command.full_name% --editor</comment>
2726
2727 To choose your editor you can set the "EDITOR" env variable.
2728
2729 To get a list of configuration values in the file:
2730
2731     <comment>%command.full_name% --list</comment>
2732
2733 You can always pass more than one option. As an example, if you want to edit the
2734 global config.json file.
2735
2736     <comment>%command.full_name% --editor --global</comment>
2737
2738 Read more at https://getcomposer.org/doc/03-cli.md#config
2739 EOT
2740 )
2741 ;
2742 }
2743
2744
2745
2746
2747 protected function initialize(InputInterface $input, OutputInterface $output)
2748 {
2749 parent::initialize($input, $output);
2750
2751 if ($input->getOption('global') && null !== $input->getOption('file')) {
2752 throw new \RuntimeException('--file and --global can not be combined');
2753 }
2754
2755 $io = $this->getIO();
2756 $this->config = Factory::createConfig($io);
2757
2758
2759  
2760  $configFile = $input->getOption('global')
2761 ? ($this->config->get('home') . '/config.json')
2762 : ($input->getOption('file') ?: Factory::getComposerFile());
2763
2764
2765  if (
2766 ($configFile === 'composer.json' || $configFile === './composer.json')
2767 && !file_exists($configFile)
2768 && realpath(getcwd()) === realpath($this->config->get('home'))
2769 ) {
2770 file_put_contents($configFile, "{\n}\n");
2771 }
2772
2773 $this->configFile = new JsonFile($configFile, null, $io);
2774 $this->configSource = new JsonConfigSource($this->configFile);
2775
2776 $authConfigFile = $input->getOption('global')
2777 ? ($this->config->get('home') . '/auth.json')
2778 : dirname(realpath($configFile)) . '/auth.json';
2779
2780 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2781 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2782
2783
2784  if ($input->getOption('global') && !$this->configFile->exists()) {
2785 touch($this->configFile->getPath());
2786 $this->configFile->write(array('config' => new \ArrayObject));
2787 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2788 }
2789 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2790 touch($this->authConfigFile->getPath());
2791 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject, 'bearer' => new \ArrayObject));
2792 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2793 }
2794
2795 if (!$this->configFile->exists()) {
2796 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2797 }
2798 }
2799
2800
2801
2802
2803 protected function execute(InputInterface $input, OutputInterface $output)
2804 {
2805
2806  if ($input->getOption('editor')) {
2807 $editor = escapeshellcmd(getenv('EDITOR'));
2808 if (!$editor) {
2809 if (Platform::isWindows()) {
2810 $editor = 'notepad';
2811 } else {
2812 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2813 if (exec('which '.$candidate)) {
2814 $editor = $candidate;
2815 break;
2816 }
2817 }
2818 }
2819 }
2820
2821 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2822 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2823
2824 return 0;
2825 }
2826
2827 if (!$input->getOption('global')) {
2828 $this->config->merge($this->configFile->read());
2829 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2830 }
2831
2832
2833  if ($input->getOption('list')) {
2834 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2835
2836 return 0;
2837 }
2838
2839 $settingKey = $input->getArgument('setting-key');
2840 if (!$settingKey) {
2841 return 0;
2842 }
2843
2844
2845  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2846 throw new \RuntimeException('You can not combine a setting value with --unset');
2847 }
2848
2849
2850  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2851 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2852 $rawData = $this->configFile->read();
2853 $data = $this->config->all();
2854 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2855 if (!isset($matches[1]) || $matches[1] === '') {
2856 $value = isset($data['repositories']) ? $data['repositories'] : array();
2857 } else {
2858 if (!isset($data['repositories'][$matches[1]])) {
2859 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2860 }
2861
2862 $value = $data['repositories'][$matches[1]];
2863 }
2864 } elseif (strpos($settingKey, '.')) {
2865 $bits = explode('.', $settingKey);
2866 if ($bits[0] === 'extra') {
2867 $data = $rawData;
2868 } else {
2869 $data = $data['config'];
2870 }
2871 $match = false;
2872 foreach ($bits as $bit) {
2873 $key = isset($key) ? $key.'.'.$bit : $bit;
2874 $match = false;
2875 if (isset($data[$key])) {
2876 $match = true;
2877 $data = $data[$key];
2878 unset($key);
2879 }
2880 }
2881
2882 if (!$match) {
2883 throw new \RuntimeException($settingKey.' is not defined.');
2884 }
2885
2886 $value = $data;
2887 } elseif (isset($data['config'][$settingKey])) {
2888 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2889 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2890 $value = $rawData[$settingKey];
2891 } else {
2892 throw new \RuntimeException($settingKey.' is not defined');
2893 }
2894
2895 if (is_array($value)) {
2896 $value = json_encode($value);
2897 }
2898
2899 $this->getIO()->write($value, true, IOInterface::QUIET);
2900
2901 return 0;
2902 }
2903
2904 $values = $input->getArgument('setting-value'); 
2905
2906 $booleanValidator = function ($val) {
2907 return in_array($val, array('true', 'false', '1', '0'), true);
2908 };
2909 $booleanNormalizer = function ($val) {
2910 return $val !== 'false' && (bool) $val;
2911 };
2912
2913
2914  $uniqueConfigValues = array(
2915 'process-timeout' => array('is_numeric', 'intval'),
2916 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2917 'use-github-api' => array($booleanValidator, $booleanNormalizer),
2918 'preferred-install' => array(
2919 function ($val) {
2920 return in_array($val, array('auto', 'source', 'dist'), true);
2921 },
2922 function ($val) {
2923 return $val;
2924 },
2925 ),
2926 'store-auths' => array(
2927 function ($val) {
2928 return in_array($val, array('true', 'false', 'prompt'), true);
2929 },
2930 function ($val) {
2931 if ('prompt' === $val) {
2932 return 'prompt';
2933 }
2934
2935 return $val !== 'false' && (bool) $val;
2936 },
2937 ),
2938 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2939 'vendor-dir' => array('is_string', function ($val) {
2940 return $val;
2941 }),
2942 'bin-dir' => array('is_string', function ($val) {
2943 return $val;
2944 }),
2945 'archive-dir' => array('is_string', function ($val) {
2946 return $val;
2947 }),
2948 'archive-format' => array('is_string', function ($val) {
2949 return $val;
2950 }),
2951 'data-dir' => array('is_string', function ($val) {
2952 return $val;
2953 }),
2954 'cache-dir' => array('is_string', function ($val) {
2955 return $val;
2956 }),
2957 'cache-files-dir' => array('is_string', function ($val) {
2958 return $val;
2959 }),
2960 'cache-repo-dir' => array('is_string', function ($val) {
2961 return $val;
2962 }),
2963 'cache-vcs-dir' => array('is_string', function ($val) {
2964 return $val;
2965 }),
2966 'cache-ttl' => array('is_numeric', 'intval'),
2967 'cache-files-ttl' => array('is_numeric', 'intval'),
2968 'cache-files-maxsize' => array(
2969 function ($val) {
2970 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2971 },
2972 function ($val) {
2973 return $val;
2974 },
2975 ),
2976 'bin-compat' => array(
2977 function ($val) {
2978 return in_array($val, array('auto', 'full'));
2979 },
2980 function ($val) {
2981 return $val;
2982 },
2983 ),
2984 'discard-changes' => array(
2985 function ($val) {
2986 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2987 },
2988 function ($val) {
2989 if ('stash' === $val) {
2990 return 'stash';
2991 }
2992
2993 return $val !== 'false' && (bool) $val;
2994 },
2995 ),
2996 'autoloader-suffix' => array('is_string', function ($val) {
2997 return $val === 'null' ? null : $val;
2998 }),
2999 'sort-packages' => array($booleanValidator, $booleanNormalizer),
3000 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
3001 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
3002 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
3003 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
3004 'disable-tls' => array($booleanValidator, $booleanNormalizer),
3005 'secure-http' => array($booleanValidator, $booleanNormalizer),
3006 'cafile' => array(
3007 function ($val) {
3008 return file_exists($val) && is_readable($val);
3009 },
3010 function ($val) {
3011 return $val === 'null' ? null : $val;
3012 },
3013 ),
3014 'capath' => array(
3015 function ($val) {
3016 return is_dir($val) && is_readable($val);
3017 },
3018 function ($val) {
3019 return $val === 'null' ? null : $val;
3020 },
3021 ),
3022 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
3023 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
3024 'lock' => array($booleanValidator, $booleanNormalizer),
3025 );
3026 $multiConfigValues = array(
3027 'github-protocols' => array(
3028 function ($vals) {
3029 if (!is_array($vals)) {
3030 return 'array expected';
3031 }
3032
3033 foreach ($vals as $val) {
3034 if (!in_array($val, array('git', 'https', 'ssh'))) {
3035 return 'valid protocols include: git, https, ssh';
3036 }
3037 }
3038
3039 return true;
3040 },
3041 function ($vals) {
3042 return $vals;
3043 },
3044 ),
3045 'github-domains' => array(
3046 function ($vals) {
3047 if (!is_array($vals)) {
3048 return 'array expected';
3049 }
3050
3051 return true;
3052 },
3053 function ($vals) {
3054 return $vals;
3055 },
3056 ),
3057 'gitlab-domains' => array(
3058 function ($vals) {
3059 if (!is_array($vals)) {
3060 return 'array expected';
3061 }
3062
3063 return true;
3064 },
3065 function ($vals) {
3066 return $vals;
3067 },
3068 ),
3069 );
3070
3071 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
3072 if ($settingKey === 'disable-tls' && $this->config->get('disable-tls')) {
3073 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
3074 }
3075
3076 $this->configSource->removeConfigSetting($settingKey);
3077
3078 return 0;
3079 }
3080 if (isset($uniqueConfigValues[$settingKey])) {
3081 $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
3082
3083 return 0;
3084 }
3085 if (isset($multiConfigValues[$settingKey])) {
3086 $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
3087
3088 return 0;
3089 }
3090
3091  if (preg_match('/^preferred-install\.(.+)/', $settingKey, $matches)) {
3092 if ($input->getOption('unset')) {
3093 $this->configSource->removeConfigSetting($settingKey);
3094
3095 return 0;
3096 }
3097
3098 list($validator) = $uniqueConfigValues['preferred-install'];
3099 if (!$validator($values[0])) {
3100 throw new \RuntimeException('Invalid value for '.$settingKey.'. Should be one of: auto, source, or dist');
3101 }
3102
3103 $this->configSource->addConfigSetting($settingKey, $values[0]);
3104
3105 return 0;
3106 }
3107
3108
3109  $uniqueProps = array(
3110 'name' => array('is_string', function ($val) {
3111 return $val;
3112 }),
3113 'type' => array('is_string', function ($val) {
3114 return $val;
3115 }),
3116 'description' => array('is_string', function ($val) {
3117 return $val;
3118 }),
3119 'homepage' => array('is_string', function ($val) {
3120 return $val;
3121 }),
3122 'version' => array('is_string', function ($val) {
3123 return $val;
3124 }),
3125 'minimum-stability' => array(
3126 function ($val) {
3127 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
3128 },
3129 function ($val) {
3130 return VersionParser::normalizeStability($val);
3131 },
3132 ),
3133 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
3134 );
3135 $multiProps = array(
3136 'keywords' => array(
3137 function ($vals) {
3138 if (!is_array($vals)) {
3139 return 'array expected';
3140 }
3141
3142 return true;
3143 },
3144 function ($vals) {
3145 return $vals;
3146 },
3147 ),
3148 'license' => array(
3149 function ($vals) {
3150 if (!is_array($vals)) {
3151 return 'array expected';
3152 }
3153
3154 return true;
3155 },
3156 function ($vals) {
3157 return $vals;
3158 },
3159 ),
3160 );
3161
3162 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
3163 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');
3164 }
3165 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
3166 $this->configSource->removeProperty($settingKey);
3167
3168 return 0;
3169 }
3170 if (isset($uniqueProps[$settingKey])) {
3171 $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
3172
3173 return 0;
3174 }
3175 if (isset($multiProps[$settingKey])) {
3176 $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
3177
3178 return 0;
3179 }
3180
3181
3182  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
3183 if ($input->getOption('unset')) {
3184 $this->configSource->removeRepository($matches[1]);
3185
3186 return 0;
3187 }
3188
3189 if (2 === count($values)) {
3190 $this->configSource->addRepository($matches[1], array(
3191 'type' => $values[0],
3192 'url' => $values[1],
3193 ));
3194
3195 return 0;
3196 }
3197
3198 if (1 === count($values)) {
3199 $value = strtolower($values[0]);
3200 if (true === $booleanValidator($value)) {
3201 if (false === $booleanNormalizer($value)) {
3202 $this->configSource->addRepository($matches[1], false);
3203
3204 return 0;
3205 }
3206 } else {
3207 $value = JsonFile::parseJson($values[0]);
3208 $this->configSource->addRepository($matches[1], $value);
3209
3210 return 0;
3211 }
3212 }
3213
3214 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
3215 }
3216
3217
3218  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
3219 if ($input->getOption('unset')) {
3220 $this->configSource->removeProperty($settingKey);
3221
3222 return 0;
3223 }
3224
3225 $this->configSource->addProperty($settingKey, $values[0]);
3226
3227 return 0;
3228 }
3229
3230
3231  if (preg_match('/^suggest\.(.+)/', $settingKey, $matches)) {
3232 if ($input->getOption('unset')) {
3233 $this->configSource->removeProperty($settingKey);
3234
3235 return 0;
3236 }
3237
3238 $this->configSource->addProperty($settingKey, implode(' ', $values));
3239
3240 return 0;
3241 }
3242
3243
3244  if (in_array($settingKey, array('suggest', 'extra'), true) && $input->getOption('unset')) {
3245 $this->configSource->removeProperty($settingKey);
3246
3247 return 0;
3248 }
3249
3250
3251  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
3252 if ($input->getOption('unset')) {
3253 $this->configSource->removeConfigSetting($settingKey);
3254
3255 return 0;
3256 }
3257
3258 $this->configSource->addConfigSetting($settingKey, $values[0]);
3259
3260 return 0;
3261 }
3262
3263
3264  if ($settingKey === 'platform' && $input->getOption('unset')) {
3265 $this->configSource->removeConfigSetting($settingKey);
3266
3267 return 0;
3268 }
3269
3270
3271  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|bearer)\.(.+)/', $settingKey, $matches)) {
3272 if ($input->getOption('unset')) {
3273 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3274 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3275
3276 return 0;
3277 }
3278
3279 if ($matches[1] === 'bitbucket-oauth') {
3280 if (2 !== count($values)) {
3281 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
3282 }
3283 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3284 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
3285 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token', 'bearer'), true)) {
3286 if (1 !== count($values)) {
3287 throw new \RuntimeException('Too many arguments, expected only one token');
3288 }
3289 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3290 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
3291 } elseif ($matches[1] === 'http-basic') {
3292 if (2 !== count($values)) {
3293 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
3294 }
3295 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
3296 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
3297 }
3298
3299 return 0;
3300 }
3301
3302
3303  if (preg_match('/^scripts\.(.+)/', $settingKey, $matches)) {
3304 if ($input->getOption('unset')) {
3305 $this->configSource->removeProperty($settingKey);
3306
3307 return 0;
3308 }
3309
3310 $this->configSource->addProperty($settingKey, count($values) > 1 ? $values : $values[0]);
3311
3312 return 0;
3313 }
3314
3315 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
3316 }
3317
3318 protected function handleSingleValue($key, array $callbacks, array $values, $method)
3319 {
3320 list($validator, $normalizer) = $callbacks;
3321 if (1 !== count($values)) {
3322 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
3323 }
3324
3325 if (true !== $validation = $validator($values[0])) {
3326 throw new \RuntimeException(sprintf(
3327 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3328 $values[0]
3329 ));
3330 }
3331
3332 $normalizedValue = $normalizer($values[0]);
3333
3334 if ($key === 'disable-tls') {
3335 if (!$normalizedValue && $this->config->get('disable-tls')) {
3336 $this->getIO()->writeError('<info>You are now running Composer with SSL/TLS protection enabled.</info>');
3337 } elseif ($normalizedValue && !$this->config->get('disable-tls')) {
3338 $this->getIO()->writeError('<warning>You are now running Composer with SSL/TLS protection disabled.</warning>');
3339 }
3340 }
3341
3342 return call_user_func(array($this->configSource, $method), $key, $normalizedValue);
3343 }
3344
3345 protected function handleMultiValue($key, array $callbacks, array $values, $method)
3346 {
3347 list($validator, $normalizer) = $callbacks;
3348 if (true !== $validation = $validator($values)) {
3349 throw new \RuntimeException(sprintf(
3350 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
3351 json_encode($values)
3352 ));
3353 }
3354
3355 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
3356 }
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
3367 {
3368 $origK = $k;
3369 $io = $this->getIO();
3370 foreach ($contents as $key => $value) {
3371 if ($k === null && !in_array($key, array('config', 'repositories'))) {
3372 continue;
3373 }
3374
3375 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
3376
3377 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
3378 $k .= preg_replace('{^config\.}', '', $key . '.');
3379 $this->listConfiguration($value, $rawVal, $output, $k);
3380 $k = $origK;
3381
3382 continue;
3383 }
3384
3385 if (is_array($value)) {
3386 $value = array_map(function ($val) {
3387 return is_array($val) ? json_encode($val) : $val;
3388 }, $value);
3389
3390 $value = '['.implode(', ', $value).']';
3391 }
3392
3393 if (is_bool($value)) {
3394 $value = var_export($value, true);
3395 }
3396
3397 if (is_string($rawVal) && $rawVal != $value) {
3398 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>', true, IOInterface::QUIET);
3399 } else {
3400 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>', true, IOInterface::QUIET);
3401 }
3402 }
3403 }
3404 }
3405 <?php
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417 namespace Composer\Command;
3418
3419 use Composer\Config;
3420 use Composer\Factory;
3421 use Composer\Installer;
3422 use Composer\Installer\ProjectInstaller;
3423 use Composer\Installer\InstallationManager;
3424 use Composer\Installer\SuggestedPackagesReporter;
3425 use Composer\IO\IOInterface;
3426 use Composer\Package\BasePackage;
3427 use Composer\DependencyResolver\Pool;
3428 use Composer\DependencyResolver\Operation\InstallOperation;
3429 use Composer\Package\Version\VersionSelector;
3430 use Composer\Package\AliasPackage;
3431 use Composer\Repository\RepositoryFactory;
3432 use Composer\Repository\CompositeRepository;
3433 use Composer\Repository\PlatformRepository;
3434 use Composer\Repository\InstalledFilesystemRepository;
3435 use Composer\Script\ScriptEvents;
3436 use Composer\Util\Silencer;
3437 use Symfony\Component\Console\Input\InputArgument;
3438 use Symfony\Component\Console\Input\InputInterface;
3439 use Symfony\Component\Console\Input\InputOption;
3440 use Symfony\Component\Console\Output\OutputInterface;
3441 use Symfony\Component\Finder\Finder;
3442 use Composer\Json\JsonFile;
3443 use Composer\Config\JsonConfigSource;
3444 use Composer\Util\Filesystem;
3445 use Composer\Package\Version\VersionParser;
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455 class CreateProjectCommand extends BaseCommand
3456 {
3457
3458
3459
3460 protected $suggestedPackagesReporter;
3461
3462 protected function configure()
3463 {
3464 $this
3465 ->setName('create-project')
3466 ->setDescription('Creates new project from a package into given directory.')
3467 ->setDefinition(array(
3468 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
3469 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
3470 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
3471 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
3472 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
3473 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
3474 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
3475 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
3476 new InputOption('add-repository', null, InputOption::VALUE_NONE, 'Add the repository option to the composer.json.'),
3477 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
3478 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
3479 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
3480 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
3481 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
3482 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.'),
3483 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deleting the vcs folder.'),
3484 new InputOption('remove-vcs', null, InputOption::VALUE_NONE, 'Whether to force deletion of the vcs folder without prompting.'),
3485 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
3486 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
3487 ))
3488 ->setHelp(
3489 <<<EOT
3490 The <info>create-project</info> command creates a new project from a given
3491 package into a new directory. If executed without params and in a directory
3492 with a composer.json file it installs the packages for the current project.
3493
3494 You can use this command to bootstrap new projects or setup a clean
3495 version-controlled installation for developers of your project.
3496
3497 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3498
3499 You can also specify the version with the package name using = or : as separator.
3500
3501 <info>php composer.phar create-project vendor/project:version target-directory</info>
3502
3503 To install unstable packages, either specify the version you want, or use the
3504 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3505
3506 To setup a developer workable version you should create the project using the source
3507 controlled code by appending the <info>'--prefer-source'</info> flag.
3508
3509 To install a package from another repository than the default one you
3510 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3511
3512 Read more at https://getcomposer.org/doc/03-cli.md#create-project
3513 EOT
3514 )
3515 ;
3516 }
3517
3518 protected function execute(InputInterface $input, OutputInterface $output)
3519 {
3520 $config = Factory::createConfig();
3521 $io = $this->getIO();
3522
3523 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3524
3525 if ($input->getOption('dev')) {
3526 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3527 }
3528 if ($input->getOption('no-custom-installers')) {
3529 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3530 $input->setOption('no-plugins', true);
3531 }
3532
3533 return $this->installProject(
3534 $io,
3535 $config,
3536 $input,
3537 $input->getArgument('package'),
3538 $input->getArgument('directory'),
3539 $input->getArgument('version'),
3540 $input->getOption('stability'),
3541 $preferSource,
3542 $preferDist,
3543 !$input->getOption('no-dev'),
3544 $input->getOption('repository') ?: $input->getOption('repository-url'),
3545 $input->getOption('no-plugins'),
3546 $input->getOption('no-scripts'),
3547 $input->getOption('no-progress'),
3548 $input->getOption('no-install'),
3549 $input->getOption('ignore-platform-reqs'),
3550 !$input->getOption('no-secure-http'),
3551 $input->getOption('add-repository')
3552 );
3553 }
3554
3555 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, $addRepository = false)
3556 {
3557 $oldCwd = getcwd();
3558
3559
3560  $io->loadConfiguration($config);
3561
3562 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3563
3564 if ($packageName !== null) {
3565 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $noProgress, $ignorePlatformReqs, $secureHttp);
3566 } else {
3567 $installedFromVcs = false;
3568 }
3569
3570 $composer = Factory::create($io, null, $disablePlugins);
3571
3572
3573  if ($repository !== null && $addRepository) {
3574 if ($composer->getLocker()->isLocked()) {
3575 $io->writeError('<error>Adding a repository when creating a project that provides a composer.lock file is not supported</error>');
3576
3577 return false;
3578 }
3579
3580 $repoConfig = RepositoryFactory::configFromString($io, $composer->getConfig(), $repository, true);
3581 $composerJsonRepositoriesConfig = $composer->getConfig()->getRepositories();
3582 $name = RepositoryFactory::generateRepositoryName(0, $repoConfig, $composerJsonRepositoriesConfig);
3583 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3584 $configSource->addRepository($name, $repoConfig);
3585
3586 $composer = Factory::create($io, null, $disablePlugins);
3587 }
3588
3589 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3590
3591 $fs = new Filesystem();
3592
3593 if ($noScripts === false) {
3594
3595  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3596 }
3597
3598
3599  $config = $composer->getConfig();
3600 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3601
3602
3603  if ($noInstall === false) {
3604 $installer = Installer::create($io, $composer);
3605 $installer->setPreferSource($preferSource)
3606 ->setPreferDist($preferDist)
3607 ->setDevMode($installDevPackages)
3608 ->setRunScripts(!$noScripts)
3609 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3610 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3611 ->setOptimizeAutoloader($config->get('optimize-autoloader'))
3612 ->setClassMapAuthoritative($config->get('classmap-authoritative'))
3613 ->setApcuAutoloader($config->get('apcu-autoloader'));
3614
3615 if ($disablePlugins) {
3616 $installer->disablePlugins();
3617 }
3618
3619 $status = $installer->run();
3620 if (0 !== $status) {
3621 return $status;
3622 }
3623 }
3624
3625 $hasVcs = $installedFromVcs;
3626 if (
3627 !$input->getOption('keep-vcs')
3628 && $installedFromVcs
3629 && (
3630 $input->getOption('remove-vcs')
3631 || !$io->isInteractive()
3632 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3633 )
3634 ) {
3635 $finder = new Finder();
3636 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3637 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3638 $finder->name($vcsName);
3639 }
3640
3641 try {
3642 $dirs = iterator_to_array($finder);
3643 unset($finder);
3644 foreach ($dirs as $dir) {
3645 if (!$fs->removeDirectory($dir)) {
3646 throw new \RuntimeException('Could not remove '.$dir);
3647 }
3648 }
3649 } catch (\Exception $e) {
3650 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3651 }
3652
3653 $hasVcs = false;
3654 }
3655
3656
3657  if (!$hasVcs) {
3658 $package = $composer->getPackage();
3659 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3660 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3661 foreach ($package->{'get'.$meta['method']}() as $link) {
3662 if ($link->getPrettyConstraint() === 'self.version') {
3663 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3664 }
3665 }
3666 }
3667 }
3668
3669 if ($noScripts === false) {
3670
3671  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3672 }
3673
3674 chdir($oldCwd);
3675 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3676 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3677 Silencer::call('rmdir', $vendorComposerDir);
3678 $vendorDir = $config->get('vendor-dir');
3679 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3680 Silencer::call('rmdir', $vendorDir);
3681 }
3682 }
3683
3684 return 0;
3685 }
3686
3687 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)
3688 {
3689 if (!$secureHttp) {
3690 $config->merge(array('config' => array('secure-http' => false)));
3691 }
3692
3693 if (null === $repository) {
3694 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3695 } else {
3696 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3697 }
3698
3699 $parser = new VersionParser();
3700 $requirements = $parser->parseNameVersionPairs(array($packageName));
3701 $name = strtolower($requirements[0]['name']);
3702 if (!$packageVersion && isset($requirements[0]['version'])) {
3703 $packageVersion = $requirements[0]['version'];
3704 }
3705
3706
3707  if (null === $directory) {
3708 $parts = explode("/", $name, 2);
3709 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3710 }
3711
3712 $fs = new Filesystem();
3713 if (!$fs->isAbsolutePath($directory)) {
3714 $directory = getcwd() . DIRECTORY_SEPARATOR . $directory;
3715 }
3716
3717 $io->writeError('<info>Creating a "' . $packageName . '" project at "' . $fs->findShortestPath(getcwd(), $directory, true) . '"</info>');
3718
3719 if (file_exists($directory)) {
3720 if (!is_dir($directory)) {
3721 throw new \InvalidArgumentException('Cannot create project directory at "'.$directory.'", it exists as a file.');
3722 } elseif (!$fs->isDirEmpty($directory)) {
3723 throw new \InvalidArgumentException('Project directory "'.$directory.'" is not empty.');
3724 }
3725 }
3726
3727 if (null === $stability) {
3728 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3729 $stability = $match[1];
3730 } else {
3731 $stability = VersionParser::parseStability($packageVersion);
3732 }
3733 }
3734
3735 $stability = VersionParser::normalizeStability($stability);
3736
3737 if (!isset(BasePackage::$stabilities[$stability])) {
3738 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3739 }
3740
3741 $pool = new Pool($stability);
3742 $pool->addRepository($sourceRepo);
3743
3744 $phpVersion = null;
3745 $prettyPhpVersion = null;
3746 if (!$ignorePlatformReqs) {
3747 $platformOverrides = $config->get('platform') ?: array();
3748
3749  $platform = new PlatformRepository(array(), $platformOverrides);
3750 $phpPackage = $platform->findPackage('php', '*');
3751 $phpVersion = $phpPackage->getVersion();
3752 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3753 }
3754
3755
3756  $versionSelector = new VersionSelector($pool);
3757 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3758
3759 if (!$package) {
3760 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3761 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3762 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3763 }
3764
3765 throw new \InvalidArgumentException($errorMessage .'.');
3766 }
3767
3768
3769  if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
3770 @mkdir($directory, 0777, true);
3771 if ($realDir = realpath($directory)) {
3772 pcntl_async_signals(true);
3773 pcntl_signal(SIGINT, function () use ($realDir) {
3774 $fs = new Filesystem();
3775 $fs->removeDirectory($realDir);
3776 exit(130);
3777 });
3778 }
3779 }
3780
3781 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3782
3783 if ($disablePlugins) {
3784 $io->writeError('<info>Plugins have been disabled.</info>');
3785 }
3786
3787 if ($package instanceof AliasPackage) {
3788 $package = $package->getAliasOf();
3789 }
3790
3791 $dm = $this->createDownloadManager($io, $config);
3792 $dm->setPreferSource($preferSource)
3793 ->setPreferDist($preferDist)
3794 ->setOutputProgress(!$noProgress);
3795
3796 $projectInstaller = new ProjectInstaller($directory, $dm);
3797 $im = $this->createInstallationManager();
3798 $im->addInstaller($projectInstaller);
3799 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3800 $im->notifyInstalls($io);
3801
3802
3803  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3804
3805 $installedFromVcs = 'source' === $package->getInstallationSource();
3806
3807 $io->writeError('<info>Created project in ' . $directory . '</info>');
3808 chdir($directory);
3809
3810 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3811 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3812
3813 return $installedFromVcs;
3814 }
3815
3816 protected function createDownloadManager(IOInterface $io, Config $config)
3817 {
3818 $factory = new Factory();
3819
3820 return $factory->createDownloadManager($io, $config);
3821 }
3822
3823 protected function createInstallationManager()
3824 {
3825 return new InstallationManager();
3826 }
3827 }
3828 <?php
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840 namespace Composer\Command;
3841
3842 use Symfony\Component\Console\Input\InputInterface;
3843 use Symfony\Component\Console\Output\OutputInterface;
3844
3845
3846
3847
3848 class DependsCommand extends BaseDependencyCommand
3849 {
3850
3851
3852
3853 protected function configure()
3854 {
3855 parent::configure();
3856
3857 $this
3858 ->setName('depends')
3859 ->setAliases(array('why'))
3860 ->setDescription('Shows which packages cause the given package to be installed.')
3861 ->setHelp(
3862 <<<EOT
3863 Displays detailed information about where a package is referenced.
3864
3865 <info>php composer.phar depends composer/composer</info>
3866
3867 Read more at https://getcomposer.org/doc/03-cli.md#depends-why-
3868 EOT
3869 )
3870 ;
3871 }
3872
3873
3874
3875
3876
3877
3878
3879
3880 protected function execute(InputInterface $input, OutputInterface $output)
3881 {
3882 return parent::doExecute($input, $output, false);
3883 }
3884 }
3885 <?php
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897 namespace Composer\Command;
3898
3899 use Composer\Composer;
3900 use Composer\Factory;
3901 use Composer\Config;
3902 use Composer\Downloader\TransportException;
3903 use Composer\Repository\PlatformRepository;
3904 use Composer\Plugin\CommandEvent;
3905 use Composer\Plugin\PluginEvents;
3906 use Composer\Util\ConfigValidator;
3907 use Composer\Util\IniHelper;
3908 use Composer\Util\ProcessExecutor;
3909 use Composer\Util\RemoteFilesystem;
3910 use Composer\Util\StreamContextFactory;
3911 use Composer\SelfUpdate\Keys;
3912 use Composer\SelfUpdate\Versions;
3913 use Composer\IO\NullIO;
3914 use Symfony\Component\Console\Input\InputInterface;
3915 use Symfony\Component\Console\Output\OutputInterface;
3916
3917
3918
3919
3920 class DiagnoseCommand extends BaseCommand
3921 {
3922
3923 protected $rfs;
3924
3925
3926 protected $process;
3927
3928
3929 protected $exitCode = 0;
3930
3931 protected function configure()
3932 {
3933 $this
3934 ->setName('diagnose')
3935 ->setDescription('Diagnoses the system to identify common errors.')
3936 ->setHelp(
3937 <<<EOT
3938 The <info>diagnose</info> command checks common errors to help debugging problems.
3939
3940 The process exit code will be 1 in case of warnings and 2 for errors.
3941
3942 Read more at https://getcomposer.org/doc/03-cli.md#diagnose
3943 EOT
3944 )
3945 ;
3946 }
3947
3948
3949
3950
3951 protected function execute(InputInterface $input, OutputInterface $output)
3952 {
3953 $composer = $this->getComposer(false);
3954 $io = $this->getIO();
3955
3956 if ($composer) {
3957 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3958 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3959
3960 $io->write('Checking composer.json: ', false);
3961 $this->outputResult($this->checkComposerSchema());
3962 }
3963
3964 if ($composer) {
3965 $config = $composer->getConfig();
3966 } else {
3967 $config = Factory::createConfig();
3968 }
3969
3970 $config->merge(array('config' => array('secure-http' => false)));
3971 $config->prohibitUrlByConfig('http://repo.packagist.org', new NullIO);
3972
3973 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3974 $this->process = new ProcessExecutor($io);
3975
3976 $io->write('Checking platform settings: ', false);
3977 $this->outputResult($this->checkPlatform());
3978
3979 $io->write('Checking git settings: ', false);
3980 $this->outputResult($this->checkGit());
3981
3982 $io->write('Checking http connectivity to packagist: ', false);
3983 $this->outputResult($this->checkHttp('http', $config));
3984
3985 $io->write('Checking https connectivity to packagist: ', false);
3986 $this->outputResult($this->checkHttp('https', $config));
3987
3988 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3989 if (!empty($opts['http']['proxy'])) {
3990 $io->write('Checking HTTP proxy: ', false);
3991 $this->outputResult($this->checkHttpProxy());
3992 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3993 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3994 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3995 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3996 }
3997
3998 if ($oauth = $config->get('github-oauth')) {
3999 foreach ($oauth as $domain => $token) {
4000 $io->write('Checking '.$domain.' oauth access: ', false);
4001 $this->outputResult($this->checkGithubOauth($domain, $token));
4002 }
4003 } else {
4004 $io->write('Checking github.com rate limit: ', false);
4005 try {
4006 $rate = $this->getGithubRateLimit('github.com');
4007 if (!is_array($rate)) {
4008 $this->outputResult($rate);
4009 } elseif (10 > $rate['remaining']) {
4010 $io->write('<warning>WARNING</warning>');
4011 $io->write(sprintf(
4012 '<comment>Github has a rate limit on their API. '
4013 . 'You currently have <options=bold>%u</options=bold> '
4014 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
4015 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
4016 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
4017 $rate['remaining'],
4018 $rate['limit']
4019 ));
4020 } else {
4021 $this->outputResult(true);
4022 }
4023 } catch (\Exception $e) {
4024 if ($e instanceof TransportException && $e->getCode() === 401) {
4025 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
4026 } else {
4027 $this->outputResult($e);
4028 }
4029 }
4030 }
4031
4032 $io->write('Checking disk free space: ', false);
4033 $this->outputResult($this->checkDiskSpace($config));
4034
4035 if ('phar:' === substr(__FILE__, 0, 5)) {
4036 $io->write('Checking pubkeys: ', false);
4037 $this->outputResult($this->checkPubKeys($config));
4038
4039 $io->write('Checking composer version: ', false);
4040 $this->outputResult($this->checkVersion($config));
4041 }
4042
4043 $io->write(sprintf('Composer version: <comment>%s</comment>', Composer::VERSION));
4044
4045 $platformOverrides = $config->get('platform') ?: array();
4046 $platformRepo = new PlatformRepository(array(), $platformOverrides);
4047 $phpPkg = $platformRepo->findPackage('php', '*');
4048 $phpVersion = $phpPkg->getPrettyVersion();
4049 if (false !== strpos($phpPkg->getDescription(), 'overridden')) {
4050 $phpVersion .= ' - ' . $phpPkg->getDescription();
4051 }
4052
4053 $io->write(sprintf('PHP version: <comment>%s</comment>', $phpVersion));
4054
4055 if (defined('PHP_BINARY')) {
4056 $io->write(sprintf('PHP binary path: <comment>%s</comment>', PHP_BINARY));
4057 }
4058
4059 $io->write(sprintf('OpenSSL version: <comment>%s</comment>', OPENSSL_VERSION_TEXT));
4060
4061 return $this->exitCode;
4062 }
4063
4064 private function checkComposerSchema()
4065 {
4066 $validator = new ConfigValidator($this->getIO());
4067 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
4068
4069 if ($errors || $warnings) {
4070 $messages = array(
4071 'error' => $errors,
4072 'warning' => $warnings,
4073 );
4074
4075 $output = '';
4076 foreach ($messages as $style => $msgs) {
4077 foreach ($msgs as $msg) {
4078 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
4079 }
4080 }
4081
4082 return rtrim($output);
4083 }
4084
4085 return true;
4086 }
4087
4088 private function checkGit()
4089 {
4090 $this->process->execute('git config color.ui', $output);
4091 if (strtolower(trim($output)) === 'always') {
4092 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>';
4093 }
4094
4095 return true;
4096 }
4097
4098 private function checkHttp($proto, Config $config)
4099 {
4100 $result = $this->checkConnectivity();
4101 if ($result !== true) {
4102 return $result;
4103 }
4104
4105 $disableTls = false;
4106 $result = array();
4107 if ($proto === 'https' && $config->get('disable-tls') === true) {
4108 $disableTls = true;
4109 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
4110 }
4111 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
4112 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
4113 }
4114
4115 try {
4116 $this->rfs->getContents('packagist.org', $proto . '://repo.packagist.org/packages.json', false);
4117 } catch (TransportException $e) {
4118 if (false !== strpos($e->getMessage(), 'cafile')) {
4119 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
4120 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
4121 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
4122 } else {
4123 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
4124 }
4125 }
4126
4127 if (count($result) > 0) {
4128 return $result;
4129 }
4130
4131 return true;
4132 }
4133
4134 private function checkHttpProxy()
4135 {
4136 $result = $this->checkConnectivity();
4137 if ($result !== true) {
4138 return $result;
4139 }
4140
4141 $protocol = extension_loaded('openssl') ? 'https' : 'http';
4142 try {
4143 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/packages.json', false), true);
4144 $hash = reset($json['provider-includes']);
4145 $hash = $hash['sha256'];
4146 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
4147 $provider = $this->rfs->getContents('packagist.org', $protocol . '://repo.packagist.org/'.$path, false);
4148
4149 if (hash('sha256', $provider) !== $hash) {
4150 return 'It seems that your proxy is modifying http traffic on the fly';
4151 }
4152 } catch (\Exception $e) {
4153 return $e;
4154 }
4155
4156 return true;
4157 }
4158
4159
4160
4161
4162
4163
4164
4165
4166 private function checkHttpProxyFullUriRequestParam()
4167 {
4168 $result = $this->checkConnectivity();
4169 if ($result !== true) {
4170 return $result;
4171 }
4172
4173 $url = 'http://repo.packagist.org/packages.json';
4174 try {
4175 $this->rfs->getContents('packagist.org', $url, false);
4176 } catch (TransportException $e) {
4177 try {
4178 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
4179 } catch (TransportException $e) {
4180 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
4181 }
4182
4183 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"';
4184 }
4185
4186 return true;
4187 }
4188
4189
4190
4191
4192
4193
4194
4195
4196 private function checkHttpsProxyFullUriRequestParam()
4197 {
4198 $result = $this->checkConnectivity();
4199 if ($result !== true) {
4200 return $result;
4201 }
4202
4203 if (!extension_loaded('openssl')) {
4204 return 'You need the openssl extension installed for this check';
4205 }
4206
4207 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
4208 try {
4209 $this->rfs->getContents('github.com', $url, false);
4210 } catch (TransportException $e) {
4211 try {
4212 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
4213 } catch (TransportException $e) {
4214 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
4215 }
4216
4217 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
4218 }
4219
4220 return true;
4221 }
4222
4223 private function checkGithubOauth($domain, $token)
4224 {
4225 $result = $this->checkConnectivity();
4226 if ($result !== true) {
4227 return $result;
4228 }
4229
4230 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
4231 try {
4232 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
4233
4234 return $this->rfs->getContents($domain, $url, false, array(
4235 'retry-auth-failure' => false,
4236 )) ? true : 'Unexpected error';
4237 } catch (\Exception $e) {
4238 if ($e instanceof TransportException && $e->getCode() === 401) {
4239 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
4240 }
4241
4242 return $e;
4243 }
4244 }
4245
4246
4247
4248
4249
4250
4251
4252 private function getGithubRateLimit($domain, $token = null)
4253 {
4254 $result = $this->checkConnectivity();
4255 if ($result !== true) {
4256 return $result;
4257 }
4258
4259 if ($token) {
4260 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
4261 }
4262
4263 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
4264 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
4265 $data = json_decode($json, true);
4266
4267 return $data['resources']['core'];
4268 }
4269
4270 private function checkDiskSpace($config)
4271 {
4272 $minSpaceFree = 1024 * 1024;
4273 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
4274 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
4275 ) {
4276 return '<error>The disk hosting '.$dir.' is full</error>';
4277 }
4278
4279 return true;
4280 }
4281
4282 private function checkPubKeys($config)
4283 {
4284 $home = $config->get('home');
4285 $errors = array();
4286 $io = $this->getIO();
4287
4288 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
4289 $io->write('');
4290 }
4291
4292 if (file_exists($home.'/keys.tags.pub')) {
4293 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
4294 } else {
4295 $errors[] = '<error>Missing pubkey for tags verification</error>';
4296 }
4297
4298 if (file_exists($home.'/keys.dev.pub')) {
4299 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
4300 } else {
4301 $errors[] = '<error>Missing pubkey for dev verification</error>';
4302 }
4303
4304 if ($errors) {
4305 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
4306 }
4307
4308 return $errors ?: true;
4309 }
4310
4311 private function checkVersion($config)
4312 {
4313 $result = $this->checkConnectivity();
4314 if ($result !== true) {
4315 return $result;
4316 }
4317
4318 $versionsUtil = new Versions($config, $this->rfs);
4319 $latest = $versionsUtil->getLatest();
4320
4321 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
4322 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
4323 }
4324
4325 return true;
4326 }
4327
4328
4329
4330
4331 private function outputResult($result)
4332 {
4333 $io = $this->getIO();
4334 if (true === $result) {
4335 $io->write('<info>OK</info>');
4336
4337 return;
4338 }
4339
4340 $hadError = false;
4341 $hadWarning = false;
4342 if ($result instanceof \Exception) {
4343 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
4344 }
4345
4346 if (!$result) {
4347
4348  $hadError = true;
4349 } else {
4350 if (!is_array($result)) {
4351 $result = array($result);
4352 }
4353 foreach ($result as $message) {
4354 if (false !== strpos($message, '<error>')) {
4355 $hadError = true;
4356 } elseif (false !== strpos($message, '<warning>')) {
4357 $hadWarning = true;
4358 }
4359 }
4360 }
4361
4362 if ($hadError) {
4363 $io->write('<error>FAIL</error>');
4364 $this->exitCode = max($this->exitCode, 2);
4365 } elseif ($hadWarning) {
4366 $io->write('<warning>WARNING</warning>');
4367 $this->exitCode = max($this->exitCode, 1);
4368 }
4369
4370 if ($result) {
4371 foreach ($result as $message) {
4372 $io->write($message);
4373 }
4374 }
4375 }
4376
4377 private function checkPlatform()
4378 {
4379 $output = '';
4380 $out = function ($msg, $style) use (&$output) {
4381 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
4382 };
4383
4384
4385  $errors = array();
4386 $warnings = array();
4387 $displayIniMessage = false;
4388
4389 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
4390 $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.';
4391
4392 if (!function_exists('json_decode')) {
4393 $errors['json'] = true;
4394 }
4395
4396 if (!extension_loaded('Phar')) {
4397 $errors['phar'] = true;
4398 }
4399
4400 if (!extension_loaded('filter')) {
4401 $errors['filter'] = true;
4402 }
4403
4404 if (!extension_loaded('hash')) {
4405 $errors['hash'] = true;
4406 }
4407
4408 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
4409 $errors['iconv_mbstring'] = true;
4410 }
4411
4412 if (!filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
4413 $errors['allow_url_fopen'] = true;
4414 }
4415
4416 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
4417 $errors['ioncube'] = ioncube_loader_version();
4418 }
4419
4420 if (PHP_VERSION_ID < 50302) {
4421 $errors['php'] = PHP_VERSION;
4422 }
4423
4424 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
4425 $warnings['php'] = PHP_VERSION;
4426 }
4427
4428 if (!extension_loaded('openssl')) {
4429 $errors['openssl'] = true;
4430 }
4431
4432 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
4433 $warnings['openssl_version'] = true;
4434 }
4435
4436 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) {
4437 $warnings['apc_cli'] = true;
4438 }
4439
4440 if (!extension_loaded('zlib')) {
4441 $warnings['zlib'] = true;
4442 }
4443
4444 ob_start();
4445 phpinfo(INFO_GENERAL);
4446 $phpinfo = ob_get_clean();
4447 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
4448 $configure = $match[1];
4449
4450 if (false !== strpos($configure, '--enable-sigchild')) {
4451 $warnings['sigchild'] = true;
4452 }
4453
4454 if (false !== strpos($configure, '--with-curlwrappers')) {
4455 $warnings['curlwrappers'] = true;
4456 }
4457 }
4458
4459 if (filter_var(ini_get('xdebug.profiler_enabled'), FILTER_VALIDATE_BOOLEAN)) {
4460 $warnings['xdebug_profile'] = true;
4461 } elseif (extension_loaded('xdebug')) {
4462 $warnings['xdebug_loaded'] = true;
4463 }
4464
4465 if (defined('PHP_WINDOWS_VERSION_BUILD')
4466 && (version_compare(PHP_VERSION, '7.2.23', '<')
4467 || (version_compare(PHP_VERSION, '7.3.0', '>=')
4468 && version_compare(PHP_VERSION, '7.3.10', '<')))) {
4469 $warnings['onedrive'] = PHP_VERSION;
4470 }
4471
4472 if (!empty($errors)) {
4473 foreach ($errors as $error => $current) {
4474 switch ($error) {
4475 case 'json':
4476 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
4477 $text .= "Install it or recompile php without --disable-json";
4478 break;
4479
4480 case 'phar':
4481 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
4482 $text .= "Install it or recompile php without --disable-phar";
4483 break;
4484
4485 case 'filter':
4486 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
4487 $text .= "Install it or recompile php without --disable-filter";
4488 break;
4489
4490 case 'hash':
4491 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
4492 $text .= "Install it or recompile php without --disable-hash";
4493 break;
4494
4495 case 'iconv_mbstring':
4496 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
4497 $text .= "Install either of them or recompile php without --disable-iconv";
4498 break;
4499
4500 case 'unicode':
4501 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
4502 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4503 $text .= "    detect_unicode = Off";
4504 $displayIniMessage = true;
4505 break;
4506
4507 case 'suhosin':
4508 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
4509 $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;
4510 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
4511 $displayIniMessage = true;
4512 break;
4513
4514 case 'php':
4515 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
4516 break;
4517
4518 case 'allow_url_fopen':
4519 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
4520 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4521 $text .= "    allow_url_fopen = On";
4522 $displayIniMessage = true;
4523 break;
4524
4525 case 'ioncube':
4526 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
4527 $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;
4528 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
4529 $displayIniMessage = true;
4530 break;
4531
4532 case 'openssl':
4533 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
4534 $text .= "If possible you should enable it or recompile php with --with-openssl";
4535 break;
4536 }
4537 $out($text, 'error');
4538 }
4539
4540 $output .= PHP_EOL;
4541 }
4542
4543 if (!empty($warnings)) {
4544 foreach ($warnings as $warning => $current) {
4545 switch ($warning) {
4546 case 'apc_cli':
4547 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
4548 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
4549 $text .= "  apc.enable_cli = Off";
4550 $displayIniMessage = true;
4551 break;
4552
4553 case 'zlib':
4554 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
4555 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
4556 $displayIniMessage = true;
4557 break;
4558
4559 case 'sigchild':
4560 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
4561 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
4562 $text .= "  https://bugs.php.net/bug.php?id=22999";
4563 break;
4564
4565 case 'curlwrappers':
4566 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
4567 $text .= " Recompile it without this flag if possible";
4568 break;
4569
4570 case 'php':
4571 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
4572 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
4573 break;
4574
4575 case 'openssl_version':
4576
4577  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
4578 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
4579
4580 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
4581 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
4582 break;
4583
4584 case 'xdebug_loaded':
4585 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
4586 $text .= " Disabling it when using Composer is recommended.";
4587 break;
4588
4589 case 'xdebug_profile':
4590 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
4591 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
4592 $text .= "  xdebug.profiler_enabled = 0";
4593 $displayIniMessage = true;
4594 break;
4595
4596 case 'onedrive':
4597 $text = "The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10.".PHP_EOL;
4598 $text .= "Upgrade your PHP ({$current}) to use this location with Composer.".PHP_EOL;
4599 break;
4600 }
4601 $out($text, 'comment');
4602 }
4603 }
4604
4605 if ($displayIniMessage) {
4606 $out($iniMessage, 'comment');
4607 }
4608
4609 return !$warnings && !$errors ? true : $output;
4610 }
4611
4612
4613
4614
4615
4616
4617
4618 private function checkConnectivity()
4619 {
4620 if (!ini_get('allow_url_fopen')) {
4621 $result = '<info>Skipped because allow_url_fopen is missing.</info>';
4622 return $result;
4623 }
4624
4625 return true;
4626 }
4627 }
4628 <?php
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640 namespace Composer\Command;
4641
4642 use Composer\Plugin\CommandEvent;
4643 use Composer\Plugin\PluginEvents;
4644 use Symfony\Component\Console\Input\InputInterface;
4645 use Symfony\Component\Console\Input\InputOption;
4646 use Symfony\Component\Console\Output\OutputInterface;
4647
4648
4649
4650
4651 class DumpAutoloadCommand extends BaseCommand
4652 {
4653 protected function configure()
4654 {
4655 $this
4656 ->setName('dump-autoload')
4657 ->setAliases(array('dumpautoload'))
4658 ->setDescription('Dumps the autoloader.')
4659 ->setDefinition(array(
4660 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4661 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4662 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4663 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4664 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4665 ))
4666 ->setHelp(
4667 <<<EOT
4668 <info>php composer.phar dump-autoload</info>
4669
4670 Read more at https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload-
4671 EOT
4672 )
4673 ;
4674 }
4675
4676 protected function execute(InputInterface $input, OutputInterface $output)
4677 {
4678 $composer = $this->getComposer();
4679
4680 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4681 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4682
4683 $installationManager = $composer->getInstallationManager();
4684 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4685 $package = $composer->getPackage();
4686 $config = $composer->getConfig();
4687
4688 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4689 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4690 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4691
4692 if ($authoritative) {
4693 $this->getIO()->write('<info>Generating optimized autoload files (authoritative)</info>');
4694 } elseif ($optimize) {
4695 $this->getIO()->write('<info>Generating optimized autoload files</info>');
4696 } else {
4697 $this->getIO()->write('<info>Generating autoload files</info>');
4698 }
4699
4700 $generator = $composer->getAutoloadGenerator();
4701 $generator->setDevMode(!$input->getOption('no-dev'));
4702 $generator->setClassMapAuthoritative($authoritative);
4703 $generator->setApcu($apcu);
4704 $generator->setRunScripts(!$input->getOption('no-scripts'));
4705 $numberOfClasses = $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4706
4707 if ($authoritative) {
4708 $this->getIO()->write('<info>Generated optimized autoload files (authoritative) containing '. $numberOfClasses .' classes</info>');
4709 } elseif ($optimize) {
4710 $this->getIO()->write('<info>Generated optimized autoload files containing '. $numberOfClasses .' classes</info>');
4711 } else {
4712 $this->getIO()->write('<info>Generated autoload files</info>');
4713 }
4714
4715 return 0;
4716 }
4717 }
4718 <?php
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730 namespace Composer\Command;
4731
4732 use Symfony\Component\Console\Input\InputInterface;
4733 use Symfony\Component\Console\Input\InputOption;
4734 use Symfony\Component\Console\Output\OutputInterface;
4735 use Symfony\Component\Console\Input\InputArgument;
4736
4737
4738
4739
4740 class ExecCommand extends BaseCommand
4741 {
4742 protected function configure()
4743 {
4744 $this
4745 ->setName('exec')
4746 ->setDescription('Executes a vendored binary/script.')
4747 ->setDefinition(array(
4748 new InputOption('list', 'l', InputOption::VALUE_NONE),
4749 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4750 new InputArgument(
4751 'args',
4752 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4753 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4754 ),
4755 ))
4756 ->setHelp(
4757 <<<EOT
4758 Executes a vendored binary/script.
4759
4760 Read more at https://getcomposer.org/doc/03-cli.md#exec
4761 EOT
4762 )
4763 ;
4764 }
4765
4766 protected function execute(InputInterface $input, OutputInterface $output)
4767 {
4768 $composer = $this->getComposer();
4769 $binDir = $composer->getConfig()->get('bin-dir');
4770 if ($input->getOption('list') || !$input->getArgument('binary')) {
4771 $bins = glob($binDir . '/*');
4772 $bins = array_merge($bins, array_map(function ($e) {
4773 return "$e (local)";
4774 }, $composer->getPackage()->getBinaries()));
4775
4776 if (!$bins) {
4777 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4778 }
4779
4780 $this->getIO()->write(
4781 <<<EOT
4782 <comment>Available binaries:</comment>
4783 EOT
4784 );
4785
4786 foreach ($bins as $bin) {
4787
4788  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4789 continue;
4790 }
4791
4792 $previousBin = $bin;
4793 $bin = basename($bin);
4794 $this->getIO()->write(
4795 <<<EOT
4796 <info>- $bin</info>
4797 EOT
4798 );
4799 }
4800
4801 return 0;
4802 }
4803
4804 $binary = $input->getArgument('binary');
4805
4806 $dispatcher = $composer->getEventDispatcher();
4807 $dispatcher->addListener('__exec_command', $binary);
4808 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4809 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4810 }
4811
4812
4813  
4814  
4815  if (getcwd() !== $this->getApplication()->getInitialWorkingDirectory()) {
4816 try {
4817 chdir($this->getApplication()->getInitialWorkingDirectory());
4818 } catch (\Exception $e) {
4819 throw new \RuntimeException('Could not switch back to working directory "'.$this->getApplication()->getInitialWorkingDirectory().'"', 0, $e);
4820 }
4821 }
4822
4823 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4824 }
4825 }
4826 <?php
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838 namespace Composer\Command;
4839
4840 use Composer\Package\CompletePackageInterface;
4841 use Composer\Package\AliasPackage;
4842 use Composer\Repository\CompositeRepository;
4843 use Symfony\Component\Console\Input\InputInterface;
4844 use Symfony\Component\Console\Input\InputOption;
4845 use Symfony\Component\Console\Output\OutputInterface;
4846
4847
4848
4849
4850
4851 class FundCommand extends BaseCommand
4852 {
4853 protected function configure()
4854 {
4855 $this->setName('fund')
4856 ->setDescription('Discover how to help fund the maintenance of your dependencies.')
4857 ;
4858 }
4859
4860 protected function execute(InputInterface $input, OutputInterface $output)
4861 {
4862 $composer = $this->getComposer();
4863
4864 $repo = $composer->getRepositoryManager()->getLocalRepository();
4865 $remoteRepos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
4866 $fundings = array();
4867 foreach ($repo->getPackages() as $package) {
4868 if ($package instanceof AliasPackage) {
4869 continue;
4870 }
4871 $latest = $remoteRepos->findPackage($package->getName(), 'dev-master');
4872 if ($latest instanceof CompletePackageInterface && $latest->getFunding()) {
4873 $fundings = $this->insertFundingData($fundings, $latest);
4874 continue;
4875 }
4876 if ($package instanceof CompletePackageInterface && $package->getFunding()) {
4877 $fundings = $this->insertFundingData($fundings, $package);
4878 }
4879 }
4880
4881 ksort($fundings);
4882
4883 $io = $this->getIO();
4884
4885 if ($fundings) {
4886 $prev = null;
4887
4888 $io->write('The following packages were found in your dependencies which publish funding information:');
4889
4890 foreach ($fundings as $vendor => $links) {
4891 $io->write('');
4892 $io->write(sprintf("<comment>%s</comment>", $vendor));
4893 foreach ($links as $url => $packages) {
4894 $line = sprintf('  <info>%s</info>', implode(', ', $packages));
4895
4896 if ($prev !== $line) {
4897 $io->write($line);
4898 $prev = $line;
4899 }
4900
4901 $io->write(sprintf('    %s', $url));
4902 }
4903 }
4904
4905 $io->write("");
4906 $io->write("Please consider following these links and sponsoring the work of package authors!");
4907 $io->write("Thank you!");
4908 } else {
4909 $io->write("No funding links were found in your package dependencies. This doesn't mean they don't need your support!");
4910 }
4911
4912 return 0;
4913 }
4914
4915 private function insertFundingData(array $fundings, CompletePackageInterface $package)
4916 {
4917 foreach ($package->getFunding() as $fundingOption) {
4918 list($vendor, $packageName) = explode('/', $package->getPrettyName());
4919
4920  if (empty($fundingOption['url'])) {
4921 continue;
4922 }
4923 $url = $fundingOption['url'];
4924 if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && preg_match('{^https://github.com/([^/]+)$}', $url, $match)) {
4925 $url = 'https://github.com/sponsors/'.$match[1];
4926 }
4927 $fundings[$vendor][$url][] = $packageName;
4928 }
4929
4930 return $fundings;
4931 }
4932 }
4933 <?php
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945 namespace Composer\Command;
4946
4947 use Composer\Factory;
4948 use Composer\Util\Filesystem;
4949 use Symfony\Component\Console\Input\InputInterface;
4950 use Symfony\Component\Console\Input\InputArgument;
4951 use Symfony\Component\Console\Input\StringInput;
4952 use Symfony\Component\Console\Output\OutputInterface;
4953
4954
4955
4956
4957 class GlobalCommand extends BaseCommand
4958 {
4959 protected function configure()
4960 {
4961 $this
4962 ->setName('global')
4963 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4964 ->setDefinition(array(
4965 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4966 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4967 ))
4968 ->setHelp(
4969 <<<EOT
4970 Use this command as a wrapper to run other Composer commands
4971 within the global context of COMPOSER_HOME.
4972
4973 You can use this to install CLI utilities globally, all you need
4974 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4975
4976 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4977 and /home/<user>/.composer on unix systems.
4978
4979 If your system uses freedesktop.org standards, then it will first check
4980 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4981
4982 Note: This path may vary depending on customizations to bin-dir in
4983 composer.json or the environmental variable COMPOSER_BIN_DIR.
4984
4985 Read more at https://getcomposer.org/doc/03-cli.md#global
4986 EOT
4987 )
4988 ;
4989 }
4990
4991 public function run(InputInterface $input, OutputInterface $output)
4992 {
4993
4994  $tokens = preg_split('{\s+}', $input->__toString());
4995 $args = array();
4996 foreach ($tokens as $token) {
4997 if ($token && $token[0] !== '-') {
4998 $args[] = $token;
4999 if (count($args) >= 2) {
5000 break;
5001 }
5002 }
5003 }
5004
5005
5006  if (count($args) < 2) {
5007 return parent::run($input, $output);
5008 }
5009
5010
5011  $config = Factory::createConfig();
5012 $home = $config->get('home');
5013
5014 if (!is_dir($home)) {
5015 $fs = new Filesystem();
5016 $fs->ensureDirectoryExists($home);
5017 if (!is_dir($home)) {
5018 throw new \RuntimeException('Could not create home directory');
5019 }
5020 }
5021
5022 try {
5023 chdir($home);
5024 } catch (\Exception $e) {
5025 throw new \RuntimeException('Could not switch to home directory "'.$home.'"', 0, $e);
5026 }
5027 $this->getIO()->writeError('<info>Changed current directory to '.$home.'</info>');
5028
5029
5030  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
5031 $this->getApplication()->resetComposer();
5032
5033 return $this->getApplication()->run($input, $output);
5034 }
5035
5036
5037
5038
5039 public function isProxyCommand()
5040 {
5041 return true;
5042 }
5043 }
5044 <?php
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056 namespace Composer\Command;
5057
5058 use Composer\Package\CompletePackageInterface;
5059 use Composer\Repository\RepositoryInterface;
5060 use Composer\Repository\ArrayRepository;
5061 use Composer\Repository\RepositoryFactory;
5062 use Composer\Util\Platform;
5063 use Composer\Util\ProcessExecutor;
5064 use Symfony\Component\Console\Input\InputArgument;
5065 use Symfony\Component\Console\Input\InputOption;
5066 use Symfony\Component\Console\Input\InputInterface;
5067 use Symfony\Component\Console\Output\OutputInterface;
5068
5069
5070
5071
5072 class HomeCommand extends BaseCommand
5073 {
5074
5075
5076
5077 protected function configure()
5078 {
5079 $this
5080 ->setName('browse')
5081 ->setAliases(array('home'))
5082 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
5083 ->setDefinition(array(
5084 new InputArgument('packages', InputArgument::IS_ARRAY, 'Package(s) to browse to.'),
5085 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
5086 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
5087 ))
5088 ->setHelp(
5089 <<<EOT
5090 The home command opens or shows a package's repository URL or
5091 homepage in your default browser.
5092
5093 To open the homepage by default, use -H or --homepage.
5094 To show instead of open the repository or homepage URL, use -s or --show.
5095
5096 Read more at https://getcomposer.org/doc/03-cli.md#browse-home
5097 EOT
5098 );
5099 }
5100
5101
5102
5103
5104 protected function execute(InputInterface $input, OutputInterface $output)
5105 {
5106 $repos = $this->initializeRepos();
5107 $io = $this->getIO();
5108 $return = 0;
5109
5110 $packages = $input->getArgument('packages');
5111 if (!$packages) {
5112 $io->writeError('No package specified, opening homepage for the root package');
5113 $packages = array($this->getComposer()->getPackage()->getName());
5114 }
5115
5116 foreach ($packages as $packageName) {
5117 $handled = false;
5118 $packageExists = false;
5119 foreach ($repos as $repo) {
5120 foreach ($repo->findPackages($packageName) as $package) {
5121 $packageExists = true;
5122 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
5123 $handled = true;
5124 break 2;
5125 }
5126 }
5127 }
5128
5129 if (!$packageExists) {
5130 $return = 1;
5131 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
5132 }
5133
5134 if (!$handled) {
5135 $return = 1;
5136 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
5137 }
5138 }
5139
5140 return $return;
5141 }
5142
5143 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
5144 {
5145 $support = $package->getSupport();
5146 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
5147 if (!$url || $showHomepage) {
5148 $url = $package->getHomepage();
5149 }
5150
5151 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
5152 return false;
5153 }
5154
5155 if ($showOnly) {
5156 $this->getIO()->write(sprintf('<info>%s</info>', $url));
5157 } else {
5158 $this->openBrowser($url);
5159 }
5160
5161 return true;
5162 }
5163
5164
5165
5166
5167
5168
5169 private function openBrowser($url)
5170 {
5171 $url = ProcessExecutor::escape($url);
5172
5173 $process = new ProcessExecutor($this->getIO());
5174 if (Platform::isWindows()) {
5175 return $process->execute('start "web" explorer "' . $url . '"', $output);
5176 }
5177
5178 $linux = $process->execute('which xdg-open', $output);
5179 $osx = $process->execute('which open', $output);
5180
5181 if (0 === $linux) {
5182 $process->execute('xdg-open ' . $url, $output);
5183 } elseif (0 === $osx) {
5184 $process->execute('open ' . $url, $output);
5185 } else {
5186 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
5187 }
5188 }
5189
5190
5191
5192
5193
5194
5195
5196
5197 private function initializeRepos()
5198 {
5199 $composer = $this->getComposer(false);
5200
5201 if ($composer) {
5202 return array_merge(
5203 array(new ArrayRepository(array($composer->getPackage()))), 
5204  array($composer->getRepositoryManager()->getLocalRepository()), 
5205  $composer->getRepositoryManager()->getRepositories() 
5206  );
5207 }
5208
5209 return RepositoryFactory::defaultRepos($this->getIO());
5210 }
5211 }
5212 <?php
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224 namespace Composer\Command;
5225
5226 use Composer\DependencyResolver\Pool;
5227 use Composer\Factory;
5228 use Composer\Json\JsonFile;
5229 use Composer\Package\BasePackage;
5230 use Composer\Package\Package;
5231 use Composer\Package\Version\VersionParser;
5232 use Composer\Package\Version\VersionSelector;
5233 use Composer\Repository\CompositeRepository;
5234 use Composer\Repository\PlatformRepository;
5235 use Composer\Repository\RepositoryFactory;
5236 use Composer\Util\ProcessExecutor;
5237 use Symfony\Component\Console\Input\ArrayInput;
5238 use Symfony\Component\Console\Input\InputInterface;
5239 use Symfony\Component\Console\Input\InputOption;
5240 use Symfony\Component\Console\Output\OutputInterface;
5241 use Symfony\Component\Process\ExecutableFinder;
5242 use Symfony\Component\Process\Process;
5243
5244
5245
5246
5247
5248 class InitCommand extends BaseCommand
5249 {
5250
5251 protected $repos;
5252
5253
5254 private $gitConfig;
5255
5256
5257 private $pools;
5258
5259
5260
5261
5262 protected function configure()
5263 {
5264 $this
5265 ->setName('init')
5266 ->setDescription('Creates a basic composer.json file in current directory.')
5267 ->setDefinition(array(
5268 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
5269 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
5270 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
5271
5272  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
5273 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
5274 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"'),
5275 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"'),
5276 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
5277 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
5278 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
5279 ))
5280 ->setHelp(
5281 <<<EOT
5282 The <info>init</info> command creates a basic composer.json file
5283 in the current directory.
5284
5285 <info>php composer.phar init</info>
5286
5287 Read more at https://getcomposer.org/doc/03-cli.md#init
5288 EOT
5289 )
5290 ;
5291 }
5292
5293
5294
5295
5296 protected function execute(InputInterface $input, OutputInterface $output)
5297 {
5298 $io = $this->getIO();
5299
5300 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
5301 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
5302
5303 if (isset($options['author'])) {
5304 $options['authors'] = $this->formatAuthors($options['author']);
5305 unset($options['author']);
5306 }
5307
5308 $repositories = $input->getOption('repository');
5309 if ($repositories) {
5310 $config = Factory::createConfig($io);
5311 foreach ($repositories as $repo) {
5312 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
5313 }
5314 }
5315
5316 if (isset($options['stability'])) {
5317 $options['minimum-stability'] = $options['stability'];
5318 unset($options['stability']);
5319 }
5320
5321 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
5322 if (array() === $options['require']) {
5323 $options['require'] = new \stdClass;
5324 }
5325
5326 if (isset($options['require-dev'])) {
5327 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
5328 if (array() === $options['require-dev']) {
5329 $options['require-dev'] = new \stdClass;
5330 }
5331 }
5332
5333 $file = new JsonFile(Factory::getComposerFile());
5334 $json = $file->encode($options);
5335
5336 if ($input->isInteractive()) {
5337 $io->writeError(array('', $json, ''));
5338 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
5339 $io->writeError('<error>Command aborted</error>');
5340
5341 return 1;
5342 }
5343 }
5344
5345 $file->write($options);
5346
5347 if ($input->isInteractive() && is_dir('.git')) {
5348 $ignoreFile = realpath('.gitignore');
5349
5350 if (false === $ignoreFile) {
5351 $ignoreFile = realpath('.') . '/.gitignore';
5352 }
5353
5354 if (!$this->hasVendorIgnore($ignoreFile)) {
5355 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
5356
5357 if ($io->askConfirmation($question, true)) {
5358 $this->addVendorIgnore($ignoreFile);
5359 }
5360 }
5361 }
5362
5363 $question = 'Would you like to install dependencies now [<comment>yes</comment>]? ';
5364 if ($input->isInteractive() && $this->hasDependencies($options) && $io->askConfirmation($question, true)) {
5365 $this->installDependencies($output);
5366 }
5367
5368 return 0;
5369 }
5370
5371
5372
5373
5374 protected function interact(InputInterface $input, OutputInterface $output)
5375 {
5376 $git = $this->getGitConfig();
5377 $io = $this->getIO();
5378 $formatter = $this->getHelperSet()->get('formatter');
5379
5380
5381  $repositories = $input->getOption('repository');
5382 if ($repositories) {
5383 $config = Factory::createConfig($io);
5384 $repos = array(new PlatformRepository);
5385 $createDefaultPackagistRepo = true;
5386 foreach ($repositories as $repo) {
5387 $repoConfig = RepositoryFactory::configFromString($io, $config, $repo);
5388 if (
5389 (isset($repoConfig['packagist']) && $repoConfig === array('packagist' => false))
5390 || (isset($repoConfig['packagist.org']) && $repoConfig === array('packagist.org' => false))
5391 ) {
5392 $createDefaultPackagistRepo = false;
5393 continue;
5394 }
5395 $repos[] = RepositoryFactory::createRepo($io, $config, $repoConfig);
5396 }
5397
5398 if ($createDefaultPackagistRepo) {
5399 $repos[] = RepositoryFactory::createRepo($io, $config, array(
5400 'type' => 'composer',
5401 'url' => 'https://repo.packagist.org',
5402 ));
5403 }
5404
5405 $this->repos = new CompositeRepository($repos);
5406 unset($repos, $config, $repositories);
5407 }
5408
5409 $io->writeError(array(
5410 '',
5411 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
5412 '',
5413 ));
5414
5415
5416  $io->writeError(array(
5417 '',
5418 'This command will guide you through creating your composer.json config.',
5419 '',
5420 ));
5421
5422 $cwd = realpath(".");
5423
5424 if (!$name = $input->getOption('name')) {
5425 $name = basename($cwd);
5426 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
5427 $name = strtolower($name);
5428 if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) {
5429 $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name;
5430 } elseif (isset($git['github.user'])) {
5431 $name = $git['github.user'] . '/' . $name;
5432 } elseif (!empty($_SERVER['USERNAME'])) {
5433 $name = $_SERVER['USERNAME'] . '/' . $name;
5434 } elseif (!empty($_SERVER['USER'])) {
5435 $name = $_SERVER['USER'] . '/' . $name;
5436 } elseif (get_current_user()) {
5437 $name = get_current_user() . '/' . $name;
5438 } else {
5439
5440  $name .= '/' . $name;
5441 }
5442 $name = strtolower($name);
5443 } else {
5444 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $name)) {
5445 throw new \InvalidArgumentException(
5446 '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_.-]+'
5447 );
5448 }
5449 }
5450
5451 $name = $io->askAndValidate(
5452 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
5453 function ($value) use ($name) {
5454 if (null === $value) {
5455 return $name;
5456 }
5457
5458 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $value)) {
5459 throw new \InvalidArgumentException(
5460 '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_.-]+'
5461 );
5462 }
5463
5464 return $value;
5465 },
5466 null,
5467 $name
5468 );
5469 $input->setOption('name', $name);
5470
5471 $description = $input->getOption('description') ?: false;
5472 $description = $io->ask(
5473 'Description [<comment>'.$description.'</comment>]: ',
5474 $description
5475 );
5476 $input->setOption('description', $description);
5477
5478 if (null === $author = $input->getOption('author')) {
5479 if (!empty($_SERVER['COMPOSER_DEFAULT_AUTHOR'])) {
5480 $author_name = $_SERVER['COMPOSER_DEFAULT_AUTHOR'];
5481 } elseif (isset($git['user.name'])) {
5482 $author_name = $git['user.name'];
5483 }
5484
5485 if (!empty($_SERVER['COMPOSER_DEFAULT_EMAIL'])) {
5486 $author_email = $_SERVER['COMPOSER_DEFAULT_EMAIL'];
5487 } elseif (isset($git['user.email'])) {
5488 $author_email = $git['user.email'];
5489 }
5490
5491 if (isset($author_name) && isset($author_email)) {
5492 $author = sprintf('%s <%s>', $author_name, $author_email);
5493 }
5494 }
5495
5496 $self = $this;
5497 $author = $io->askAndValidate(
5498 'Author [<comment>'.$author.'</comment>, n to skip]: ',
5499 function ($value) use ($self, $author) {
5500 if ($value === 'n' || $value === 'no') {
5501 return;
5502 }
5503 $value = $value ?: $author;
5504 $author = $self->parseAuthorString($value);
5505
5506 return sprintf('%s <%s>', $author['name'], $author['email']);
5507 },
5508 null,
5509 $author
5510 );
5511 $input->setOption('author', $author);
5512
5513 $minimumStability = $input->getOption('stability') ?: null;
5514 $minimumStability = $io->askAndValidate(
5515 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
5516 function ($value) use ($minimumStability) {
5517 if (null === $value) {
5518 return $minimumStability;
5519 }
5520
5521 if (!isset(BasePackage::$stabilities[$value])) {
5522 throw new \InvalidArgumentException(
5523 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
5524 implode(', ', array_keys(BasePackage::$stabilities))
5525 );
5526 }
5527
5528 return $value;
5529 },
5530 null,
5531 $minimumStability
5532 );
5533 $input->setOption('stability', $minimumStability);
5534
5535 $type = $input->getOption('type') ?: false;
5536 $type = $io->ask(
5537 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
5538 $type
5539 );
5540 $input->setOption('type', $type);
5541
5542 if (null === $license = $input->getOption('license')) {
5543 if (!empty($_SERVER['COMPOSER_DEFAULT_LICENSE'])) {
5544 $license = $_SERVER['COMPOSER_DEFAULT_LICENSE'];
5545 }
5546 }
5547
5548 $license = $io->ask(
5549 'License [<comment>'.$license.'</comment>]: ',
5550 $license
5551 );
5552 $input->setOption('license', $license);
5553
5554 $io->writeError(array('', 'Define your dependencies.', ''));
5555
5556
5557  $repos = $this->getRepos();
5558 $preferredStability = $minimumStability ?: 'stable';
5559 $phpVersion = $repos->findPackage('php', '*')->getPrettyVersion();
5560
5561 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
5562 $require = $input->getOption('require');
5563 $requirements = array();
5564 if ($require || $io->askConfirmation($question, true)) {
5565 $requirements = $this->determineRequirements($input, $output, $require, $phpVersion, $preferredStability);
5566 }
5567 $input->setOption('require', $requirements);
5568
5569 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
5570 $requireDev = $input->getOption('require-dev');
5571 $devRequirements = array();
5572 if ($requireDev || $io->askConfirmation($question, true)) {
5573 $devRequirements = $this->determineRequirements($input, $output, $requireDev, $phpVersion, $preferredStability);
5574 }
5575 $input->setOption('require-dev', $devRequirements);
5576 }
5577
5578
5579
5580
5581
5582
5583 public function parseAuthorString($author)
5584 {
5585 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
5586 if ($this->isValidEmail($match['email'])) {
5587 return array(
5588 'name' => trim($match['name']),
5589 'email' => $match['email'],
5590 );
5591 }
5592 }
5593
5594 throw new \InvalidArgumentException(
5595 'Invalid author string.  Must be in the format: '.
5596 'John Smith <john@example.com>'
5597 );
5598 }
5599
5600 protected function findPackages($name)
5601 {
5602 return $this->getRepos()->search($name);
5603 }
5604
5605 protected function getRepos()
5606 {
5607 if (!$this->repos) {
5608 $this->repos = new CompositeRepository(array_merge(
5609 array(new PlatformRepository),
5610 RepositoryFactory::defaultRepos($this->getIO())
5611 ));
5612 }
5613
5614 return $this->repos;
5615 }
5616
5617 final protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true, $fixed = false)
5618 {
5619 if ($requires) {
5620 $requires = $this->normalizeRequirements($requires);
5621 $result = array();
5622 $io = $this->getIO();
5623
5624 foreach ($requires as $requirement) {
5625 if (!isset($requirement['version'])) {
5626
5627  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, null, null, $fixed);
5628 $requirement['version'] = $version;
5629
5630
5631  $requirement['name'] = $name;
5632
5633 $io->writeError(sprintf(
5634 'Using version <info>%s</info> for <info>%s</info>',
5635 $requirement['version'],
5636 $requirement['name']
5637 ));
5638 } else {
5639
5640  list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev', $fixed);
5641
5642
5643  $requirement['name'] = $name;
5644 }
5645
5646 $result[] = $requirement['name'] . ' ' . $requirement['version'];
5647 }
5648
5649 return $result;
5650 }
5651
5652 $versionParser = new VersionParser();
5653
5654
5655  $composer = $this->getComposer(false);
5656 $installedRepo = $composer ? $composer->getRepositoryManager()->getLocalRepository() : null;
5657 $existingPackages = array();
5658 if ($installedRepo) {
5659 foreach ($installedRepo->getPackages() as $package) {
5660 $existingPackages[] = $package->getName();
5661 }
5662 }
5663 foreach ($requires as $requiredPackage) {
5664 $existingPackages[] = substr($requiredPackage, 0, strpos($requiredPackage, ' '));
5665 }
5666 unset($composer, $installedRepo, $requiredPackage);
5667
5668 $io = $this->getIO();
5669 while (null !== $package = $io->ask('Search for a package: ')) {
5670 $matches = $this->findPackages($package);
5671
5672 if (count($matches)) {
5673
5674  foreach ($matches as $position => $foundPackage) {
5675 if (in_array($foundPackage['name'], $existingPackages, true)) {
5676 unset($matches[$position]);
5677 }
5678 }
5679 $matches = array_values($matches);
5680
5681 $exactMatch = null;
5682 $choices = array();
5683 foreach ($matches as $position => $foundPackage) {
5684 $abandoned = '';
5685 if (isset($foundPackage['abandoned'])) {
5686 if (is_string($foundPackage['abandoned'])) {
5687 $replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
5688 } else {
5689 $replacement = 'No replacement was suggested';
5690 }
5691 $abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
5692 }
5693
5694 $choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
5695 if ($foundPackage['name'] === $package) {
5696 $exactMatch = true;
5697 break;
5698 }
5699 }
5700
5701
5702  if (!$exactMatch) {
5703 $io->writeError(array(
5704 '',
5705 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
5706 '',
5707 ));
5708
5709 $io->writeError($choices);
5710 $io->writeError('');
5711
5712 $validator = function ($selection) use ($matches, $versionParser) {
5713 if ('' === $selection) {
5714 return false;
5715 }
5716
5717 if (is_numeric($selection) && isset($matches[(int) $selection])) {
5718 $package = $matches[(int) $selection];
5719
5720 return $package['name'];
5721 }
5722
5723 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
5724 if (isset($packageMatches['version'])) {
5725
5726
5727
5728  $versionParser->parseConstraints($packageMatches['version']);
5729
5730 return $packageMatches['name'].' '.$packageMatches['version'];
5731 }
5732
5733
5734  return $packageMatches['name'];
5735 }
5736
5737 throw new \Exception('Not a valid selection');
5738 };
5739
5740 $package = $io->askAndValidate(
5741 'Enter package # to add, or the complete package name if it is not listed: ',
5742 $validator,
5743 3,
5744 false
5745 );
5746 }
5747
5748
5749  if (false !== $package && false === strpos($package, ' ')) {
5750 $validator = function ($input) {
5751 $input = trim($input);
5752
5753 return $input ?: false;
5754 };
5755
5756 $constraint = $io->askAndValidate(
5757 'Enter the version constraint to require (or leave blank to use the latest version): ',
5758 $validator,
5759 3,
5760 false
5761 );
5762
5763 if (false === $constraint) {
5764 list($name, $constraint) = $this->findBestVersionAndNameForPackage($input, $package, $phpVersion, $preferredStability);
5765
5766 $io->writeError(sprintf(
5767 'Using version <info>%s</info> for <info>%s</info>',
5768 $constraint,
5769 $package
5770 ));
5771 }
5772
5773 $package .= ' '.$constraint;
5774 }
5775
5776 if (false !== $package) {
5777 $requires[] = $package;
5778 $existingPackages[] = substr($package, 0, strpos($package, ' '));
5779 }
5780 }
5781 }
5782
5783 return $requires;
5784 }
5785
5786 protected function formatAuthors($author)
5787 {
5788 return array($this->parseAuthorString($author));
5789 }
5790
5791 protected function formatRequirements(array $requirements)
5792 {
5793 $requires = array();
5794 $requirements = $this->normalizeRequirements($requirements);
5795 foreach ($requirements as $requirement) {
5796 $requires[$requirement['name']] = $requirement['version'];
5797 }
5798
5799 return $requires;
5800 }
5801
5802 protected function getGitConfig()
5803 {
5804 if (null !== $this->gitConfig) {
5805 return $this->gitConfig;
5806 }
5807
5808 $finder = new ExecutableFinder();
5809 $gitBin = $finder->find('git');
5810
5811
5812  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
5813 $cmd = new Process(array($gitBin, 'config', '-l'));
5814 } else {
5815 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
5816 }
5817 $cmd->run();
5818
5819 if ($cmd->isSuccessful()) {
5820 $this->gitConfig = array();
5821 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
5822 foreach ($matches as $match) {
5823 $this->gitConfig[$match[1]] = $match[2];
5824 }
5825
5826 return $this->gitConfig;
5827 }
5828
5829 return $this->gitConfig = array();
5830 }
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
5849 {
5850 if (!file_exists($ignoreFile)) {
5851 return false;
5852 }
5853
5854 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
5855
5856 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
5857 foreach ($lines as $line) {
5858 if (preg_match($pattern, $line)) {
5859 return true;
5860 }
5861 }
5862
5863 return false;
5864 }
5865
5866 protected function normalizeRequirements(array $requirements)
5867 {
5868 $parser = new VersionParser();
5869
5870 return $parser->parseNameVersionPairs($requirements);
5871 }
5872
5873 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
5874 {
5875 $contents = "";
5876 if (file_exists($ignoreFile)) {
5877 $contents = file_get_contents($ignoreFile);
5878
5879 if ("\n" !== substr($contents, 0, -1)) {
5880 $contents .= "\n";
5881 }
5882 }
5883
5884 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5885 }
5886
5887 protected function isValidEmail($email)
5888 {
5889
5890  if (!function_exists('filter_var')) {
5891 return true;
5892 }
5893
5894
5895  if (PHP_VERSION_ID < 50303) {
5896 return true;
5897 }
5898
5899 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5900 }
5901
5902 private function getPool(InputInterface $input, $minimumStability = null)
5903 {
5904 $key = $minimumStability ?: 'default';
5905
5906 if (!isset($this->pools[$key])) {
5907 $this->pools[$key] = $pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5908 $pool->addRepository($this->getRepos());
5909 }
5910
5911 return $this->pools[$key];
5912 }
5913
5914 private function getMinimumStability(InputInterface $input)
5915 {
5916 if ($input->hasOption('stability')) {
5917 return VersionParser::normalizeStability($input->getOption('stability') ?: 'stable');
5918 }
5919
5920 $file = Factory::getComposerFile();
5921 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5922 if (!empty($composer['minimum-stability'])) {
5923 return VersionParser::normalizeStability($composer['minimum-stability']);
5924 }
5925 }
5926
5927 return 'stable';
5928 }
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945 private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null, $fixed = null)
5946 {
5947
5948  $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5949 $ignorePlatformReqs = $input->hasOption('ignore-platform-reqs') && $input->getOption('ignore-platform-reqs');
5950
5951
5952  if ($ignorePlatformReqs) {
5953 $phpVersion = null;
5954 }
5955
5956 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5957
5958 if (!$package) {
5959
5960  
5961  if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
5962 return array($name, $requiredVersion ?: '*');
5963 }
5964
5965
5966  if ($phpVersion && $versionSelector->findBestCandidate($name, $requiredVersion, null, $preferredStability)) {
5967 throw new \InvalidArgumentException(sprintf(
5968 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)',
5969 $name,
5970 $requiredVersion,
5971 $phpVersion
5972 ));
5973 }
5974
5975  if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
5976 throw new \InvalidArgumentException(sprintf(
5977 'Could not find package %s in a version matching %s',
5978 $name,
5979 $requiredVersion
5980 ));
5981 }
5982
5983  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5984 throw new \InvalidArgumentException(sprintf(
5985 'Could not find package %s in any version matching your PHP version (%s)',
5986 $name,
5987 $phpVersion
5988 ));
5989 }
5990
5991
5992  $similar = $this->findSimilar($name);
5993 if ($similar) {
5994
5995  if ($requiredVersion === null && in_array($name, $similar, true)) {
5996 throw new \InvalidArgumentException(sprintf(
5997 'Could not find a version of package %s matching your minimum-stability (%s). Require it with an explicit version constraint allowing its desired stability.',
5998 $name,
5999 $this->getMinimumStability($input)
6000 ));
6001 }
6002
6003 throw new \InvalidArgumentException(sprintf(
6004 "Could not find package %s.\n\nDid you mean " . (count($similar) > 1 ? 'one of these' : 'this') . "?\n    %s",
6005 $name,
6006 implode("\n    ", $similar)
6007 ));
6008 }
6009
6010 throw new \InvalidArgumentException(sprintf(
6011 '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).',
6012 $name,
6013 $this->getMinimumStability($input)
6014 ));
6015 }
6016
6017 return array(
6018 $package->getPrettyName(),
6019 $fixed ? $package->getPrettyVersion() : $versionSelector->findRecommendedRequireVersion($package),
6020 );
6021 }
6022
6023 private function findSimilar($package)
6024 {
6025 try {
6026 $results = $this->repos->search($package);
6027 } catch (\Exception $e) {
6028
6029  return array();
6030 }
6031 $similarPackages = array();
6032
6033 $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
6034
6035 foreach ($results as $result) {
6036 if ($installedRepo->findPackage($result['name'], '*')) {
6037
6038  continue;
6039 }
6040 $similarPackages[$result['name']] = levenshtein($package, $result['name']);
6041 }
6042 asort($similarPackages);
6043
6044 return array_keys(array_slice($similarPackages, 0, 5));
6045 }
6046
6047 private function installDependencies($output)
6048 {
6049 try {
6050 $installCommand = $this->getApplication()->find('install');
6051 $installCommand->run(new ArrayInput(array()), $output);
6052 } catch (\Exception $e) {
6053 $this->getIO()->writeError('Could not install dependencies. Run `composer install` to see more information.');
6054 }
6055
6056 }
6057
6058 private function hasDependencies($options)
6059 {
6060 $requires = (array) $options['require'];
6061 $devRequires = isset($options['require-dev']) ? (array) $options['require-dev'] : array();
6062
6063 return !empty($requires) || !empty($devRequires);
6064 }
6065 }
6066 <?php
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078 namespace Composer\Command;
6079
6080 use Composer\Installer;
6081 use Composer\Plugin\CommandEvent;
6082 use Composer\Plugin\PluginEvents;
6083 use Symfony\Component\Console\Input\InputInterface;
6084 use Symfony\Component\Console\Input\InputOption;
6085 use Symfony\Component\Console\Input\InputArgument;
6086 use Symfony\Component\Console\Output\OutputInterface;
6087
6088
6089
6090
6091
6092
6093
6094 class InstallCommand extends BaseCommand
6095 {
6096 protected function configure()
6097 {
6098 $this
6099 ->setName('install')
6100 ->setAliases(array('i'))
6101 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
6102 ->setDefinition(array(
6103 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
6104 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
6105 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
6106 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
6107 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
6108 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
6109 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
6110 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6111 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6112 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
6113 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
6114 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6115 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6116 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6117 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6118 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
6119 ))
6120 ->setHelp(
6121 <<<EOT
6122 The <info>install</info> command reads the composer.lock file from
6123 the current directory, processes it, and downloads and installs all the
6124 libraries and dependencies outlined in that file. If the file does not
6125 exist it will look for composer.json and do the same.
6126
6127 <info>php composer.phar install</info>
6128
6129 Read more at https://getcomposer.org/doc/03-cli.md#install-i
6130 EOT
6131 )
6132 ;
6133 }
6134
6135 protected function execute(InputInterface $input, OutputInterface $output)
6136 {
6137 $io = $this->getIO();
6138 if ($args = $input->getArgument('packages')) {
6139 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
6140
6141 return 1;
6142 }
6143
6144 if ($input->getOption('no-custom-installers')) {
6145 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
6146 $input->setOption('no-plugins', true);
6147 }
6148
6149 if ($input->getOption('dev')) {
6150 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
6151 }
6152
6153 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6154 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6155
6156 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
6157 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6158
6159 $install = Installer::create($io, $composer);
6160
6161 $config = $composer->getConfig();
6162 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
6163
6164 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
6165 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
6166 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
6167
6168 $install
6169 ->setDryRun($input->getOption('dry-run'))
6170 ->setVerbose($input->getOption('verbose'))
6171 ->setPreferSource($preferSource)
6172 ->setPreferDist($preferDist)
6173 ->setDevMode(!$input->getOption('no-dev'))
6174 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
6175 ->setRunScripts(!$input->getOption('no-scripts'))
6176 ->setSkipSuggest($input->getOption('no-suggest'))
6177 ->setOptimizeAutoloader($optimize)
6178 ->setClassMapAuthoritative($authoritative)
6179 ->setApcuAutoloader($apcu)
6180 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6181 ;
6182
6183 if ($input->getOption('no-plugins')) {
6184 $install->disablePlugins();
6185 }
6186
6187 return $install->run();
6188 }
6189 }
6190 <?php
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202 namespace Composer\Command;
6203
6204 use Composer\Json\JsonFile;
6205 use Composer\Plugin\CommandEvent;
6206 use Composer\Plugin\PluginEvents;
6207 use Composer\Package\PackageInterface;
6208 use Composer\Repository\RepositoryInterface;
6209 use Symfony\Component\Console\Helper\Table;
6210 use Symfony\Component\Console\Input\InputInterface;
6211 use Symfony\Component\Console\Input\InputOption;
6212 use Symfony\Component\Console\Output\OutputInterface;
6213
6214
6215
6216
6217 class LicensesCommand extends BaseCommand
6218 {
6219 protected function configure()
6220 {
6221 $this
6222 ->setName('licenses')
6223 ->setDescription('Shows information about licenses of dependencies.')
6224 ->setDefinition(array(
6225 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6226 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
6227 ))
6228 ->setHelp(
6229 <<<EOT
6230 The license command displays detailed information about the licenses of
6231 the installed dependencies.
6232
6233 Read more at https://getcomposer.org/doc/03-cli.md#licenses
6234 EOT
6235 )
6236 ;
6237 }
6238
6239 protected function execute(InputInterface $input, OutputInterface $output)
6240 {
6241 $composer = $this->getComposer();
6242
6243 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
6244 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6245
6246 $root = $composer->getPackage();
6247 $repo = $composer->getRepositoryManager()->getLocalRepository();
6248
6249 if ($input->getOption('no-dev')) {
6250 $packages = $this->filterRequiredPackages($repo, $root);
6251 } else {
6252 $packages = $this->appendPackages($repo->getPackages(), array());
6253 }
6254
6255 ksort($packages);
6256 $io = $this->getIO();
6257
6258 switch ($format = $input->getOption('format')) {
6259 case 'text':
6260 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
6261 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
6262 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
6263 $io->write('Dependencies:');
6264 $io->write('');
6265
6266 $table = new Table($output);
6267 $table->setStyle('compact');
6268 $tableStyle = $table->getStyle();
6269 if (method_exists($tableStyle, 'setVerticalBorderChars')) {
6270 $tableStyle->setVerticalBorderChars('');
6271 } else {
6272 $tableStyle->setVerticalBorderChar('');
6273 }
6274 $tableStyle->setCellRowContentFormat('%s  ');
6275 $table->setHeaders(array('Name', 'Version', 'License'));
6276 foreach ($packages as $package) {
6277 $table->addRow(array(
6278 $package->getPrettyName(),
6279 $package->getFullPrettyVersion(),
6280 implode(', ', $package->getLicense()) ?: 'none',
6281 ));
6282 }
6283 $table->render();
6284 break;
6285
6286 case 'json':
6287 $dependencies = array();
6288 foreach ($packages as $package) {
6289 $dependencies[$package->getPrettyName()] = array(
6290 'version' => $package->getFullPrettyVersion(),
6291 'license' => $package->getLicense(),
6292 );
6293 }
6294
6295 $io->write(JsonFile::encode(array(
6296 'name' => $root->getPrettyName(),
6297 'version' => $root->getFullPrettyVersion(),
6298 'license' => $root->getLicense(),
6299 'dependencies' => $dependencies,
6300 )));
6301 break;
6302
6303 default:
6304 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
6305 }
6306
6307 return 0;
6308 }
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
6319 {
6320 $requires = array_keys($package->getRequires());
6321
6322 $packageListNames = array_keys($bucket);
6323 $packages = array_filter(
6324 $repo->getPackages(),
6325 function ($package) use ($requires, $packageListNames) {
6326 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
6327 }
6328 );
6329
6330 $bucket = $this->appendPackages($packages, $bucket);
6331
6332 foreach ($packages as $package) {
6333 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
6334 }
6335
6336 return $bucket;
6337 }
6338
6339
6340
6341
6342
6343
6344
6345
6346 public function appendPackages(array $packages, array $bucket)
6347 {
6348 foreach ($packages as $package) {
6349 $bucket[$package->getName()] = $package;
6350 }
6351
6352 return $bucket;
6353 }
6354 }
6355 <?php
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367 namespace Composer\Command;
6368
6369 use Symfony\Component\Console\Input\InputInterface;
6370 use Symfony\Component\Console\Input\InputArgument;
6371 use Symfony\Component\Console\Input\ArrayInput;
6372 use Symfony\Component\Console\Input\InputOption;
6373 use Symfony\Component\Console\Output\OutputInterface;
6374
6375
6376
6377
6378 class OutdatedCommand extends ShowCommand
6379 {
6380 protected function configure()
6381 {
6382 $this
6383 ->setName('outdated')
6384 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
6385 ->setDefinition(array(
6386 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
6387 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
6388 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
6389 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
6390 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
6391 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
6392 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6393 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.'),
6394 ))
6395 ->setHelp(
6396 <<<EOT
6397 The outdated command is just a proxy for `composer show -l`
6398
6399 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
6400
6401 - <info>green</info> (=): Dependency is in the latest version and is up to date.
6402 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
6403   compatibility breaks according to semver, so upgrade when you can but it
6404   may involve work.
6405 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
6406
6407 Read more at https://getcomposer.org/doc/03-cli.md#outdated
6408 EOT
6409 )
6410 ;
6411 }
6412
6413 protected function execute(InputInterface $input, OutputInterface $output)
6414 {
6415 $args = array(
6416 'command' => 'show',
6417 '--latest' => true,
6418 );
6419 if (!$input->getOption('all')) {
6420 $args['--outdated'] = true;
6421 }
6422 if ($input->getOption('direct')) {
6423 $args['--direct'] = true;
6424 }
6425 if ($input->getArgument('package')) {
6426 $args['package'] = $input->getArgument('package');
6427 }
6428 if ($input->getOption('strict')) {
6429 $args['--strict'] = true;
6430 }
6431 if ($input->getOption('minor-only')) {
6432 $args['--minor-only'] = true;
6433 }
6434 $args['--format'] = $input->getOption('format');
6435 $args['--ignore'] = $input->getOption('ignore');
6436
6437 $input = new ArrayInput($args);
6438
6439 return $this->getApplication()->run($input, $output);
6440 }
6441
6442
6443
6444
6445 public function isProxyCommand()
6446 {
6447 return true;
6448 }
6449 }
6450 <?php
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462 namespace Composer\Command;
6463
6464 use Symfony\Component\Console\Input\InputInterface;
6465 use Symfony\Component\Console\Output\OutputInterface;
6466
6467
6468
6469
6470 class ProhibitsCommand extends BaseDependencyCommand
6471 {
6472
6473
6474
6475 protected function configure()
6476 {
6477 parent::configure();
6478
6479 $this
6480 ->setName('prohibits')
6481 ->setAliases(array('why-not'))
6482 ->setDescription('Shows which packages prevent the given package from being installed.')
6483 ->setHelp(
6484 <<<EOT
6485 Displays detailed information about why a package cannot be installed.
6486
6487 <info>php composer.phar prohibits composer/composer</info>
6488
6489 Read more at https://getcomposer.org/doc/03-cli.md#prohibits-why-not-
6490 EOT
6491 )
6492 ;
6493 }
6494
6495
6496
6497
6498
6499
6500
6501
6502 protected function execute(InputInterface $input, OutputInterface $output)
6503 {
6504 return parent::doExecute($input, $output, true);
6505 }
6506 }
6507 <?php
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519 namespace Composer\Command;
6520
6521 use Composer\Config\JsonConfigSource;
6522 use Composer\Installer;
6523 use Composer\Plugin\CommandEvent;
6524 use Composer\Plugin\PluginEvents;
6525 use Composer\Json\JsonFile;
6526 use Composer\Factory;
6527 use Symfony\Component\Console\Input\InputInterface;
6528 use Symfony\Component\Console\Input\InputOption;
6529 use Symfony\Component\Console\Input\InputArgument;
6530 use Symfony\Component\Console\Output\OutputInterface;
6531 use Composer\Package\BasePackage;
6532
6533
6534
6535
6536
6537 class RemoveCommand extends BaseCommand
6538 {
6539 protected function configure()
6540 {
6541 $this
6542 ->setName('remove')
6543 ->setDescription('Removes a package from the require or require-dev.')
6544 ->setDefinition(array(
6545 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
6546 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
6547 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6548 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6549 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6550 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6551 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
6552 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
6553 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6554 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6555 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6556 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6557 ))
6558 ->setHelp(
6559 <<<EOT
6560 The <info>remove</info> command removes a package from the current
6561 list of installed packages
6562
6563 <info>php composer.phar remove</info>
6564
6565 Read more at https://getcomposer.org/doc/03-cli.md#remove
6566 EOT
6567 )
6568 ;
6569 }
6570
6571 protected function execute(InputInterface $input, OutputInterface $output)
6572 {
6573 $packages = $input->getArgument('packages');
6574 $packages = array_map('strtolower', $packages);
6575
6576 $file = Factory::getComposerFile();
6577
6578 $jsonFile = new JsonFile($file);
6579 $composer = $jsonFile->read();
6580 $composerBackup = file_get_contents($jsonFile->getPath());
6581
6582 $json = new JsonConfigSource($jsonFile);
6583
6584 $type = $input->getOption('dev') ? 'require-dev' : 'require';
6585 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
6586 $io = $this->getIO();
6587
6588 if ($input->getOption('update-with-dependencies')) {
6589 $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>');
6590 }
6591
6592
6593  foreach (array('require', 'require-dev') as $linkType) {
6594 if (isset($composer[$linkType])) {
6595 foreach ($composer[$linkType] as $name => $version) {
6596 $composer[$linkType][strtolower($name)] = $name;
6597 }
6598 }
6599 }
6600
6601 foreach ($packages as $package) {
6602 if (isset($composer[$type][$package])) {
6603 $json->removeLink($type, $composer[$type][$package]);
6604 } elseif (isset($composer[$altType][$package])) {
6605 $io->writeError('<warning>' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6606 if ($io->isInteractive()) {
6607 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6608 $json->removeLink($altType, $composer[$altType][$package]);
6609 }
6610 }
6611 } elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) {
6612 foreach ($matches as $matchedPackage) {
6613 $json->removeLink($type, $matchedPackage);
6614 }
6615 } elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) {
6616 foreach ($matches as $matchedPackage) {
6617 $io->writeError('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
6618 if ($io->isInteractive()) {
6619 if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
6620 $json->removeLink($altType, $matchedPackage);
6621 }
6622 }
6623 }
6624 } else {
6625 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
6626 }
6627 }
6628
6629 if ($input->getOption('no-update')) {
6630 return 0;
6631 }
6632
6633
6634  $this->resetComposer();
6635 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6636 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6637
6638 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
6639 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6640
6641 $install = Installer::create($io, $composer);
6642
6643 $updateDevMode = !$input->getOption('update-no-dev');
6644 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6645 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6646 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6647
6648 $install
6649 ->setVerbose($input->getOption('verbose'))
6650 ->setDevMode($updateDevMode)
6651 ->setOptimizeAutoloader($optimize)
6652 ->setClassMapAuthoritative($authoritative)
6653 ->setApcuAutoloader($apcu)
6654 ->setUpdate(true)
6655 ->setUpdateWhitelist($packages)
6656 ->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
6657 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6658 ->setRunScripts(!$input->getOption('no-scripts'))
6659 ;
6660
6661 $status = $install->run();
6662 if ($status !== 0) {
6663 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
6664 file_put_contents($jsonFile->getPath(), $composerBackup);
6665 }
6666
6667 return $status;
6668 }
6669 }
6670 <?php
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682 namespace Composer\Command;
6683
6684 use Symfony\Component\Console\Input\InputInterface;
6685 use Symfony\Component\Console\Input\InputArgument;
6686 use Symfony\Component\Console\Input\InputOption;
6687 use Symfony\Component\Console\Output\OutputInterface;
6688 use Composer\Factory;
6689 use Composer\Installer;
6690 use Composer\Json\JsonFile;
6691 use Composer\Json\JsonManipulator;
6692 use Composer\Package\Version\VersionParser;
6693 use Composer\Plugin\CommandEvent;
6694 use Composer\Plugin\PluginEvents;
6695 use Composer\Repository\CompositeRepository;
6696 use Composer\Repository\PlatformRepository;
6697 use Composer\IO\IOInterface;
6698 use Composer\Util\Silencer;
6699
6700
6701
6702
6703
6704 class RequireCommand extends InitCommand
6705 {
6706 private $newlyCreated;
6707 private $json;
6708 private $file;
6709 private $composerBackup;
6710
6711 protected function configure()
6712 {
6713 $this
6714 ->setName('require')
6715 ->setDescription('Adds required packages to your composer.json and installs them.')
6716 ->setDefinition(array(
6717 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"'),
6718 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
6719 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
6720 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
6721 new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'),
6722 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6723 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
6724 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
6725 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
6726 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
6727 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
6728 new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
6729 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
6730 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
6731 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
6732 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
6733 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
6734 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
6735 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
6736 ))
6737 ->setHelp(
6738 <<<EOT
6739 The require command adds required packages to your composer.json and installs them.
6740
6741 If you do not specify a package, composer will prompt you to search for a package, and given results, provide a list of
6742 matches to require.
6743
6744 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
6745
6746 If you do not want to install the new dependencies immediately you can call it with --no-update
6747
6748 Read more at https://getcomposer.org/doc/03-cli.md#require
6749 EOT
6750 )
6751 ;
6752 }
6753
6754 protected function execute(InputInterface $input, OutputInterface $output)
6755 {
6756 if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
6757 pcntl_async_signals(true);
6758 pcntl_signal(SIGINT, array($this, 'revertComposerFile'));
6759 pcntl_signal(SIGTERM, array($this, 'revertComposerFile'));
6760 pcntl_signal(SIGHUP, array($this, 'revertComposerFile'));
6761 }
6762
6763 $this->file = Factory::getComposerFile();
6764 $io = $this->getIO();
6765
6766 $this->newlyCreated = !file_exists($this->file);
6767 if ($this->newlyCreated && !file_put_contents($this->file, "{\n}\n")) {
6768 $io->writeError('<error>'.$this->file.' could not be created.</error>');
6769
6770 return 1;
6771 }
6772
6773  
6774  if (!is_readable($this->file) && false === Silencer::call('file_get_contents', $this->file)) {
6775 $io->writeError('<error>'.$this->file.' is not readable.</error>');
6776
6777 return 1;
6778 }
6779
6780 if (filesize($this->file) === 0) {
6781 file_put_contents($this->file, "{\n}\n");
6782 }
6783
6784 $this->json = new JsonFile($this->file);
6785 $this->composerBackup = file_get_contents($this->json->getPath());
6786
6787
6788  
6789  if (!is_writable($this->file) && !Silencer::call('file_put_contents', $this->file, $this->composerBackup)) {
6790 $io->writeError('<error>'.$this->file.' is not writable.</error>');
6791
6792 return 1;
6793 }
6794
6795 if ($input->getOption('fixed') === true) {
6796 $config = $this->json->read();
6797
6798 $packageType = empty($config['type']) ? 'library' : $config['type'];
6799
6800
6801
6802
6803 if ($packageType !== 'project') {
6804 $io->writeError('<error>"--fixed" option is allowed for "project" package types only to prevent possible misuses.</error>');
6805
6806 if (empty($config['type'])) {
6807 $io->writeError('<error>If your package is not library, you should explicitly specify "type" parameter in composer.json.</error>');
6808 }
6809
6810 return 1;
6811 }
6812 }
6813
6814 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6815 $repos = $composer->getRepositoryManager()->getRepositories();
6816
6817 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6818
6819  $this->repos = new CompositeRepository(array_merge(
6820 array(new PlatformRepository(array(), $platformOverrides)),
6821 $repos
6822 ));
6823
6824 if ($composer->getPackage()->getPreferStable()) {
6825 $preferredStability = 'stable';
6826 } else {
6827 $preferredStability = $composer->getPackage()->getMinimumStability();
6828 }
6829
6830 $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion();
6831 try {
6832 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'), $input->getOption('fixed'));
6833 } catch (\Exception $e) {
6834 if ($this->newlyCreated) {
6835 throw new \RuntimeException('No composer.json present in the current directory, this may be the cause of the following exception.', 0, $e);
6836 }
6837
6838 throw $e;
6839 }
6840
6841 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
6842 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
6843 $requirements = $this->formatRequirements($requirements);
6844
6845
6846  $versionParser = new VersionParser();
6847 foreach ($requirements as $package => $constraint) {
6848 if (strtolower($package) === $composer->getPackage()->getName()) {
6849 $io->writeError(sprintf('<error>Root package \'%s\' cannot require itself in its composer.json</error>', $package));
6850
6851 return 1;
6852 }
6853 $versionParser->parseConstraints($constraint);
6854 }
6855
6856 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
6857
6858 if (!$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
6859 $composerDefinition = $this->json->read();
6860 foreach ($requirements as $package => $version) {
6861 $composerDefinition[$requireKey][$package] = $version;
6862 unset($composerDefinition[$removeKey][$package]);
6863 }
6864 $this->json->write($composerDefinition);
6865 }
6866
6867 $io->writeError('<info>'.$this->file.' has been '.($this->newlyCreated ? 'created' : 'updated').'</info>');
6868
6869 if ($input->getOption('no-update')) {
6870 return 0;
6871 }
6872
6873 try {
6874 return $this->doUpdate($input, $output, $io, $requirements);
6875 } catch (\Exception $e) {
6876 $this->revertComposerFile(false);
6877 throw $e;
6878 }
6879 }
6880
6881 private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
6882 {
6883
6884  $this->resetComposer();
6885 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
6886 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
6887
6888 $updateDevMode = !$input->getOption('update-no-dev');
6889 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
6890 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
6891 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
6892
6893 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
6894 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6895
6896 $install = Installer::create($io, $composer);
6897
6898 $install
6899 ->setVerbose($input->getOption('verbose'))
6900 ->setPreferSource($input->getOption('prefer-source'))
6901 ->setPreferDist($input->getOption('prefer-dist'))
6902 ->setDevMode($updateDevMode)
6903 ->setRunScripts(!$input->getOption('no-scripts'))
6904 ->setSkipSuggest($input->getOption('no-suggest'))
6905 ->setOptimizeAutoloader($optimize)
6906 ->setClassMapAuthoritative($authoritative)
6907 ->setApcuAutoloader($apcu)
6908 ->setUpdate(true)
6909 ->setUpdateWhitelist(array_keys($requirements))
6910 ->setWhitelistTransitiveDependencies($input->getOption('update-with-dependencies'))
6911 ->setWhitelistAllDependencies($input->getOption('update-with-all-dependencies'))
6912 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
6913 ->setPreferStable($input->getOption('prefer-stable'))
6914 ->setPreferLowest($input->getOption('prefer-lowest'))
6915 ;
6916
6917 $status = $install->run();
6918 if ($status !== 0) {
6919 $this->revertComposerFile(false);
6920 }
6921
6922 return $status;
6923 }
6924
6925 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
6926 {
6927 $contents = file_get_contents($json->getPath());
6928
6929 $manipulator = new JsonManipulator($contents);
6930
6931 foreach ($new as $package => $constraint) {
6932 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
6933 return false;
6934 }
6935 if (!$manipulator->removeSubNode($removeKey, $package)) {
6936 return false;
6937 }
6938 }
6939
6940 file_put_contents($json->getPath(), $manipulator->getContents());
6941
6942 return true;
6943 }
6944
6945 protected function interact(InputInterface $input, OutputInterface $output)
6946 {
6947 return;
6948 }
6949
6950 public function revertComposerFile($hardExit = true)
6951 {
6952 $io = $this->getIO();
6953
6954 if ($this->newlyCreated) {
6955 $io->writeError("\n".'<error>Installation failed, deleting '.$this->file.'.</error>');
6956 unlink($this->json->getPath());
6957 } else {
6958 $io->writeError("\n".'<error>Installation failed, reverting '.$this->file.' to its original content.</error>');
6959 file_put_contents($this->json->getPath(), $this->composerBackup);
6960 }
6961
6962 if ($hardExit) {
6963 exit(1);
6964 }
6965 }
6966 }
6967 <?php
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979 namespace Composer\Command;
6980
6981 use Composer\Script\Event as ScriptEvent;
6982 use Composer\Script\ScriptEvents;
6983 use Composer\Util\ProcessExecutor;
6984 use Symfony\Component\Console\Input\InputInterface;
6985 use Symfony\Component\Console\Input\InputOption;
6986 use Symfony\Component\Console\Input\InputArgument;
6987 use Symfony\Component\Console\Output\OutputInterface;
6988 use Symfony\Component\Console\Helper\Table;
6989
6990
6991
6992
6993 class RunScriptCommand extends BaseCommand
6994 {
6995
6996
6997
6998 protected $scriptEvents = array(
6999 ScriptEvents::PRE_INSTALL_CMD,
7000 ScriptEvents::POST_INSTALL_CMD,
7001 ScriptEvents::PRE_UPDATE_CMD,
7002 ScriptEvents::POST_UPDATE_CMD,
7003 ScriptEvents::PRE_STATUS_CMD,
7004 ScriptEvents::POST_STATUS_CMD,
7005 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
7006 ScriptEvents::POST_CREATE_PROJECT_CMD,
7007 ScriptEvents::PRE_ARCHIVE_CMD,
7008 ScriptEvents::POST_ARCHIVE_CMD,
7009 ScriptEvents::PRE_AUTOLOAD_DUMP,
7010 ScriptEvents::POST_AUTOLOAD_DUMP,
7011 );
7012
7013 protected function configure()
7014 {
7015 $this
7016 ->setName('run-script')
7017 ->setAliases(array('run'))
7018 ->setDescription('Runs the scripts defined in composer.json.')
7019 ->setDefinition(array(
7020 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
7021 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
7022 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
7023 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
7024 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
7025 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
7026 ))
7027 ->setHelp(
7028 <<<EOT
7029 The <info>run-script</info> command runs scripts defined in composer.json:
7030
7031 <info>php composer.phar run-script post-update-cmd</info>
7032
7033 Read more at https://getcomposer.org/doc/03-cli.md#run-script
7034 EOT
7035 )
7036 ;
7037 }
7038
7039 protected function execute(InputInterface $input, OutputInterface $output)
7040 {
7041 if ($input->getOption('list')) {
7042 return $this->listScripts($output);
7043 } elseif (!$input->getArgument('script')) {
7044 throw new \RuntimeException('Missing required argument "script"');
7045 }
7046
7047 $script = $input->getArgument('script');
7048 if (!in_array($script, $this->scriptEvents)) {
7049 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
7050 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
7051 }
7052 }
7053
7054 $composer = $this->getComposer();
7055 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
7056 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
7057 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
7058 if (!$hasListeners) {
7059 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
7060 }
7061
7062 $args = $input->getArgument('args');
7063
7064 if (null !== $timeout = $input->getOption('timeout')) {
7065 if (!ctype_digit($timeout)) {
7066 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
7067 }
7068
7069  ProcessExecutor::setTimeout((int) $timeout);
7070 }
7071
7072 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
7073 }
7074
7075 protected function listScripts(OutputInterface $output)
7076 {
7077 $scripts = $this->getComposer()->getPackage()->getScripts();
7078
7079 if (!count($scripts)) {
7080 return 0;
7081 }
7082
7083 $io = $this->getIO();
7084 $io->writeError('<info>scripts:</info>');
7085 $table = array();
7086 foreach ($scripts as $name => $script) {
7087 $description = '';
7088 try {
7089 $cmd = $this->getApplication()->find($name);
7090 if ($cmd instanceof ScriptAliasCommand) {
7091 $description = $cmd->getDescription();
7092 }
7093 } catch (\Symfony\Component\Console\Exception\CommandNotFoundException $e) {
7094
7095  }
7096 $table[] = array('  '.$name, $description);
7097 }
7098
7099 $renderer = new Table($output);
7100 $renderer->setStyle('compact');
7101 $rendererStyle = $renderer->getStyle();
7102 if (method_exists($rendererStyle, 'setVerticalBorderChars')) {
7103 $rendererStyle->setVerticalBorderChars('');
7104 } else {
7105 $rendererStyle->setVerticalBorderChar('');
7106 }
7107 $rendererStyle->setCellRowContentFormat('%s  ');
7108 $renderer->setRows($table)->render();
7109
7110 return 0;
7111 }
7112 }
7113 <?php
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125 namespace Composer\Command;
7126
7127 use Symfony\Component\Console\Input\InputInterface;
7128 use Symfony\Component\Console\Input\InputOption;
7129 use Symfony\Component\Console\Input\InputArgument;
7130 use Symfony\Component\Console\Output\OutputInterface;
7131
7132
7133
7134
7135 class ScriptAliasCommand extends BaseCommand
7136 {
7137 private $script;
7138 private $description;
7139
7140 public function __construct($script, $description)
7141 {
7142 $this->script = $script;
7143 $this->description = empty($description) ? 'Runs the '.$script.' script as defined in composer.json.' : $description;
7144
7145 parent::__construct();
7146 }
7147
7148 protected function configure()
7149 {
7150 $this
7151 ->setName($this->script)
7152 ->setDescription($this->description)
7153 ->setDefinition(array(
7154 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
7155 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
7156 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
7157 ))
7158 ->setHelp(
7159 <<<EOT
7160 The <info>run-script</info> command runs scripts defined in composer.json:
7161
7162 <info>php composer.phar run-script post-update-cmd</info>
7163
7164 Read more at https://getcomposer.org/doc/03-cli.md#run-script
7165 EOT
7166 )
7167 ;
7168 }
7169
7170 protected function execute(InputInterface $input, OutputInterface $output)
7171 {
7172 $composer = $this->getComposer();
7173
7174 $args = $input->getArguments();
7175
7176 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
7177 }
7178 }
7179 <?php
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191 namespace Composer\Command;
7192
7193 use Composer\Factory;
7194 use Symfony\Component\Console\Input\InputInterface;
7195 use Symfony\Component\Console\Input\InputArgument;
7196 use Symfony\Component\Console\Input\InputOption;
7197 use Symfony\Component\Console\Output\OutputInterface;
7198 use Composer\Repository\CompositeRepository;
7199 use Composer\Repository\PlatformRepository;
7200 use Composer\Repository\RepositoryInterface;
7201 use Composer\Plugin\CommandEvent;
7202 use Composer\Plugin\PluginEvents;
7203
7204
7205
7206
7207 class SearchCommand extends BaseCommand
7208 {
7209 protected $matches;
7210 protected $lowMatches = array();
7211 protected $tokens;
7212 protected $output;
7213 protected $onlyName;
7214
7215 protected function configure()
7216 {
7217 $this
7218 ->setName('search')
7219 ->setDescription('Searches for packages.')
7220 ->setDefinition(array(
7221 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
7222 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
7223 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
7224 ))
7225 ->setHelp(
7226 <<<EOT
7227 The search command searches for packages by its name
7228 <info>php composer.phar search symfony composer</info>
7229
7230 Read more at https://getcomposer.org/doc/03-cli.md#search
7231 EOT
7232 )
7233 ;
7234 }
7235
7236 protected function execute(InputInterface $input, OutputInterface $output)
7237 {
7238
7239  $platformRepo = new PlatformRepository;
7240 $io = $this->getIO();
7241 if (!($composer = $this->getComposer(false))) {
7242 $composer = Factory::create($this->getIO(), array(), $input->hasParameterOption('--no-plugins'));
7243 }
7244 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
7245 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
7246 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
7247
7248 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
7249 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7250
7251 $onlyName = $input->getOption('only-name');
7252 $type = $input->getOption('type') ?: null;
7253
7254 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
7255 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
7256
7257 foreach ($results as $result) {
7258 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
7259 }
7260
7261 return 0;
7262 }
7263 }
7264 <?php
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276 namespace Composer\Command;
7277
7278 use Composer\Composer;
7279 use Composer\Factory;
7280 use Composer\Config;
7281 use Composer\Util\Filesystem;
7282 use Composer\SelfUpdate\Keys;
7283 use Composer\SelfUpdate\Versions;
7284 use Composer\IO\IOInterface;
7285 use Composer\Downloader\FilesystemException;
7286 use Symfony\Component\Console\Input\InputInterface;
7287 use Symfony\Component\Console\Input\InputOption;
7288 use Symfony\Component\Console\Input\InputArgument;
7289 use Symfony\Component\Console\Output\OutputInterface;
7290 use Symfony\Component\Finder\Finder;
7291
7292
7293
7294
7295
7296
7297 class SelfUpdateCommand extends BaseCommand
7298 {
7299 const HOMEPAGE = 'getcomposer.org';
7300 const OLD_INSTALL_EXT = '-old.phar';
7301
7302 protected function configure()
7303 {
7304 $this
7305 ->setName('self-update')
7306 ->setAliases(array('selfupdate'))
7307 ->setDescription('Updates composer.phar to the latest version.')
7308 ->setDefinition(array(
7309 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
7310 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'),
7311 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
7312 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
7313 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
7314 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
7315 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
7316 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
7317 new InputOption('1', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 1.x versions'),
7318 new InputOption('2', null, InputOption::VALUE_NONE, 'Force an update to the stable channel, but only use 2.x versions'),
7319 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
7320 ))
7321 ->setHelp(
7322 <<<EOT
7323 The <info>self-update</info> command checks getcomposer.org for newer
7324 versions of composer and if found, installs the latest.
7325
7326 <info>php composer.phar self-update</info>
7327
7328 Read more at https://getcomposer.org/doc/03-cli.md#self-update-selfupdate-
7329 EOT
7330 )
7331 ;
7332 }
7333
7334 protected function execute(InputInterface $input, OutputInterface $output)
7335 {
7336 $config = Factory::createConfig();
7337
7338 if ($config->get('disable-tls') === true) {
7339 $baseUrl = 'http://' . self::HOMEPAGE;
7340 } else {
7341 $baseUrl = 'https://' . self::HOMEPAGE;
7342 }
7343
7344 $io = $this->getIO();
7345 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
7346
7347 $versionsUtil = new Versions($config, $remoteFilesystem);
7348
7349
7350  $requestedChannel = null;
7351 foreach (Versions::$channels as $channel) {
7352 if ($input->getOption($channel)) {
7353 $requestedChannel = $channel;
7354 $versionsUtil->setChannel($channel);
7355 break;
7356 }
7357 }
7358
7359 if ($input->getOption('set-channel-only')) {
7360 return 0;
7361 }
7362
7363 $cacheDir = $config->get('cache-dir');
7364 $rollbackDir = $config->get('data-dir');
7365 $home = $config->get('home');
7366 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
7367
7368 if ($input->getOption('update-keys')) {
7369 return $this->fetchKeys($io, $config);
7370 }
7371
7372
7373  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
7374
7375
7376  if (!is_writable($tmpDir)) {
7377 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
7378 }
7379
7380
7381  if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
7382 $composeUser = posix_getpwuid(posix_geteuid());
7383 $homeOwner = posix_getpwuid(fileowner($home));
7384 if (isset($composeUser['name']) && isset($homeOwner['name']) && $composeUser['name'] !== $homeOwner['name']) {
7385 $io->writeError('<warning>You are running composer as "'.$composeUser['name'].'", while "'.$home.'" is owned by "'.$homeOwner['name'].'"</warning>');
7386 }
7387 }
7388
7389 if ($input->getOption('rollback')) {
7390 return $this->rollback($output, $rollbackDir, $localFilename);
7391 }
7392
7393 $latest = $versionsUtil->getLatest();
7394 $latestStable = $versionsUtil->getLatest('stable');
7395 $latestVersion = $latest['version'];
7396 $updateVersion = $input->getArgument('version') ?: $latestVersion;
7397
7398 if ($requestedChannel && is_numeric($requestedChannel) && substr($latestStable['version'], 0, 1) !== $requestedChannel) {
7399 $io->writeError('<warning>Warning: You forced the install of '.$latestVersion.' via --'.$requestedChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.</warning>');
7400 }
7401
7402 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
7403 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
7404
7405 return 1;
7406 }
7407
7408 if (Composer::VERSION === $updateVersion) {
7409 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
7410
7411
7412  if ($input->getOption('clean-backups')) {
7413 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
7414 }
7415
7416 return 0;
7417 }
7418
7419 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
7420 $backupFile = sprintf(
7421 '%s/%s-%s%s',
7422 $rollbackDir,
7423 strtr(Composer::RELEASE_DATE, ' :', '_-'),
7424 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
7425 self::OLD_INSTALL_EXT
7426 );
7427
7428 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
7429
7430 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
7431 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
7432 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
7433 $io->writeError('   ', false);
7434 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
7435 $io->writeError('');
7436
7437 if (!file_exists($tempFilename) || !$signature) {
7438 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
7439
7440 return 1;
7441 }
7442
7443
7444  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
7445 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
7446 } else {
7447 if (!extension_loaded('openssl')) {
7448 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
7449 . '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.');
7450 }
7451
7452 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
7453 if (!file_exists($sigFile)) {
7454 file_put_contents(
7455 $home.'/keys.dev.pub',
7456 <<<DEVPUBKEY
7457 -----BEGIN PUBLIC KEY-----
7458 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
7459 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
7460 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
7461 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
7462 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
7463 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
7464 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
7465 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
7466 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
7467 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
7468 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
7469 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
7470 -----END PUBLIC KEY-----
7471 DEVPUBKEY
7472 );
7473
7474 file_put_contents(
7475 $home.'/keys.tags.pub',
7476 <<<TAGSPUBKEY
7477 -----BEGIN PUBLIC KEY-----
7478 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
7479 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
7480 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
7481 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
7482 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
7483 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
7484 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
7485 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
7486 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
7487 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
7488 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
7489 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
7490 -----END PUBLIC KEY-----
7491 TAGSPUBKEY
7492 );
7493 }
7494
7495 $pubkeyid = openssl_pkey_get_public($sigFile);
7496 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
7497 if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) {
7498 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
7499 }
7500 $signature = json_decode($signature, true);
7501 $signature = base64_decode($signature['sha384']);
7502 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
7503 openssl_free_key($pubkeyid);
7504 if (!$verified) {
7505 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');
7506 }
7507 }
7508
7509
7510  if ($input->getOption('clean-backups')) {
7511 $this->cleanBackups($rollbackDir);
7512 }
7513
7514 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
7515 @unlink($tempFilename);
7516 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
7517 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
7518
7519 return 1;
7520 }
7521
7522 if (file_exists($backupFile)) {
7523 $io->writeError(sprintf(
7524 'Use <info>composer self-update --rollback</info> to return to version <comment>%s</comment>',
7525 Composer::VERSION
7526 ));
7527 } else {
7528 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
7529 }
7530
7531 return 0;
7532 }
7533
7534 protected function fetchKeys(IOInterface $io, Config $config)
7535 {
7536 if (!$io->isInteractive()) {
7537 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
7538 }
7539
7540 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
7541
7542 $validator = function ($value) {
7543 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
7544 throw new \UnexpectedValueException('Invalid input');
7545 }
7546
7547 return trim($value)."\n";
7548 };
7549
7550 $devKey = '';
7551 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
7552 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
7553 while ($line = $io->ask('')) {
7554 $devKey .= trim($line)."\n";
7555 if (trim($line) === '-----END PUBLIC KEY-----') {
7556 break;
7557 }
7558 }
7559 }
7560 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
7561 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7562
7563 $tagsKey = '';
7564 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
7565 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
7566 while ($line = $io->ask('')) {
7567 $tagsKey .= trim($line)."\n";
7568 if (trim($line) === '-----END PUBLIC KEY-----') {
7569 break;
7570 }
7571 }
7572 }
7573 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
7574 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
7575
7576 $io->write('Public keys stored in '.$config->get('home'));
7577 }
7578
7579 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
7580 {
7581 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
7582 if (!$rollbackVersion) {
7583 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
7584 }
7585
7586 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
7587
7588 if (!is_file($oldFile)) {
7589 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
7590 }
7591 if (!is_readable($oldFile)) {
7592 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
7593 }
7594
7595 $io = $this->getIO();
7596 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
7597 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
7598 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
7599
7600 return 1;
7601 }
7602
7603 return 0;
7604 }
7605
7606
7607
7608
7609
7610
7611
7612
7613 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
7614 {
7615 try {
7616 @chmod($newFilename, fileperms($localFilename));
7617 if (!ini_get('phar.readonly')) {
7618
7619  $phar = new \Phar($newFilename);
7620
7621  unset($phar);
7622 }
7623
7624
7625  if ($backupTarget && file_exists($localFilename)) {
7626 @copy($localFilename, $backupTarget);
7627 }
7628
7629 rename($newFilename, $localFilename);
7630
7631 return null;
7632 } catch (\Exception $e) {
7633 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
7634 throw $e;
7635 }
7636
7637 return $e;
7638 }
7639 }
7640
7641 protected function cleanBackups($rollbackDir, $except = null)
7642 {
7643 $finder = $this->getOldInstallationFinder($rollbackDir);
7644 $io = $this->getIO();
7645 $fs = new Filesystem;
7646
7647 foreach ($finder as $file) {
7648 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
7649 continue;
7650 }
7651 $file = (string) $file;
7652 $io->writeError('<info>Removing: '.$file.'</info>');
7653 $fs->remove($file);
7654 }
7655 }
7656
7657 protected function getLastBackupVersion($rollbackDir)
7658 {
7659 $finder = $this->getOldInstallationFinder($rollbackDir);
7660 $finder->sortByName();
7661 $files = iterator_to_array($finder);
7662
7663 if (count($files)) {
7664 return basename(end($files), self::OLD_INSTALL_EXT);
7665 }
7666
7667 return false;
7668 }
7669
7670 protected function getOldInstallationFinder($rollbackDir)
7671 {
7672 $finder = Finder::create()
7673 ->depth(0)
7674 ->files()
7675 ->name('*' . self::OLD_INSTALL_EXT)
7676 ->in($rollbackDir);
7677
7678 return $finder;
7679 }
7680 }
7681 <?php
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693 namespace Composer\Command;
7694
7695 use Composer\Composer;
7696 use Composer\DependencyResolver\DefaultPolicy;
7697 use Composer\DependencyResolver\Pool;
7698 use Composer\Json\JsonFile;
7699 use Composer\Package\BasePackage;
7700 use Composer\Package\CompletePackageInterface;
7701 use Composer\Package\PackageInterface;
7702 use Composer\Package\Version\VersionParser;
7703 use Composer\Package\Version\VersionSelector;
7704 use Composer\Plugin\CommandEvent;
7705 use Composer\Plugin\PluginEvents;
7706 use Composer\Repository\ArrayRepository;
7707 use Composer\Repository\ComposerRepository;
7708 use Composer\Repository\CompositeRepository;
7709 use Composer\Repository\PlatformRepository;
7710 use Composer\Repository\RepositoryFactory;
7711 use Composer\Repository\RepositoryInterface;
7712 use Composer\Semver\Constraint\ConstraintInterface;
7713 use Composer\Semver\Semver;
7714 use Composer\Spdx\SpdxLicenses;
7715 use Composer\Util\Platform;
7716 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
7717 use Symfony\Component\Console\Input\InputArgument;
7718 use Symfony\Component\Console\Input\InputInterface;
7719 use Symfony\Component\Console\Input\InputOption;
7720 use Symfony\Component\Console\Output\OutputInterface;
7721 use Symfony\Component\Console\Terminal;
7722
7723
7724
7725
7726
7727
7728
7729 class ShowCommand extends BaseCommand
7730 {
7731
7732 protected $versionParser;
7733 protected $colors;
7734
7735
7736 private $pool;
7737
7738 protected function configure()
7739 {
7740 $this
7741 ->setName('show')
7742 ->setAliases(array('info'))
7743 ->setDescription('Shows information about packages.')
7744 ->setDefinition(array(
7745 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
7746 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
7747 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
7748 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
7749 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
7750 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
7751 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
7752 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
7753 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
7754 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
7755 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
7756 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
7757 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.'),
7758 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
7759 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
7760 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
7761 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
7762 ))
7763 ->setHelp(
7764 <<<EOT
7765 The show command displays detailed information about a package, or
7766 lists all packages available.
7767
7768 Read more at https://getcomposer.org/doc/03-cli.md#show
7769 EOT
7770 )
7771 ;
7772 }
7773
7774 protected function execute(InputInterface $input, OutputInterface $output)
7775 {
7776 $this->versionParser = new VersionParser;
7777 if ($input->getOption('tree')) {
7778 $this->initStyles($output);
7779 }
7780
7781 $composer = $this->getComposer(false);
7782 $io = $this->getIO();
7783
7784 if ($input->getOption('installed')) {
7785 $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>');
7786 }
7787
7788 if ($input->getOption('outdated')) {
7789 $input->setOption('latest', true);
7790 } elseif ($input->getOption('ignore')) {
7791 $io->writeError('<warning>You are using the option "ignore" for action other than "outdated", it will be ignored.</warning>');
7792 }
7793
7794 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
7795 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
7796
7797 return 1;
7798 }
7799
7800 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
7801 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
7802
7803 return 1;
7804 }
7805
7806 if ($input->getOption('tree') && $input->getOption('latest')) {
7807 $io->writeError('The --tree (-t) option is not usable in combination with --latest (-l)');
7808
7809 return 1;
7810 }
7811
7812 if ($input->getOption('tree') && $input->getOption('path')) {
7813 $io->writeError('The --tree (-t) option is not usable in combination with --path (-P)');
7814
7815 return 1;
7816 }
7817
7818 $format = $input->getOption('format');
7819 if (!in_array($format, array('text', 'json'))) {
7820 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
7821
7822 return 1;
7823 }
7824
7825
7826  $platformOverrides = array();
7827 if ($composer) {
7828 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
7829 }
7830 $platformRepo = new PlatformRepository(array(), $platformOverrides);
7831 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
7832
7833 if ($input->getOption('self')) {
7834 $package = $this->getComposer()->getPackage();
7835 if ($input->getOption('name-only')) {
7836 $io->write($package->getName());
7837 return 0;
7838 }
7839 $repos = $installedRepo = new ArrayRepository(array($package));
7840 } elseif ($input->getOption('platform')) {
7841 $repos = $installedRepo = $platformRepo;
7842 } elseif ($input->getOption('available')) {
7843 $installedRepo = $platformRepo;
7844 if ($composer) {
7845 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
7846 } else {
7847 $defaultRepos = RepositoryFactory::defaultRepos($io);
7848 $repos = new CompositeRepository($defaultRepos);
7849 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7850 }
7851 } elseif ($input->getOption('all') && $composer) {
7852 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
7853 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
7854 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
7855 } elseif ($input->getOption('all')) {
7856 $defaultRepos = RepositoryFactory::defaultRepos($io);
7857 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
7858 $installedRepo = $platformRepo;
7859 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
7860 } else {
7861 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
7862 $rootPkg = $this->getComposer()->getPackage();
7863 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
7864 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
7865 }
7866 }
7867
7868 if ($composer) {
7869 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
7870 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7871 }
7872
7873 if ($input->getOption('latest') && null === $composer) {
7874 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
7875 $input->setOption('latest', false);
7876 }
7877
7878 $packageFilter = $input->getArgument('package');
7879
7880
7881  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
7882 if (empty($package)) {
7883 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
7884
7885 if (empty($package)) {
7886 $options = $input->getOptions();
7887 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
7888 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $input->getArgument('package')) && !$input->getOption('platform')) {
7889 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found, try using --platform (-p) to show platform packages.');
7890 }
7891 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
7892 }
7893
7894 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
7895
7896 return 1;
7897 }
7898 } else {
7899 $versions = array($package->getPrettyVersion() => $package->getVersion());
7900 }
7901
7902 $exitCode = 0;
7903 if ($input->getOption('tree')) {
7904 $arrayTree = $this->generatePackageTree($package, $installedRepo, $repos);
7905
7906 if ('json' === $format) {
7907 $io->write(JsonFile::encode(array('installed' => array($arrayTree))));
7908 } else {
7909 $this->displayPackageTree(array($arrayTree));
7910 }
7911 } else {
7912 $latestPackage = null;
7913 if ($input->getOption('latest')) {
7914 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
7915 }
7916 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
7917 $exitCode = 1;
7918 }
7919 if ($input->getOption('path')) {
7920 $io->write($package->getName(), false);
7921 $io->write(' ' . strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n"));
7922
7923 return $exitCode;
7924 }
7925
7926 if ('json' === $format) {
7927 $this->printPackageInfoAsJson($package, $versions, $installedRepo, $latestPackage ?: null);
7928 } else {
7929 $this->printPackageInfo($package, $versions, $installedRepo, $latestPackage ?: null);
7930 }
7931 }
7932
7933 return $exitCode;
7934 }
7935
7936
7937  if ($input->getOption('tree')) {
7938 $rootRequires = $this->getRootRequires();
7939 $packages = $installedRepo->getPackages();
7940 usort($packages, 'strcmp');
7941 $arrayTree = array();
7942 foreach ($packages as $package) {
7943 if (in_array($package->getName(), $rootRequires, true)) {
7944 $arrayTree[] = $this->generatePackageTree($package, $installedRepo, $repos);
7945 }
7946 }
7947
7948 if ('json' === $format) {
7949 $io->write(JsonFile::encode(array('installed' => $arrayTree)));
7950 } else {
7951 $this->displayPackageTree($arrayTree);
7952 }
7953
7954 return 0;
7955 }
7956
7957 if ($repos instanceof CompositeRepository) {
7958 $repos = $repos->getRepositories();
7959 } elseif (!is_array($repos)) {
7960 $repos = array($repos);
7961 }
7962
7963
7964  $packages = array();
7965 if (null !== $packageFilter) {
7966 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
7967 }
7968
7969 $packageListFilter = array();
7970 if ($input->getOption('direct')) {
7971 $packageListFilter = $this->getRootRequires();
7972 }
7973
7974 if (class_exists('Symfony\Component\Console\Terminal')) {
7975 $terminal = new Terminal();
7976 $width = $terminal->getWidth();
7977 } else {
7978
7979  list($width) = $this->getApplication()->getTerminalDimensions();
7980 }
7981 if (null === $width) {
7982
7983  
7984  $width = PHP_INT_MAX;
7985 }
7986 if (Platform::isWindows()) {
7987 $width--;
7988 } else {
7989 $width = max(80, $width);
7990 }
7991
7992 if ($input->getOption('path') && null === $composer) {
7993 $io->writeError('No composer.json found in the current directory, disabling "path" option');
7994 $input->setOption('path', false);
7995 }
7996
7997 foreach ($repos as $repo) {
7998 if ($repo === $platformRepo) {
7999 $type = 'platform';
8000 } elseif (
8001 $repo === $installedRepo
8002 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
8003 ) {
8004 $type = 'installed';
8005 } else {
8006 $type = 'available';
8007 }
8008 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
8009 foreach ($repo->getProviderNames() as $name) {
8010 if (!$packageFilter || preg_match($packageFilter, $name)) {
8011 $packages[$type][$name] = $name;
8012 }
8013 }
8014 } else {
8015 foreach ($repo->getPackages() as $package) {
8016 if (!isset($packages[$type][$package->getName()])
8017 || !is_object($packages[$type][$package->getName()])
8018 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
8019 ) {
8020 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
8021 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
8022 $packages[$type][$package->getName()] = $package;
8023 }
8024 }
8025 }
8026 }
8027 }
8028 }
8029
8030 $showAllTypes = $input->getOption('all');
8031 $showLatest = $input->getOption('latest');
8032 $showMinorOnly = $input->getOption('minor-only');
8033 $ignoredPackages = array_map('strtolower', $input->getOption('ignore'));
8034 $indent = $showAllTypes ? '  ' : '';
8035 $latestPackages = array();
8036 $exitCode = 0;
8037 $viewData = array();
8038 $viewMetaData = array();
8039 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
8040 if (isset($packages[$type])) {
8041 ksort($packages[$type]);
8042
8043 $nameLength = $versionLength = $latestLength = 0;
8044
8045 if ($showLatest && $showVersion) {
8046 foreach ($packages[$type] as $package) {
8047 if (is_object($package)) {
8048 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
8049 if ($latestPackage === false) {
8050 continue;
8051 }
8052
8053 $latestPackages[$package->getPrettyName()] = $latestPackage;
8054 }
8055 }
8056 }
8057
8058 $writePath = !$input->getOption('name-only') && $input->getOption('path');
8059 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
8060 $writeLatest = $writeVersion && $showLatest;
8061 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
8062
8063 $hasOutdatedPackages = false;
8064
8065 $viewData[$type] = array();
8066 foreach ($packages[$type] as $package) {
8067 $packageViewData = array();
8068 if (is_object($package)) {
8069 $latestPackage = null;
8070 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
8071 $latestPackage = $latestPackages[$package->getPrettyName()];
8072 }
8073
8074
8075  $packageIsUpToDate = $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned();
8076 $packageIsIgnored = \in_array($package->getPrettyName(), $ignoredPackages, true);
8077 if ($input->getOption('outdated') && ($packageIsUpToDate || $packageIsIgnored)) {
8078 continue;
8079 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
8080 $hasOutdatedPackages = true;
8081 }
8082
8083 $packageViewData['name'] = $package->getPrettyName();
8084 $nameLength = max($nameLength, strlen($package->getPrettyName()));
8085 if ($writeVersion) {
8086 $packageViewData['version'] = $package->getFullPrettyVersion();
8087 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
8088 }
8089 if ($writeLatest && $latestPackage) {
8090 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
8091 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
8092 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
8093 }
8094 if ($writeDescription) {
8095 $packageViewData['description'] = $package->getDescription();
8096 }
8097 if ($writePath) {
8098 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
8099 }
8100
8101 if ($latestPackage && $latestPackage->isAbandoned()) {
8102 $replacement = is_string($latestPackage->getReplacementPackage())
8103 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
8104 : 'No replacement was suggested';
8105 $packageWarning = sprintf(
8106 'Package %s is abandoned, you should avoid using it. %s.',
8107 $package->getPrettyName(),
8108 $replacement
8109 );
8110 $packageViewData['warning'] = $packageWarning;
8111 }
8112 } else {
8113 $packageViewData['name'] = $package;
8114 $nameLength = max($nameLength, strlen($package));
8115 }
8116 $viewData[$type][] = $packageViewData;
8117 }
8118 $viewMetaData[$type] = array(
8119 'nameLength' => $nameLength,
8120 'versionLength' => $versionLength,
8121 'latestLength' => $latestLength,
8122 );
8123 if ($input->getOption('strict') && $hasOutdatedPackages) {
8124 $exitCode = 1;
8125 break;
8126 }
8127 }
8128 }
8129
8130 if ('json' === $format) {
8131 $io->write(JsonFile::encode($viewData));
8132 } else {
8133 foreach ($viewData as $type => $packages) {
8134 $nameLength = $viewMetaData[$type]['nameLength'];
8135 $versionLength = $viewMetaData[$type]['versionLength'];
8136 $latestLength = $viewMetaData[$type]['latestLength'];
8137
8138 $writeVersion = $nameLength + $versionLength + 3 <= $width;
8139 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
8140 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
8141
8142 if ($writeLatest && !$io->isDecorated()) {
8143 $latestLength += 2;
8144 }
8145
8146 if ($showAllTypes) {
8147 if ('available' === $type) {
8148 $io->write('<comment>' . $type . '</comment>:');
8149 } else {
8150 $io->write('<info>' . $type . '</info>:');
8151 }
8152 }
8153
8154 foreach ($packages as $package) {
8155 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
8156 if (isset($package['version']) && $writeVersion) {
8157 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
8158 }
8159 if (isset($package['latest']) && $writeLatest) {
8160 $latestVersion = $package['latest'];
8161 $updateStatus = $package['latest-status'];
8162 $style = $this->updateStatusToVersionStyle($updateStatus);
8163 if (!$io->isDecorated()) {
8164 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
8165 }
8166 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
8167 }
8168 if (isset($package['description']) && $writeDescription) {
8169 $description = strtok($package['description'], "\r\n");
8170 $remaining = $width - $nameLength - $versionLength - 4;
8171 if ($writeLatest) {
8172 $remaining -= $latestLength;
8173 }
8174 if (strlen($description) > $remaining) {
8175 $description = substr($description, 0, $remaining - 3) . '...';
8176 }
8177 $io->write(' ' . $description, false);
8178 }
8179 if (isset($package['path'])) {
8180 $io->write(' ' . $package['path'], false);
8181 }
8182 $io->write('');
8183 if (isset($package['warning'])) {
8184 $io->write('<warning>' . $package['warning'] . '</warning>');
8185 }
8186 }
8187
8188 if ($showAllTypes) {
8189 $io->write('');
8190 }
8191 }
8192 }
8193
8194 return $exitCode;
8195 }
8196
8197 protected function getRootRequires()
8198 {
8199 $rootPackage = $this->getComposer()->getPackage();
8200
8201 return array_map(
8202 'strtolower',
8203 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
8204 );
8205 }
8206
8207 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
8208 {
8209 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
8210 }
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
8223 {
8224 $name = strtolower($name);
8225 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
8226
8227 $policy = new DefaultPolicy();
8228 $pool = new Pool('dev');
8229 $pool->addRepository($repos);
8230
8231 $matchedPackage = null;
8232 $versions = array();
8233 $matches = $pool->whatProvides($name, $constraint);
8234 foreach ($matches as $index => $package) {
8235
8236  if ($package->getName() !== $name) {
8237 unset($matches[$index]);
8238 continue;
8239 }
8240
8241
8242  if (null === $version && $installedRepo->hasPackage($package)) {
8243 $matchedPackage = $package;
8244 }
8245
8246 $versions[$package->getPrettyVersion()] = $package->getVersion();
8247 $matches[$index] = $package->getId();
8248 }
8249
8250
8251  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
8252 $matchedPackage = $pool->literalToPackage($preferred[0]);
8253 }
8254
8255 return array($matchedPackage, $versions);
8256 }
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266 protected function printPackageInfo(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
8267 {
8268 $io = $this->getIO();
8269
8270 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
8271 $this->printLinks($package, 'requires');
8272 $this->printLinks($package, 'devRequires', 'requires (dev)');
8273
8274 if ($package->getSuggests()) {
8275 $io->write("\n<info>suggests</info>");
8276 foreach ($package->getSuggests() as $suggested => $reason) {
8277 $io->write($suggested . ' <comment>' . $reason . '</comment>');
8278 }
8279 }
8280
8281 $this->printLinks($package, 'provides');
8282 $this->printLinks($package, 'conflicts');
8283 $this->printLinks($package, 'replaces');
8284 }
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
8295 {
8296 $io = $this->getIO();
8297 $io->write('<info>name</info>     : ' . $package->getPrettyName());
8298 $io->write('<info>descrip.</info> : ' . $package->getDescription());
8299 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
8300 $this->printVersions($package, $versions, $installedRepo);
8301 if ($latestPackage) {
8302 $style = $this->getVersionStyle($latestPackage, $package);
8303 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
8304 } else {
8305 $latestPackage = $package;
8306 }
8307 $io->write('<info>type</info>     : ' . $package->getType());
8308 $this->printLicenses($package);
8309 $io->write('<info>homepage</info> : ' . $package->getHomepage());
8310 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
8311 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
8312 if ($installedRepo->hasPackage($package)) {
8313 $io->write('<info>path</info>     : ' . sprintf('%s', realpath($this->getComposer()->getInstallationManager()->getInstallPath($package))));
8314 }
8315 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
8316
8317 if ($latestPackage->isAbandoned()) {
8318 $replacement = ($latestPackage->getReplacementPackage() !== null)
8319 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
8320 : null;
8321
8322 $io->writeError(
8323 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
8324 );
8325 }
8326
8327 if ($package->getSupport()) {
8328 $io->write("\n<info>support</info>");
8329 foreach ($package->getSupport() as $type => $value) {
8330 $io->write('<comment>' . $type . '</comment> : '.$value);
8331 }
8332 }
8333
8334 if ($package->getAutoload()) {
8335 $io->write("\n<info>autoload</info>");
8336 foreach ($package->getAutoload() as $type => $autoloads) {
8337 $io->write('<comment>' . $type . '</comment>');
8338
8339 if ($type === 'psr-0') {
8340 foreach ($autoloads as $name => $path) {
8341 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
8342 }
8343 } elseif ($type === 'psr-4') {
8344 foreach ($autoloads as $name => $path) {
8345 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
8346 }
8347 } elseif ($type === 'classmap') {
8348 $io->write(implode(', ', $autoloads));
8349 }
8350 }
8351 if ($package->getIncludePaths()) {
8352 $io->write('<comment>include-path</comment>');
8353 $io->write(implode(', ', $package->getIncludePaths()));
8354 }
8355 }
8356 }
8357
8358
8359
8360
8361
8362
8363
8364
8365 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
8366 {
8367 uasort($versions, 'version_compare');
8368 $versions = array_keys(array_reverse($versions));
8369
8370
8371  if ($installedRepo->hasPackage($package)) {
8372 $installedVersion = $package->getPrettyVersion();
8373 $key = array_search($installedVersion, $versions);
8374 if (false !== $key) {
8375 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
8376 }
8377 }
8378
8379 $versions = implode(', ', $versions);
8380
8381 $this->getIO()->write('<info>versions</info> : ' . $versions);
8382 }
8383
8384
8385
8386
8387
8388
8389
8390
8391 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
8392 {
8393 $title = $title ?: $linkType;
8394 $io = $this->getIO();
8395 if ($links = $package->{'get'.ucfirst($linkType)}()) {
8396 $io->write("\n<info>" . $title . "</info>");
8397
8398 foreach ($links as $link) {
8399 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
8400 }
8401 }
8402 }
8403
8404
8405
8406
8407
8408
8409 protected function printLicenses(CompletePackageInterface $package)
8410 {
8411 $spdxLicenses = new SpdxLicenses();
8412
8413 $licenses = $package->getLicense();
8414 $io = $this->getIO();
8415
8416 foreach ($licenses as $licenseId) {
8417 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
8418
8419 if (!$license) {
8420 $out = $licenseId;
8421 } else {
8422
8423  if ($license[1] === true) {
8424 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
8425 } else {
8426 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
8427 }
8428 }
8429
8430 $io->write('<info>license</info>  : ' . $out);
8431 }
8432 }
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442 protected function printPackageInfoAsJson(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
8443 {
8444 $json = array(
8445 'name' => $package->getPrettyName(),
8446 'description' => $package->getDescription(),
8447 'keywords' => $package->getKeywords() ?: array(),
8448 'type' => $package->getType(),
8449 'homepage' => $package->getHomepage(),
8450 'names' => $package->getNames()
8451 );
8452
8453 $json = $this->appendVersions($json, $versions);
8454 $json = $this->appendLicenses($json, $package);
8455
8456 if ($latestPackage) {
8457 $json['latest'] = $latestPackage->getPrettyVersion();
8458 } else {
8459 $latestPackage = $package;
8460 }
8461
8462 if ($package->getSourceType()) {
8463 $json['source'] = array(
8464 'type' => $package->getSourceType(),
8465 'url' => $package->getSourceUrl(),
8466 'reference' => $package->getSourceReference()
8467 );
8468 }
8469
8470 if ($package->getDistType()) {
8471 $json['dist'] = array(
8472 'type' => $package->getDistType(),
8473 'url' => $package->getDistUrl(),
8474 'reference' => $package->getDistReference()
8475 );
8476 }
8477
8478 if ($installedRepo->hasPackage($package)) {
8479 $json['path'] = realpath($this->getComposer()->getInstallationManager()->getInstallPath($package));
8480 if ($json['path'] === false) {
8481 unset($json['path']);
8482 }
8483 }
8484
8485 if ($latestPackage->isAbandoned()) {
8486 $json['replacement'] = $latestPackage->getReplacementPackage();
8487 }
8488
8489 if ($package->getSuggests()) {
8490 $json['suggests'] = $package->getSuggests();
8491 }
8492
8493 if ($package->getSupport()) {
8494 $json['support'] = $package->getSupport();
8495 }
8496
8497 $json = $this->appendAutoload($json, $package);
8498
8499 if ($package->getIncludePaths()) {
8500 $json['include_path'] = $package->getIncludePaths();
8501 }
8502
8503 $json = $this->appendLinks($json, $package);
8504
8505 $this->getIO()->write(JsonFile::encode($json));
8506 }
8507
8508 private function appendVersions($json, array $versions)
8509 {
8510 uasort($versions, 'version_compare');
8511 $versions = array_keys(array_reverse($versions));
8512 $json['versions'] = $versions;
8513
8514 return $json;
8515 }
8516
8517 private function appendLicenses($json, CompletePackageInterface $package)
8518 {
8519 if ($licenses = $package->getLicense()) {
8520 $spdxLicenses = new SpdxLicenses();
8521
8522 $json['licenses'] = array_map(function ($licenseId) use ($spdxLicenses) {
8523 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
8524
8525 if (!$license) {
8526 return $licenseId;
8527 }
8528
8529 return array(
8530 'name' => $license[0],
8531 'osi' => $licenseId,
8532 'url' => $license[2]
8533 );
8534 }, $licenses);
8535 }
8536
8537 return $json;
8538 }
8539
8540 private function appendAutoload($json, CompletePackageInterface $package)
8541 {
8542 if ($package->getAutoload()) {
8543 $autoload = array();
8544
8545 foreach ($package->getAutoload() as $type => $autoloads) {
8546 if ($type === 'psr-0' || $type === 'psr-4') {
8547 $psr = array();
8548
8549 foreach ($autoloads as $name => $path) {
8550 if (!$path) {
8551 $path = '.';
8552 }
8553
8554 $psr[$name ?: '*'] = $path;
8555 }
8556
8557 $autoload[$type] = $psr;
8558 } elseif ($type === 'classmap') {
8559 $autoload['classmap'] = $autoloads;
8560 }
8561 }
8562
8563 $json['autoload'] = $autoload;
8564 }
8565
8566 return $json;
8567 }
8568
8569 private function appendLinks($json, CompletePackageInterface $package)
8570 {
8571 foreach (array('requires', 'devRequires', 'provides', 'conflicts', 'replaces') as $linkType) {
8572 $json = $this->appendLink($json, $package, $linkType);
8573 }
8574
8575 return $json;
8576 }
8577
8578 private function appendLink($json, CompletePackageInterface $package, $linkType)
8579 {
8580 $links = $package->{'get' . ucfirst($linkType)}();
8581
8582 if ($links) {
8583 $json[$linkType] = array();
8584
8585 foreach ($links as $link) {
8586 $json[$linkType][$link->getTarget()] = $link->getPrettyConstraint();
8587 }
8588 }
8589
8590 return $json;
8591 }
8592
8593
8594
8595
8596
8597
8598 protected function initStyles(OutputInterface $output)
8599 {
8600 $this->colors = array(
8601 'green',
8602 'yellow',
8603 'cyan',
8604 'magenta',
8605 'blue',
8606 );
8607
8608 foreach ($this->colors as $color) {
8609 $style = new OutputFormatterStyle($color);
8610 $output->getFormatter()->setStyle($color, $style);
8611 }
8612 }
8613
8614
8615
8616
8617
8618
8619 protected function displayPackageTree(array $arrayTree)
8620 {
8621 $io = $this->getIO();
8622 foreach ($arrayTree as $package) {
8623 $io->write(sprintf('<info>%s</info>', $package['name']), false);
8624 $io->write(' ' . $package['version'], false);
8625 $io->write(' ' . strtok($package['description'], "\r\n"));
8626
8627 if (isset($package['requires'])) {
8628 $requires = $package['requires'];
8629 $treeBar = '├';
8630 $j = 0;
8631 $total = count($requires);
8632 foreach ($requires as $require) {
8633 $requireName = $require['name'];
8634 $j++;
8635 if ($j === $total) {
8636 $treeBar = '└';
8637 }
8638 $level = 1;
8639 $color = $this->colors[$level];
8640 $info = sprintf(
8641 '%s──<%s>%s</%s> %s',
8642 $treeBar,
8643 $color,
8644 $requireName,
8645 $color,
8646 $require['version']
8647 );
8648 $this->writeTreeLine($info);
8649
8650 $treeBar = str_replace('└', ' ', $treeBar);
8651 $packagesInTree = array($package['name'], $requireName);
8652
8653 $this->displayTree($require, $packagesInTree, $treeBar, $level + 1);
8654 }
8655 }
8656 }
8657 }
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667 protected function generatePackageTree(
8668 PackageInterface $package,
8669 RepositoryInterface $installedRepo,
8670 RepositoryInterface $distantRepos
8671 ) {
8672 $requires = $package->getRequires();
8673 ksort($requires);
8674 $children = array();
8675 foreach ($requires as $requireName => $require) {
8676 $packagesInTree = array($package->getName(), $requireName);
8677
8678 $treeChildDesc = array(
8679 'name' => $requireName,
8680 'version' => $require->getPrettyConstraint(),
8681 );
8682
8683 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree);
8684
8685 if ($deepChildren) {
8686 $treeChildDesc['requires'] = $deepChildren;
8687 }
8688
8689 $children[] = $treeChildDesc;
8690 }
8691 $tree = array(
8692 'name' => $package->getPrettyName(),
8693 'version' => $package->getPrettyVersion(),
8694 'description' => $package->getDescription(),
8695 );
8696
8697 if ($children) {
8698 $tree['requires'] = $children;
8699 }
8700
8701 return $tree;
8702 }
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712 protected function displayTree(
8713 $package,
8714 array $packagesInTree,
8715 $previousTreeBar = '├',
8716 $level = 1
8717 ) {
8718 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
8719 if (isset($package['requires'])) {
8720 $requires = $package['requires'];
8721 $treeBar = $previousTreeBar . '  ├';
8722 $i = 0;
8723 $total = count($requires);
8724 foreach ($requires as $require) {
8725 $currentTree = $packagesInTree;
8726 $i++;
8727 if ($i === $total) {
8728 $treeBar = $previousTreeBar . '  └';
8729 }
8730 $colorIdent = $level % count($this->colors);
8731 $color = $this->colors[$colorIdent];
8732
8733 $circularWarn = in_array(
8734 $require['name'],
8735 $currentTree,
8736 true
8737 ) ? '(circular dependency aborted here)' : '';
8738 $info = rtrim(sprintf(
8739 '%s──<%s>%s</%s> %s %s',
8740 $treeBar,
8741 $color,
8742 $require['name'],
8743 $color,
8744 $require['version'],
8745 $circularWarn
8746 ));
8747 $this->writeTreeLine($info);
8748
8749 $treeBar = str_replace('└', ' ', $treeBar);
8750
8751 $currentTree[] = $require['name'];
8752 $this->displayTree($require, $currentTree, $treeBar, $level + 1);
8753 }
8754 }
8755 }
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767 protected function addTree(
8768 $name,
8769 $package,
8770 RepositoryInterface $installedRepo,
8771 RepositoryInterface $distantRepos,
8772 array $packagesInTree
8773 ) {
8774 $children = array();
8775 list($package, $versions) = $this->getPackage(
8776 $installedRepo,
8777 $distantRepos,
8778 $name,
8779 $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint()
8780 );
8781 if (is_object($package)) {
8782 $requires = $package->getRequires();
8783 ksort($requires);
8784 foreach ($requires as $requireName => $require) {
8785 $currentTree = $packagesInTree;
8786
8787 $treeChildDesc = array(
8788 'name' => $requireName,
8789 'version' => $require->getPrettyConstraint(),
8790 );
8791
8792 if (!in_array($requireName, $currentTree, true)) {
8793 $currentTree[] = $requireName;
8794 $deepChildren = $this->addTree($requireName, $require, $installedRepo, $distantRepos, $currentTree);
8795 if ($deepChildren) {
8796 $treeChildDesc['requires'] = $deepChildren;
8797 }
8798 }
8799
8800 $children[] = $treeChildDesc;
8801 }
8802 }
8803
8804 return $children;
8805 }
8806
8807 private function updateStatusToVersionStyle($updateStatus)
8808 {
8809
8810  
8811  
8812  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
8813 }
8814
8815 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
8816 {
8817 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
8818 return 'up-to-date';
8819 }
8820
8821 $constraint = $package->getVersion();
8822 if (0 !== strpos($constraint, 'dev-')) {
8823 $constraint = '^'.$constraint;
8824 }
8825 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
8826
8827  return 'semver-safe-update';
8828 }
8829
8830
8831  return 'update-possible';
8832 }
8833
8834 private function writeTreeLine($line)
8835 {
8836 $io = $this->getIO();
8837 if (!$io->isDecorated()) {
8838 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
8839 }
8840
8841 $io->write($line);
8842 }
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
8855 {
8856
8857  $name = $package->getName();
8858 $versionSelector = new VersionSelector($this->getPool($composer));
8859 $stability = $composer->getPackage()->getMinimumStability();
8860 $flags = $composer->getPackage()->getStabilityFlags();
8861 if (isset($flags[$name])) {
8862 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
8863 }
8864
8865 $bestStability = $stability;
8866 if ($composer->getPackage()->getPreferStable()) {
8867 $bestStability = $package->getStability();
8868 }
8869
8870 $targetVersion = null;
8871 if (0 === strpos($package->getVersion(), 'dev-')) {
8872 $targetVersion = $package->getVersion();
8873 }
8874
8875 if ($targetVersion === null && $minorOnly) {
8876 $targetVersion = '^' . $package->getVersion();
8877 }
8878
8879 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
8880 }
8881
8882 private function getPool(Composer $composer)
8883 {
8884 if (!$this->pool) {
8885 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
8886 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
8887 }
8888
8889 return $this->pool;
8890 }
8891 }
8892 <?php
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904 namespace Composer\Command;
8905
8906 use Symfony\Component\Console\Input\InputInterface;
8907 use Symfony\Component\Console\Input\InputOption;
8908 use Symfony\Component\Console\Output\OutputInterface;
8909 use Composer\Downloader\ChangeReportInterface;
8910 use Composer\Downloader\DvcsDownloaderInterface;
8911 use Composer\Downloader\VcsCapableDownloaderInterface;
8912 use Composer\Package\Dumper\ArrayDumper;
8913 use Composer\Package\Version\VersionGuesser;
8914 use Composer\Package\Version\VersionParser;
8915 use Composer\Plugin\CommandEvent;
8916 use Composer\Plugin\PluginEvents;
8917 use Composer\Script\ScriptEvents;
8918 use Composer\Util\ProcessExecutor;
8919
8920
8921
8922
8923
8924 class StatusCommand extends BaseCommand
8925 {
8926 const EXIT_CODE_ERRORS = 1;
8927 const EXIT_CODE_UNPUSHED_CHANGES = 2;
8928 const EXIT_CODE_VERSION_CHANGES = 4;
8929
8930
8931
8932
8933 protected function configure()
8934 {
8935 $this
8936 ->setName('status')
8937 ->setDescription('Shows a list of locally modified packages, for packages installed from source.')
8938 ->setDefinition(array(
8939 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
8940 ))
8941 ->setHelp(
8942 <<<EOT
8943 The status command displays a list of dependencies that have
8944 been modified locally.
8945
8946 Read more at https://getcomposer.org/doc/03-cli.md#status
8947 EOT
8948 )
8949 ;
8950 }
8951
8952
8953
8954
8955
8956
8957 protected function execute(InputInterface $input, OutputInterface $output)
8958 {
8959 $composer = $this->getComposer();
8960
8961 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
8962 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8963
8964
8965  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
8966
8967 $exitCode = $this->doExecute($input, $output);
8968
8969
8970  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
8971
8972 return $exitCode;
8973 }
8974
8975
8976
8977
8978
8979
8980 private function doExecute(InputInterface $input, OutputInterface $output)
8981 {
8982
8983  $composer = $this->getComposer();
8984
8985 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
8986
8987 $dm = $composer->getDownloadManager();
8988 $im = $composer->getInstallationManager();
8989
8990 $errors = array();
8991 $io = $this->getIO();
8992 $unpushedChanges = array();
8993 $vcsVersionChanges = array();
8994
8995 $parser = new VersionParser;
8996 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
8997 $dumper = new ArrayDumper;
8998
8999
9000  foreach ($installedRepo->getCanonicalPackages() as $package) {
9001 $downloader = $dm->getDownloaderForInstalledPackage($package);
9002 $targetDir = $im->getInstallPath($package);
9003
9004 if ($downloader instanceof ChangeReportInterface) {
9005 if (is_link($targetDir)) {
9006 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
9007 }
9008
9009 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
9010 $errors[$targetDir] = $changes;
9011 }
9012 }
9013
9014 if ($downloader instanceof VcsCapableDownloaderInterface) {
9015 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
9016 switch ($package->getInstallationSource()) {
9017 case 'source':
9018 $previousRef = $package->getSourceReference();
9019 break;
9020 case 'dist':
9021 $previousRef = $package->getDistReference();
9022 break;
9023 default:
9024 $previousRef = null;
9025 }
9026
9027 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
9028
9029 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
9030 $vcsVersionChanges[$targetDir] = array(
9031 'previous' => array(
9032 'version' => $package->getPrettyVersion(),
9033 'ref' => $previousRef,
9034 ),
9035 'current' => array(
9036 'version' => $currentVersion['pretty_version'],
9037 'ref' => $currentVersion['commit'],
9038 ),
9039 );
9040 }
9041 }
9042 }
9043
9044 if ($downloader instanceof DvcsDownloaderInterface) {
9045 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
9046 $unpushedChanges[$targetDir] = $unpushed;
9047 }
9048 }
9049 }
9050
9051
9052  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
9053 $io->writeError('<info>No local changes</info>');
9054
9055 return 0;
9056 }
9057
9058 if ($errors) {
9059 $io->writeError('<error>You have changes in the following dependencies:</error>');
9060
9061 foreach ($errors as $path => $changes) {
9062 if ($input->getOption('verbose')) {
9063 $indentedChanges = implode("\n", array_map(function ($line) {
9064 return '    ' . ltrim($line);
9065 }, explode("\n", $changes)));
9066 $io->write('<info>'.$path.'</info>:');
9067 $io->write($indentedChanges);
9068 } else {
9069 $io->write($path);
9070 }
9071 }
9072 }
9073
9074 if ($unpushedChanges) {
9075 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
9076
9077 foreach ($unpushedChanges as $path => $changes) {
9078 if ($input->getOption('verbose')) {
9079 $indentedChanges = implode("\n", array_map(function ($line) {
9080 return '    ' . ltrim($line);
9081 }, explode("\n", $changes)));
9082 $io->write('<info>'.$path.'</info>:');
9083 $io->write($indentedChanges);
9084 } else {
9085 $io->write($path);
9086 }
9087 }
9088 }
9089
9090 if ($vcsVersionChanges) {
9091 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
9092
9093 foreach ($vcsVersionChanges as $path => $changes) {
9094 if ($input->getOption('verbose')) {
9095
9096  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
9097 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
9098
9099 if ($io->isVeryVerbose()) {
9100
9101  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
9102 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
9103 }
9104
9105 $io->write('<info>'.$path.'</info>:');
9106 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
9107 } else {
9108 $io->write($path);
9109 }
9110 }
9111 }
9112
9113 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
9114 $io->writeError('Use --verbose (-v) to see a list of files');
9115 }
9116
9117 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
9118 }
9119 }
9120 <?php
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132 namespace Composer\Command;
9133
9134 use Composer\Repository\PlatformRepository;
9135 use Symfony\Component\Console\Input\InputArgument;
9136 use Symfony\Component\Console\Input\InputInterface;
9137 use Symfony\Component\Console\Input\InputOption;
9138 use Symfony\Component\Console\Output\OutputInterface;
9139
9140 class SuggestsCommand extends BaseCommand
9141 {
9142 protected function configure()
9143 {
9144 $this
9145 ->setName('suggests')
9146 ->setDescription('Shows package suggestions.')
9147 ->setDefinition(array(
9148 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
9149 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
9150 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
9151 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
9152 ))
9153 ->setHelp(
9154 <<<EOT
9155
9156 The <info>%command.name%</info> command shows a sorted list of suggested packages.
9157
9158 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
9159
9160 Read more at https://getcomposer.org/doc/03-cli.md#suggests
9161 EOT
9162 )
9163 ;
9164 }
9165
9166 protected function execute(InputInterface $input, OutputInterface $output)
9167 {
9168 $lock = $this->getComposer()->getLocker()->getLockData();
9169
9170 if (empty($lock)) {
9171 throw new \RuntimeException('Lockfile seems to be empty?');
9172 }
9173
9174 $packages = $lock['packages'];
9175
9176 if (!$input->getOption('no-dev')) {
9177 $packages += $lock['packages-dev'];
9178 }
9179
9180 $filter = $input->getArgument('packages');
9181
9182
9183  $installed = array();
9184 foreach ($packages as $package) {
9185 $installed[] = $package['name'];
9186
9187 if (!empty($package['provide'])) {
9188 $installed = array_merge($installed, array_keys($package['provide']));
9189 }
9190
9191 if (!empty($package['replace'])) {
9192 $installed = array_merge($installed, array_keys($package['replace']));
9193 }
9194 }
9195
9196
9197  $installed = array_flip($installed);
9198 ksort($installed);
9199
9200
9201  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
9202
9203
9204  $suggesters = array();
9205 $suggested = array();
9206 foreach ($packages as $package) {
9207 $packageName = $package['name'];
9208 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
9209 continue;
9210 }
9211 foreach ($package['suggest'] as $suggestion => $reason) {
9212 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $suggestion) && null !== $platform->findPackage($suggestion, '*')) {
9213 continue;
9214 }
9215 if (!isset($installed[$suggestion])) {
9216 $suggesters[$packageName][$suggestion] = $reason;
9217 $suggested[$suggestion][$packageName] = $reason;
9218 }
9219 }
9220 }
9221 ksort($suggesters);
9222 ksort($suggested);
9223
9224
9225  $mode = 0;
9226 $io = $this->getIO();
9227 if ($input->getOption('by-package') || $io->isVerbose()) {
9228 $mode |= 1;
9229 }
9230 if ($input->getOption('by-suggestion')) {
9231 $mode |= 2;
9232 }
9233
9234
9235  if ($mode === 0) {
9236 foreach (array_keys($suggested) as $suggestion) {
9237 $io->write(sprintf('<info>%s</info>', $suggestion));
9238 }
9239
9240 return 0;
9241 }
9242
9243
9244  if ($mode & 1) {
9245 foreach ($suggesters as $suggester => $suggestions) {
9246 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
9247
9248 foreach ($suggestions as $suggestion => $reason) {
9249 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
9250 }
9251 $io->write('');
9252 }
9253 }
9254
9255
9256  if ($mode & 2) {
9257
9258  if ($mode & 1) {
9259 $io->write(str_repeat('-', 78));
9260 }
9261 foreach ($suggested as $suggestion => $suggesters) {
9262 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
9263
9264 foreach ($suggesters as $suggester => $reason) {
9265 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
9266 }
9267 $io->write('');
9268 }
9269 }
9270
9271 return 0;
9272 }
9273 }
9274 <?php
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286 namespace Composer\Command;
9287
9288 use Composer\Composer;
9289 use Composer\Installer;
9290 use Composer\IO\IOInterface;
9291 use Composer\Plugin\CommandEvent;
9292 use Composer\Plugin\PluginEvents;
9293 use Symfony\Component\Console\Helper\Table;
9294 use Symfony\Component\Console\Input\InputInterface;
9295 use Symfony\Component\Console\Input\InputOption;
9296 use Symfony\Component\Console\Input\InputArgument;
9297 use Symfony\Component\Console\Output\OutputInterface;
9298 use Symfony\Component\Console\Question\Question;
9299
9300
9301
9302
9303
9304 class UpdateCommand extends BaseCommand
9305 {
9306 protected function configure()
9307 {
9308 $this
9309 ->setName('update')
9310 ->setAliases(array('u', 'upgrade'))
9311 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
9312 ->setDefinition(array(
9313 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
9314 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
9315 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
9316 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
9317 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
9318 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
9319 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
9320 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
9321 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
9322 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
9323 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
9324 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
9325 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, except those defined in root package.'),
9326 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.'),
9327 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
9328 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
9329 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
9330 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
9331 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
9332 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
9333 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
9334 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
9335 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
9336 ))
9337 ->setHelp(
9338 <<<EOT
9339 The <info>update</info> command reads the composer.json file from the
9340 current directory, processes it, and updates, removes or installs all the
9341 dependencies.
9342
9343 <info>php composer.phar update</info>
9344
9345 To limit the update operation to a few packages, you can list the package(s)
9346 you want to update as such:
9347
9348 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
9349
9350 You may also use an asterisk (*) pattern to limit the update operation to package(s)
9351 from a specific vendor:
9352
9353 <info>php composer.phar update vendor/package1 foo/* [...]</info>
9354
9355 To select packages names interactively with auto-completion use <info>-i</info>.
9356
9357 Read more at https://getcomposer.org/doc/03-cli.md#update-u
9358 EOT
9359 )
9360 ;
9361 }
9362
9363 protected function execute(InputInterface $input, OutputInterface $output)
9364 {
9365 $io = $this->getIO();
9366 if ($input->getOption('no-custom-installers')) {
9367 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
9368 $input->setOption('no-plugins', true);
9369 }
9370
9371 if ($input->getOption('dev')) {
9372 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
9373 }
9374
9375 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
9376
9377 $packages = $input->getArgument('packages');
9378
9379 if ($input->getOption('interactive')) {
9380 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
9381 }
9382
9383 if ($input->getOption('root-reqs')) {
9384 $require = array_keys($composer->getPackage()->getRequires());
9385 if (!$input->getOption('no-dev')) {
9386 $requireDev = array_keys($composer->getPackage()->getDevRequires());
9387 $require = array_merge($require, $requireDev);
9388 }
9389
9390 if (!empty($packages)) {
9391 $packages = array_intersect($packages, $require);
9392 } else {
9393 $packages = $require;
9394 }
9395 }
9396
9397 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
9398
9399 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
9400 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
9401
9402 $install = Installer::create($io, $composer);
9403
9404 $config = $composer->getConfig();
9405 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
9406
9407 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
9408 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
9409 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
9410
9411 $install
9412 ->setDryRun($input->getOption('dry-run'))
9413 ->setVerbose($input->getOption('verbose'))
9414 ->setPreferSource($preferSource)
9415 ->setPreferDist($preferDist)
9416 ->setDevMode(!$input->getOption('no-dev'))
9417 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
9418 ->setRunScripts(!$input->getOption('no-scripts'))
9419 ->setSkipSuggest($input->getOption('no-suggest'))
9420 ->setOptimizeAutoloader($optimize)
9421 ->setClassMapAuthoritative($authoritative)
9422 ->setApcuAutoloader($apcu)
9423 ->setUpdate(true)
9424 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
9425 ->setWhitelistTransitiveDependencies($input->getOption('with-dependencies'))
9426 ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
9427 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
9428 ->setPreferStable($input->getOption('prefer-stable'))
9429 ->setPreferLowest($input->getOption('prefer-lowest'))
9430 ;
9431
9432 if ($input->getOption('no-plugins')) {
9433 $install->disablePlugins();
9434 }
9435
9436 return $install->run();
9437 }
9438
9439 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
9440 {
9441 if (!$input->isInteractive()) {
9442 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
9443 }
9444
9445 $requires = array_merge(
9446 $composer->getPackage()->getRequires(),
9447 $composer->getPackage()->getDevRequires()
9448 );
9449 $autocompleterValues = array();
9450 foreach ($requires as $require) {
9451 $target = $require->getTarget();
9452 $autocompleterValues[strtolower($target)] = $target;
9453 }
9454
9455 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
9456 foreach ($installedPackages as $package) {
9457 $autocompleterValues[$package->getName()] = $package->getPrettyName();
9458 }
9459
9460 $helper = $this->getHelper('question');
9461 $question = new Question('<comment>Enter package name: </comment>', null);
9462
9463 $io->writeError('<info>Press enter without value to end submission</info>');
9464
9465 do {
9466 $autocompleterValues = array_diff($autocompleterValues, $packages);
9467 $question->setAutocompleterValues($autocompleterValues);
9468 $addedPackage = $helper->ask($input, $output, $question);
9469
9470 if (!is_string($addedPackage) || empty($addedPackage)) {
9471 break;
9472 }
9473
9474 $addedPackage = strtolower($addedPackage);
9475 if (!in_array($addedPackage, $packages)) {
9476 $packages[] = $addedPackage;
9477 }
9478 } while (true);
9479
9480 $packages = array_filter($packages);
9481 if (!$packages) {
9482 throw new \InvalidArgumentException('You must enter minimum one package.');
9483 }
9484
9485 $table = new Table($output);
9486 $table->setHeaders(array('Selected packages'));
9487 foreach ($packages as $package) {
9488 $table->addRow(array($package));
9489 }
9490 $table->render();
9491
9492 if ($io->askConfirmation(sprintf(
9493 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
9494 1 === count($packages) ? '' : 's'
9495 ), true)) {
9496 return $packages;
9497 }
9498
9499 throw new \RuntimeException('Installation aborted.');
9500 }
9501 }
9502 <?php
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514 namespace Composer\Command;
9515
9516 use Composer\Factory;
9517 use Composer\Package\Loader\ValidatingArrayLoader;
9518 use Composer\Plugin\CommandEvent;
9519 use Composer\Plugin\PluginEvents;
9520 use Composer\Util\ConfigValidator;
9521 use Symfony\Component\Console\Input\InputArgument;
9522 use Symfony\Component\Console\Input\InputInterface;
9523 use Symfony\Component\Console\Input\InputOption;
9524 use Symfony\Component\Console\Output\OutputInterface;
9525
9526
9527
9528
9529
9530
9531
9532 class ValidateCommand extends BaseCommand
9533 {
9534
9535
9536
9537 protected function configure()
9538 {
9539 $this
9540 ->setName('validate')
9541 ->setDescription('Validates a composer.json and composer.lock.')
9542 ->setDefinition(array(
9543 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not validate requires for overly strict/loose constraints'),
9544 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
9545 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
9546 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
9547 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
9548 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file'),
9549 ))
9550 ->setHelp(
9551 <<<EOT
9552 The validate command validates a given composer.json and composer.lock
9553
9554 Exit codes in case of errors are:
9555 1 validation warning(s), only when --strict is given
9556 2 validation error(s)
9557 3 file unreadable or missing
9558
9559 Read more at https://getcomposer.org/doc/03-cli.md#validate
9560 EOT
9561 );
9562 }
9563
9564
9565
9566
9567
9568
9569
9570 protected function execute(InputInterface $input, OutputInterface $output)
9571 {
9572 $file = $input->getArgument('file') ?: Factory::getComposerFile();
9573 $io = $this->getIO();
9574
9575 if (!file_exists($file)) {
9576 $io->writeError('<error>' . $file . ' not found.</error>');
9577
9578 return 3;
9579 }
9580 if (!is_readable($file)) {
9581 $io->writeError('<error>' . $file . ' is not readable.</error>');
9582
9583 return 3;
9584 }
9585
9586 $validator = new ConfigValidator($io);
9587 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
9588 $checkPublish = !$input->getOption('no-check-publish');
9589 $checkLock = !$input->getOption('no-check-lock');
9590 $isStrict = $input->getOption('strict');
9591 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
9592
9593 $lockErrors = array();
9594 $composer = Factory::create($io, $file, $input->hasParameterOption('--no-plugins'));
9595 $locker = $composer->getLocker();
9596 if ($locker->isLocked() && !$locker->isFresh()) {
9597 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update` or `composer update <package name>`.';
9598 }
9599
9600 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
9601
9602
9603  $exitCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
9604
9605 if ($input->getOption('with-dependencies')) {
9606 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
9607 foreach ($localRepo->getPackages() as $package) {
9608 $path = $composer->getInstallationManager()->getInstallPath($package);
9609 $file = $path . '/composer.json';
9610 if (is_dir($path) && file_exists($file)) {
9611 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
9612
9613 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
9614
9615
9616  $depCode = $errors ? 2 : ($isStrict && $warnings ? 1 : 0);
9617 $exitCode = max($depCode, $exitCode);
9618 }
9619 }
9620 }
9621
9622 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
9623 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
9624 $exitCode = max($eventCode, $exitCode);
9625
9626 return $exitCode;
9627 }
9628
9629 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
9630 {
9631 $doPrintSchemaUrl = false;
9632
9633 if ($errors) {
9634 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
9635 } elseif ($publishErrors) {
9636 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
9637 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
9638 $doPrintSchemaUrl = $printSchemaUrl;
9639 } elseif ($warnings) {
9640 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
9641 $doPrintSchemaUrl = $printSchemaUrl;
9642 } else {
9643 $io->write('<info>' . $name . ' is valid</info>');
9644
9645  }
9646
9647 if ($doPrintSchemaUrl) {
9648 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
9649 }
9650
9651
9652  $extraWarnings = array();
9653
9654
9655  if ($checkPublish) {
9656 $errors = array_merge($errors, $publishErrors);
9657 } else {
9658 $extraWarnings = array_merge($extraWarnings, $publishErrors);
9659 }
9660
9661
9662  if ($checkLock) {
9663 $errors = array_merge($errors, $lockErrors);
9664 } else {
9665 $extraWarnings = array_merge($extraWarnings, $lockErrors);
9666 }
9667
9668 $messages = array(
9669 'error' => $errors,
9670 'warning' => array_merge($warnings, $extraWarnings),
9671 );
9672
9673 foreach ($messages as $style => $msgs) {
9674 foreach ($msgs as $msg) {
9675 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
9676 }
9677 }
9678 }
9679 }
9680 <?php
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692 namespace Composer;
9693
9694 use Composer\Package\RootPackageInterface;
9695 use Composer\Package\Locker;
9696 use Composer\Repository\RepositoryManager;
9697 use Composer\Installer\InstallationManager;
9698 use Composer\Plugin\PluginManager;
9699 use Composer\Downloader\DownloadManager;
9700 use Composer\EventDispatcher\EventDispatcher;
9701 use Composer\Autoload\AutoloadGenerator;
9702 use Composer\Package\Archiver\ArchiveManager;
9703
9704
9705
9706
9707
9708
9709 class Composer
9710 {
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732 const VERSION = '1.10.7';
9733 const BRANCH_ALIAS_VERSION = '';
9734 const RELEASE_DATE = '2020-06-03 10:03:56';
9735 const SOURCE_VERSION = '';
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746 const RUNTIME_API_VERSION = '1.0.0';
9747
9748 public static function getVersion()
9749 {
9750
9751  if (self::VERSION === '@package_version'.'@') {
9752 return self::SOURCE_VERSION;
9753 }
9754
9755
9756  if (self::BRANCH_ALIAS_VERSION !== '' && preg_match('{^[a-f0-9]{40}$}', self::VERSION)) {
9757 return self::BRANCH_ALIAS_VERSION.'+'.self::VERSION;
9758 }
9759
9760 return self::VERSION;
9761 }
9762
9763
9764
9765
9766 private $package;
9767
9768
9769
9770
9771 private $locker;
9772
9773
9774
9775
9776 private $repositoryManager;
9777
9778
9779
9780
9781 private $downloadManager;
9782
9783
9784
9785
9786 private $installationManager;
9787
9788
9789
9790
9791 private $pluginManager;
9792
9793
9794
9795
9796 private $config;
9797
9798
9799
9800
9801 private $eventDispatcher;
9802
9803
9804
9805
9806 private $autoloadGenerator;
9807
9808
9809
9810
9811 private $archiveManager;
9812
9813
9814
9815
9816
9817 public function setPackage(RootPackageInterface $package)
9818 {
9819 $this->package = $package;
9820 }
9821
9822
9823
9824
9825 public function getPackage()
9826 {
9827 return $this->package;
9828 }
9829
9830
9831
9832
9833 public function setConfig(Config $config)
9834 {
9835 $this->config = $config;
9836 }
9837
9838
9839
9840
9841 public function getConfig()
9842 {
9843 return $this->config;
9844 }
9845
9846
9847
9848
9849 public function setLocker(Locker $locker)
9850 {
9851 $this->locker = $locker;
9852 }
9853
9854
9855
9856
9857 public function getLocker()
9858 {
9859 return $this->locker;
9860 }
9861
9862
9863
9864
9865 public function setRepositoryManager(RepositoryManager $manager)
9866 {
9867 $this->repositoryManager = $manager;
9868 }
9869
9870
9871
9872
9873 public function getRepositoryManager()
9874 {
9875 return $this->repositoryManager;
9876 }
9877
9878
9879
9880
9881 public function setDownloadManager(DownloadManager $manager)
9882 {
9883 $this->downloadManager = $manager;
9884 }
9885
9886
9887
9888
9889 public function getDownloadManager()
9890 {
9891 return $this->downloadManager;
9892 }
9893
9894
9895
9896
9897 public function setArchiveManager(ArchiveManager $manager)
9898 {
9899 $this->archiveManager = $manager;
9900 }
9901
9902
9903
9904
9905 public function getArchiveManager()
9906 {
9907 return $this->archiveManager;
9908 }
9909
9910
9911
9912
9913 public function setInstallationManager(InstallationManager $manager)
9914 {
9915 $this->installationManager = $manager;
9916 }
9917
9918
9919
9920
9921 public function getInstallationManager()
9922 {
9923 return $this->installationManager;
9924 }
9925
9926
9927
9928
9929 public function setPluginManager(PluginManager $manager)
9930 {
9931 $this->pluginManager = $manager;
9932 }
9933
9934
9935
9936
9937 public function getPluginManager()
9938 {
9939 return $this->pluginManager;
9940 }
9941
9942
9943
9944
9945 public function setEventDispatcher(EventDispatcher $eventDispatcher)
9946 {
9947 $this->eventDispatcher = $eventDispatcher;
9948 }
9949
9950
9951
9952
9953 public function getEventDispatcher()
9954 {
9955 return $this->eventDispatcher;
9956 }
9957
9958
9959
9960
9961 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
9962 {
9963 $this->autoloadGenerator = $autoloadGenerator;
9964 }
9965
9966
9967
9968
9969 public function getAutoloadGenerator()
9970 {
9971 return $this->autoloadGenerator;
9972 }
9973 }
9974 <?php
9975
9976
9977
9978
9979
9980
9981
9982
9983
9984
9985
9986 namespace Composer;
9987
9988 use Composer\Config\ConfigSourceInterface;
9989 use Composer\Downloader\TransportException;
9990 use Composer\IO\IOInterface;
9991 use Composer\Util\Platform;
9992 use Composer\Util\ProcessExecutor;
9993
9994
9995
9996
9997 class Config
9998 {
9999 const RELATIVE_PATHS = 1;
10000
10001 public static $defaultConfig = array(
10002 'process-timeout' => 300,
10003 'use-include-path' => false,
10004 'preferred-install' => 'auto',
10005 'notify-on-install' => true,
10006 'github-protocols' => array('https', 'ssh', 'git'),
10007 'vendor-dir' => 'vendor',
10008 'bin-dir' => '{$vendor-dir}/bin',
10009 'cache-dir' => '{$home}/cache',
10010 'data-dir' => '{$home}',
10011 'cache-files-dir' => '{$cache-dir}/files',
10012 'cache-repo-dir' => '{$cache-dir}/repo',
10013 'cache-vcs-dir' => '{$cache-dir}/vcs',
10014 'cache-ttl' => 15552000, 
10015  'cache-files-ttl' => null, 
10016  'cache-files-maxsize' => '300MiB',
10017 'bin-compat' => 'auto',
10018 'discard-changes' => false,
10019 'autoloader-suffix' => null,
10020 'sort-packages' => false,
10021 'optimize-autoloader' => false,
10022 'classmap-authoritative' => false,
10023 'apcu-autoloader' => false,
10024 'prepend-autoloader' => true,
10025 'github-domains' => array('github.com'),
10026 'bitbucket-expose-hostname' => true,
10027 'disable-tls' => false,
10028 'secure-http' => true,
10029 'cafile' => null,
10030 'capath' => null,
10031 'github-expose-hostname' => true,
10032 'gitlab-domains' => array('gitlab.com'),
10033 'store-auths' => 'prompt',
10034 'platform' => array(),
10035 'archive-format' => 'tar',
10036 'archive-dir' => '.',
10037 'htaccess-protect' => true,
10038 'use-github-api' => true,
10039 'lock' => true,
10040
10041  
10042  
10043  
10044  
10045  
10046  
10047  );
10048
10049 public static $defaultRepositories = array(
10050 'packagist.org' => array(
10051 'type' => 'composer',
10052 'url' => 'https?://repo.packagist.org',
10053 'allow_ssl_downgrade' => true,
10054 ),
10055 );
10056
10057 private $config;
10058 private $baseDir;
10059 private $repositories;
10060
10061 private $configSource;
10062
10063 private $authConfigSource;
10064 private $useEnvironment;
10065 private $warnedHosts = array();
10066
10067
10068
10069
10070
10071 public function __construct($useEnvironment = true, $baseDir = null)
10072 {
10073
10074  $this->config = static::$defaultConfig;
10075 $this->repositories = static::$defaultRepositories;
10076 $this->useEnvironment = (bool) $useEnvironment;
10077 $this->baseDir = $baseDir;
10078 }
10079
10080 public function setConfigSource(ConfigSourceInterface $source)
10081 {
10082 $this->configSource = $source;
10083 }
10084
10085 public function getConfigSource()
10086 {
10087 return $this->configSource;
10088 }
10089
10090 public function setAuthConfigSource(ConfigSourceInterface $source)
10091 {
10092 $this->authConfigSource = $source;
10093 }
10094
10095 public function getAuthConfigSource()
10096 {
10097 return $this->authConfigSource;
10098 }
10099
10100
10101
10102
10103
10104
10105 public function merge($config)
10106 {
10107
10108  if (!empty($config['config']) && is_array($config['config'])) {
10109 foreach ($config['config'] as $key => $val) {
10110 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic', 'bearer')) && isset($this->config[$key])) {
10111 $this->config[$key] = array_merge($this->config[$key], $val);
10112 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
10113 if (is_array($val) || is_array($this->config[$key])) {
10114 if (is_string($val)) {
10115 $val = array('*' => $val);
10116 }
10117 if (is_string($this->config[$key])) {
10118 $this->config[$key] = array('*' => $this->config[$key]);
10119 }
10120 $this->config[$key] = array_merge($this->config[$key], $val);
10121
10122  if (isset($this->config[$key]['*'])) {
10123 $wildcard = $this->config[$key]['*'];
10124 unset($this->config[$key]['*']);
10125 $this->config[$key]['*'] = $wildcard;
10126 }
10127 } else {
10128 $this->config[$key] = $val;
10129 }
10130 } else {
10131 $this->config[$key] = $val;
10132 }
10133 }
10134 }
10135
10136 if (!empty($config['repositories']) && is_array($config['repositories'])) {
10137 $this->repositories = array_reverse($this->repositories, true);
10138 $newRepos = array_reverse($config['repositories'], true);
10139 foreach ($newRepos as $name => $repository) {
10140
10141  if (false === $repository) {
10142 $this->disableRepoByName($name);
10143 continue;
10144 }
10145
10146
10147  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
10148 $this->disableRepoByName(key($repository));
10149 continue;
10150 }
10151
10152
10153  if (is_int($name)) {
10154 $this->repositories[] = $repository;
10155 } else {
10156 if ($name === 'packagist') { 
10157  $this->repositories[$name . '.org'] = $repository;
10158 } else {
10159 $this->repositories[$name] = $repository;
10160 }
10161 }
10162 }
10163 $this->repositories = array_reverse($this->repositories, true);
10164 }
10165 }
10166
10167
10168
10169
10170 public function getRepositories()
10171 {
10172 return $this->repositories;
10173 }
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183 public function get($key, $flags = 0)
10184 {
10185 switch ($key) {
10186 case 'vendor-dir':
10187 case 'bin-dir':
10188 case 'process-timeout':
10189 case 'data-dir':
10190 case 'cache-dir':
10191 case 'cache-files-dir':
10192 case 'cache-repo-dir':
10193 case 'cache-vcs-dir':
10194 case 'cafile':
10195 case 'capath':
10196
10197  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
10198
10199 $val = $this->getComposerEnv($env);
10200 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
10201 $val = Platform::expandPath($val);
10202
10203 if (substr($key, -4) !== '-dir') {
10204 return $val;
10205 }
10206
10207 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
10208
10209 case 'htaccess-protect':
10210 $value = $this->getComposerEnv('COMPOSER_HTACCESS_PROTECT');
10211 if (false === $value) {
10212 $value = $this->config[$key];
10213 }
10214 return $value !== 'false' && (bool) $value;
10215
10216 case 'cache-ttl':
10217 return (int) $this->config[$key];
10218
10219 case 'cache-files-maxsize':
10220 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
10221 throw new \RuntimeException(
10222 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
10223 );
10224 }
10225 $size = $matches[1];
10226 if (isset($matches[2])) {
10227 switch (strtolower($matches[2])) {
10228 case 'g':
10229 $size *= 1024;
10230
10231  
10232  case 'm':
10233 $size *= 1024;
10234
10235  
10236  case 'k':
10237 $size *= 1024;
10238 break;
10239 }
10240 }
10241
10242 return $size;
10243
10244 case 'cache-files-ttl':
10245 if (isset($this->config[$key])) {
10246 return (int) $this->config[$key];
10247 }
10248
10249 return (int) $this->config['cache-ttl'];
10250
10251 case 'home':
10252 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
10253
10254 return rtrim($this->process($val, $flags), '/\\');
10255
10256 case 'bin-compat':
10257 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
10258
10259 if (!in_array($value, array('auto', 'full'))) {
10260 throw new \RuntimeException(
10261 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
10262 );
10263 }
10264
10265 return $value;
10266
10267 case 'discard-changes':
10268 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
10269 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
10270 throw new \RuntimeException(
10271 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
10272 );
10273 }
10274 if ('stash' === $env) {
10275 return 'stash';
10276 }
10277
10278
10279  return $env !== 'false' && (bool) $env;
10280 }
10281
10282 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
10283 throw new \RuntimeException(
10284 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
10285 );
10286 }
10287
10288 return $this->config[$key];
10289
10290 case 'github-protocols':
10291 $protos = $this->config['github-protocols'];
10292 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
10293 unset($protos[$index]);
10294 }
10295 if (reset($protos) === 'http') {
10296 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
10297 }
10298
10299 return $protos;
10300
10301 case 'disable-tls':
10302 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10303 case 'secure-http':
10304 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10305 case 'use-github-api':
10306 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10307 case 'lock':
10308 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
10309 default:
10310 if (!isset($this->config[$key])) {
10311 return null;
10312 }
10313
10314 return $this->process($this->config[$key], $flags);
10315 }
10316 }
10317
10318 public function all($flags = 0)
10319 {
10320 $all = array(
10321 'repositories' => $this->getRepositories(),
10322 );
10323 foreach (array_keys($this->config) as $key) {
10324 $all['config'][$key] = $this->get($key, $flags);
10325 }
10326
10327 return $all;
10328 }
10329
10330 public function raw()
10331 {
10332 return array(
10333 'repositories' => $this->getRepositories(),
10334 'config' => $this->config,
10335 );
10336 }
10337
10338
10339
10340
10341
10342
10343
10344 public function has($key)
10345 {
10346 return array_key_exists($key, $this->config);
10347 }
10348
10349
10350
10351
10352
10353
10354
10355
10356 private function process($value, $flags)
10357 {
10358 $config = $this;
10359
10360 if (!is_string($value)) {
10361 return $value;
10362 }
10363
10364 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
10365 return $config->get($match[1], $flags);
10366 }, $value);
10367 }
10368
10369
10370
10371
10372
10373
10374
10375
10376
10377 private function realpath($path)
10378 {
10379 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
10380 return $path;
10381 }
10382
10383 return $this->baseDir . '/' . $path;
10384 }
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395 private function getComposerEnv($var)
10396 {
10397 if ($this->useEnvironment) {
10398 return getenv($var);
10399 }
10400
10401 return false;
10402 }
10403
10404 private function disableRepoByName($name)
10405 {
10406 if (isset($this->repositories[$name])) {
10407 unset($this->repositories[$name]);
10408 } elseif ($name === 'packagist') { 
10409  unset($this->repositories['packagist.org']);
10410 }
10411 }
10412
10413
10414
10415
10416
10417
10418
10419 public function prohibitUrlByConfig($url, IOInterface $io = null)
10420 {
10421
10422  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
10423 return;
10424 }
10425
10426
10427  $scheme = parse_url($url, PHP_URL_SCHEME);
10428 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
10429 if ($this->get('secure-http')) {
10430 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
10431 } elseif ($io) {
10432 $host = parse_url($url, PHP_URL_HOST);
10433 if (!isset($this->warnedHosts[$host])) {
10434 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
10435 }
10436 $this->warnedHosts[$host] = true;
10437 }
10438 }
10439 }
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451 public static function disableProcessTimeout()
10452 {
10453
10454  ProcessExecutor::setTimeout(0);
10455 }
10456 }
10457 <?php
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469 namespace Composer\Config;
10470
10471
10472
10473
10474
10475
10476
10477 interface ConfigSourceInterface
10478 {
10479
10480
10481
10482
10483
10484
10485 public function addRepository($name, $config);
10486
10487
10488
10489
10490
10491
10492 public function removeRepository($name);
10493
10494
10495
10496
10497
10498
10499
10500 public function addConfigSetting($name, $value);
10501
10502
10503
10504
10505
10506
10507 public function removeConfigSetting($name);
10508
10509
10510
10511
10512
10513
10514
10515 public function addProperty($name, $value);
10516
10517
10518
10519
10520
10521
10522 public function removeProperty($name);
10523
10524
10525
10526
10527
10528
10529
10530
10531 public function addLink($type, $name, $value);
10532
10533
10534
10535
10536
10537
10538
10539 public function removeLink($type, $name);
10540
10541
10542
10543
10544
10545
10546 public function getName();
10547 }
10548 <?php
10549
10550
10551
10552
10553
10554
10555
10556
10557
10558
10559
10560 namespace Composer\Config;
10561
10562 use Composer\Json\JsonFile;
10563 use Composer\Json\JsonManipulator;
10564 use Composer\Util\Silencer;
10565
10566
10567
10568
10569
10570
10571
10572 class JsonConfigSource implements ConfigSourceInterface
10573 {
10574
10575
10576
10577 private $file;
10578
10579
10580
10581
10582 private $authConfig;
10583
10584
10585
10586
10587
10588
10589
10590 public function __construct(JsonFile $file, $authConfig = false)
10591 {
10592 $this->file = $file;
10593 $this->authConfig = $authConfig;
10594 }
10595
10596
10597
10598
10599 public function getName()
10600 {
10601 return $this->file->getPath();
10602 }
10603
10604
10605
10606
10607 public function addRepository($name, $config)
10608 {
10609 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
10610
10611  
10612  if (isset($config['repositories'])) {
10613 foreach ($config['repositories'] as $index => $val) {
10614 if ($index === $repo) {
10615 continue;
10616 }
10617 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
10618 unset($config['repositories'][$index]);
10619 $config['repositories']['packagist.org'] = false;
10620 break;
10621 }
10622 }
10623 }
10624
10625 $config['repositories'][$repo] = $repoConfig;
10626 });
10627 }
10628
10629
10630
10631
10632 public function removeRepository($name)
10633 {
10634 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
10635 unset($config['repositories'][$repo]);
10636 });
10637 }
10638
10639
10640
10641
10642 public function addConfigSetting($name, $value)
10643 {
10644 $authConfig = $this->authConfig;
10645 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
10646 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) {
10647 list($key, $host) = explode('.', $key, 2);
10648 if ($authConfig) {
10649 $config[$key][$host] = $val;
10650 } else {
10651 $config['config'][$key][$host] = $val;
10652 }
10653 } else {
10654 $config['config'][$key] = $val;
10655 }
10656 });
10657 }
10658
10659
10660
10661
10662 public function removeConfigSetting($name)
10663 {
10664 $authConfig = $this->authConfig;
10665 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
10666 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) {
10667 list($key, $host) = explode('.', $key, 2);
10668 if ($authConfig) {
10669 unset($config[$key][$host]);
10670 } else {
10671 unset($config['config'][$key][$host]);
10672 }
10673 } else {
10674 unset($config['config'][$key]);
10675 }
10676 });
10677 }
10678
10679
10680
10681
10682 public function addProperty($name, $value)
10683 {
10684 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
10685 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10686 $bits = explode('.', $key);
10687 $last = array_pop($bits);
10688 $arr = &$config[reset($bits)];
10689 foreach ($bits as $bit) {
10690 if (!isset($arr[$bit])) {
10691 $arr[$bit] = array();
10692 }
10693 $arr = &$arr[$bit];
10694 }
10695 $arr[$last] = $val;
10696 } else {
10697 $config[$key] = $val;
10698 }
10699 });
10700 }
10701
10702
10703
10704
10705 public function removeProperty($name)
10706 {
10707 $authConfig = $this->authConfig;
10708 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
10709 if (substr($key, 0, 6) === 'extra.' || substr($key, 0, 8) === 'scripts.') {
10710 $bits = explode('.', $key);
10711 $last = array_pop($bits);
10712 $arr = &$config[reset($bits)];
10713 foreach ($bits as $bit) {
10714 if (!isset($arr[$bit])) {
10715 return;
10716 }
10717 $arr = &$arr[$bit];
10718 }
10719 unset($arr[$last]);
10720 } else {
10721 unset($config[$key]);
10722 }
10723 });
10724 }
10725
10726
10727
10728
10729 public function addLink($type, $name, $value)
10730 {
10731 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
10732 $config[$type][$name] = $value;
10733 });
10734 }
10735
10736
10737
10738
10739 public function removeLink($type, $name)
10740 {
10741 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
10742 unset($config[$type][$name]);
10743
10744 if (0 === count($config[$type])) {
10745 unset($config[$type]);
10746 }
10747 });
10748 }
10749
10750 protected function manipulateJson($method, $args, $fallback)
10751 {
10752 $args = func_get_args();
10753
10754  array_shift($args);
10755 $fallback = array_pop($args);
10756
10757 if ($this->file->exists()) {
10758 if (!is_writable($this->file->getPath())) {
10759 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
10760 }
10761
10762 if (!is_readable($this->file->getPath())) {
10763 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
10764 }
10765
10766 $contents = file_get_contents($this->file->getPath());
10767 } elseif ($this->authConfig) {
10768 $contents = "{\n}\n";
10769 } else {
10770 $contents = "{\n    \"config\": {\n    }\n}\n";
10771 }
10772
10773 $manipulator = new JsonManipulator($contents);
10774
10775 $newFile = !$this->file->exists();
10776
10777
10778  if ($this->authConfig && $method === 'addConfigSetting') {
10779 $method = 'addSubNode';
10780 list($mainNode, $name) = explode('.', $args[0], 2);
10781 $args = array($mainNode, $name, $args[1]);
10782 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
10783 $method = 'removeSubNode';
10784 list($mainNode, $name) = explode('.', $args[0], 2);
10785 $args = array($mainNode, $name);
10786 }
10787
10788
10789  if (call_user_func_array(array($manipulator, $method), $args)) {
10790 file_put_contents($this->file->getPath(), $manipulator->getContents());
10791 } else {
10792
10793  $config = $this->file->read();
10794 $this->arrayUnshiftRef($args, $config);
10795 call_user_func_array($fallback, $args);
10796
10797  foreach (array('require', 'require-dev', 'conflict', 'provide', 'replace', 'suggest', 'config', 'autoload', 'autoload-dev') as $linkType) {
10798 if (isset($config[$linkType]) && $config[$linkType] === array()) {
10799 $config[$linkType] = new \stdClass;
10800 }
10801 }
10802 $this->file->write($config);
10803 }
10804
10805 if ($newFile) {
10806 Silencer::call('chmod', $this->file->getPath(), 0600);
10807 }
10808 }
10809
10810
10811
10812
10813
10814
10815
10816
10817 private function arrayUnshiftRef(&$array, &$value)
10818 {
10819 $return = array_unshift($array, '');
10820 $array[0] = &$value;
10821
10822 return $return;
10823 }
10824 }
10825 <?php
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837 namespace Composer\Console;
10838
10839 use Composer\IO\NullIO;
10840 use Composer\Util\Platform;
10841 use Composer\Util\Silencer;
10842 use Symfony\Component\Console\Application as BaseApplication;
10843 use Symfony\Component\Console\Exception\CommandNotFoundException;
10844 use Symfony\Component\Console\Helper\HelperSet;
10845 use Symfony\Component\Console\Helper\QuestionHelper;
10846 use Symfony\Component\Console\Input\InputInterface;
10847 use Symfony\Component\Console\Input\InputOption;
10848 use Symfony\Component\Console\Output\OutputInterface;
10849 use Composer\Command;
10850 use Composer\Composer;
10851 use Composer\Factory;
10852 use Composer\IO\IOInterface;
10853 use Composer\IO\ConsoleIO;
10854 use Composer\Json\JsonValidationException;
10855 use Composer\Util\ErrorHandler;
10856 use Composer\EventDispatcher\ScriptExecutionException;
10857 use Composer\Exception\NoSslException;
10858
10859
10860
10861
10862
10863
10864
10865
10866 class Application extends BaseApplication
10867 {
10868
10869
10870
10871 protected $composer;
10872
10873
10874
10875
10876 protected $io;
10877
10878 private static $logo = '   ______
10879   / ____/___  ____ ___  ____  ____  ________  _____
10880  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
10881 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
10882 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
10883                     /_/
10884 ';
10885
10886 private $hasPluginCommands = false;
10887 private $disablePluginsByDefault = false;
10888
10889
10890
10891
10892 private $initialWorkingDirectory = '';
10893
10894 public function __construct()
10895 {
10896 static $shutdownRegistered = false;
10897
10898 if (function_exists('ini_set') && extension_loaded('xdebug')) {
10899 ini_set('xdebug.show_exception_trace', false);
10900 ini_set('xdebug.scream', false);
10901 }
10902
10903 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
10904 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
10905 }
10906
10907 if (!$shutdownRegistered) {
10908 $shutdownRegistered = true;
10909
10910 register_shutdown_function(function () {
10911 $lastError = error_get_last();
10912
10913 if ($lastError && $lastError['message'] &&
10914 (strpos($lastError['message'], 'Allowed memory') !== false  ||
10915 strpos($lastError['message'], 'exceeded memory') !== false )) {
10916 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
10917 }
10918 });
10919 }
10920
10921 $this->io = new NullIO();
10922
10923 $this->initialWorkingDirectory = getcwd();
10924
10925 parent::__construct('Composer', Composer::getVersion());
10926 }
10927
10928
10929
10930
10931 public function run(InputInterface $input = null, OutputInterface $output = null)
10932 {
10933 if (null === $output) {
10934 $output = Factory::createOutput();
10935 }
10936
10937 return parent::run($input, $output);
10938 }
10939
10940
10941
10942
10943 public function doRun(InputInterface $input, OutputInterface $output)
10944 {
10945 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
10946
10947 if (getenv('COMPOSER_NO_INTERACTION')) {
10948 $input->setInteractive(false);
10949 }
10950
10951 $io = $this->io = new ConsoleIO($input, $output, new HelperSet(array(
10952 new QuestionHelper(),
10953 )));
10954 ErrorHandler::register($io);
10955
10956 if ($input->hasParameterOption('--no-cache')) {
10957 $io->writeError('Disabling cache usage', true, IOInterface::DEBUG);
10958 $_SERVER['COMPOSER_CACHE_DIR'] = Platform::isWindows() ? 'nul' : '/dev/null';
10959 putenv('COMPOSER_CACHE_DIR='.$_SERVER['COMPOSER_CACHE_DIR']);
10960 }
10961
10962
10963  if ($newWorkDir = $this->getNewWorkingDir($input)) {
10964 $oldWorkingDir = getcwd();
10965 chdir($newWorkDir);
10966 $this->initialWorkingDirectory = $newWorkDir;
10967 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
10968 }
10969
10970
10971  $commandName = '';
10972 if ($name = $this->getCommandName($input)) {
10973 try {
10974 $commandName = $this->find($name)->getName();
10975 } catch (CommandNotFoundException $e) {
10976
10977  $commandName = false;
10978 } catch (\InvalidArgumentException $e) {
10979 }
10980 }
10981
10982
10983  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
10984 $dir = dirname(getcwd());
10985 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
10986
10987
10988  while (dirname($dir) !== $dir && $dir !== $home) {
10989 if (file_exists($dir.'/'.Factory::getComposerFile())) {
10990 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)) {
10991 $oldWorkingDir = getcwd();
10992 chdir($dir);
10993 }
10994 break;
10995 }
10996 $dir = dirname($dir);
10997 }
10998 }
10999
11000 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
11001 try {
11002 foreach ($this->getPluginCommands() as $command) {
11003 if ($this->has($command->getName())) {
11004 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
11005 } else {
11006 $this->add($command);
11007 }
11008 }
11009 } catch (NoSslException $e) {
11010
11011  }
11012
11013 $this->hasPluginCommands = true;
11014 }
11015
11016
11017  $isProxyCommand = false;
11018 if ($name = $this->getCommandName($input)) {
11019 try {
11020 $command = $this->find($name);
11021 $commandName = $command->getName();
11022 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
11023 } catch (\InvalidArgumentException $e) {
11024 }
11025 }
11026
11027 if (!$isProxyCommand) {
11028 $io->writeError(sprintf(
11029 'Running %s (%s) with %s on %s',
11030 Composer::getVersion(),
11031 Composer::RELEASE_DATE,
11032 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
11033 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
11034 ), true, IOInterface::DEBUG);
11035
11036 if (PHP_VERSION_ID < 50302) {
11037 $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>');
11038 }
11039
11040 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
11041 $io->writeError('<warning>You are running composer with Xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
11042 }
11043
11044 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
11045 $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']));
11046 }
11047
11048 if (
11049 !Platform::isWindows()
11050 && function_exists('exec')
11051 && !getenv('COMPOSER_ALLOW_SUPERUSER')
11052 && (ini_get('open_basedir') || !file_exists('/.dockerenv'))
11053 ) {
11054 if (function_exists('posix_getuid') && posix_getuid() === 0) {
11055 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
11056 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
11057 }
11058 if ($uid = (int) getenv('SUDO_UID')) {
11059
11060  
11061  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
11062 }
11063 }
11064
11065  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
11066 }
11067
11068
11069  Silencer::call(function () use ($io) {
11070 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
11071 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
11072 $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()));
11073 }
11074 });
11075
11076
11077  $file = Factory::getComposerFile();
11078 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
11079 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
11080 foreach ($composer['scripts'] as $script => $dummy) {
11081 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
11082 if ($this->has($script)) {
11083 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
11084 } else {
11085 $description = null;
11086
11087 if (isset($composer['scripts-descriptions'][$script])) {
11088 $description = $composer['scripts-descriptions'][$script];
11089 }
11090
11091 $this->add(new Command\ScriptAliasCommand($script, $description));
11092 }
11093 }
11094 }
11095 }
11096 }
11097 }
11098
11099 try {
11100 if ($input->hasParameterOption('--profile')) {
11101 $startTime = microtime(true);
11102 $this->io->enableDebugging($startTime);
11103 }
11104
11105 $result = parent::doRun($input, $output);
11106
11107 if (isset($oldWorkingDir)) {
11108 chdir($oldWorkingDir);
11109 }
11110
11111 if (isset($startTime)) {
11112 $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');
11113 }
11114
11115 restore_error_handler();
11116
11117 return $result;
11118 } catch (ScriptExecutionException $e) {
11119 return $e->getCode();
11120 } catch (\Exception $e) {
11121 $this->hintCommonErrors($e);
11122 restore_error_handler();
11123 throw $e;
11124 }
11125 }
11126
11127
11128
11129
11130
11131
11132 private function getNewWorkingDir(InputInterface $input)
11133 {
11134 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
11135 if (false !== $workingDir && !is_dir($workingDir)) {
11136 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
11137 }
11138
11139 return $workingDir;
11140 }
11141
11142
11143
11144
11145 private function hintCommonErrors($exception)
11146 {
11147 $io = $this->getIO();
11148
11149 Silencer::suppress();
11150 try {
11151 $composer = $this->getComposer(false, true);
11152 if ($composer) {
11153 $config = $composer->getConfig();
11154
11155 $minSpaceFree = 1024 * 1024;
11156 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
11157 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
11158 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
11159 ) {
11160 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
11161 }
11162 }
11163 } catch (\Exception $e) {
11164 }
11165 Silencer::restore();
11166
11167 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
11168 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
11169 $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);
11170 }
11171
11172 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
11173 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
11174 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
11175 }
11176 }
11177
11178
11179
11180
11181
11182
11183
11184 public function getComposer($required = true, $disablePlugins = null)
11185 {
11186 if (null === $disablePlugins) {
11187 $disablePlugins = $this->disablePluginsByDefault;
11188 }
11189
11190 if (null === $this->composer) {
11191 try {
11192 $this->composer = Factory::create($this->io, null, $disablePlugins);
11193 } catch (\InvalidArgumentException $e) {
11194 if ($required) {
11195 $this->io->writeError($e->getMessage());
11196 exit(1);
11197 }
11198 } catch (JsonValidationException $e) {
11199 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
11200 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
11201 throw new JsonValidationException($message);
11202 }
11203 }
11204
11205 return $this->composer;
11206 }
11207
11208
11209
11210
11211 public function resetComposer()
11212 {
11213 $this->composer = null;
11214 if ($this->getIO() && method_exists($this->getIO(), 'resetAuthentications')) {
11215 $this->getIO()->resetAuthentications();
11216 }
11217 }
11218
11219
11220
11221
11222 public function getIO()
11223 {
11224 return $this->io;
11225 }
11226
11227 public function getHelp()
11228 {
11229 return self::$logo . parent::getHelp();
11230 }
11231
11232
11233
11234
11235 protected function getDefaultCommands()
11236 {
11237 $commands = array_merge(parent::getDefaultCommands(), array(
11238 new Command\AboutCommand(),
11239 new Command\ConfigCommand(),
11240 new Command\DependsCommand(),
11241 new Command\ProhibitsCommand(),
11242 new Command\InitCommand(),
11243 new Command\InstallCommand(),
11244 new Command\CreateProjectCommand(),
11245 new Command\UpdateCommand(),
11246 new Command\SearchCommand(),
11247 new Command\ValidateCommand(),
11248 new Command\ShowCommand(),
11249 new Command\SuggestsCommand(),
11250 new Command\RequireCommand(),
11251 new Command\DumpAutoloadCommand(),
11252 new Command\StatusCommand(),
11253 new Command\ArchiveCommand(),
11254 new Command\DiagnoseCommand(),
11255 new Command\RunScriptCommand(),
11256 new Command\LicensesCommand(),
11257 new Command\GlobalCommand(),
11258 new Command\ClearCacheCommand(),
11259 new Command\RemoveCommand(),
11260 new Command\HomeCommand(),
11261 new Command\ExecCommand(),
11262 new Command\OutdatedCommand(),
11263 new Command\CheckPlatformReqsCommand(),
11264 new Command\FundCommand(),
11265 ));
11266
11267 if ('phar:' === substr(__FILE__, 0, 5)) {
11268 $commands[] = new Command\SelfUpdateCommand();
11269 }
11270
11271 return $commands;
11272 }
11273
11274
11275
11276
11277 public function getLongVersion()
11278 {
11279 if (Composer::BRANCH_ALIAS_VERSION && Composer::BRANCH_ALIAS_VERSION !== '@package_branch_alias_version'.'@') {
11280 return sprintf(
11281 '<info>%s</info> version <comment>%s (%s)</comment> %s',
11282 $this->getName(),
11283 Composer::BRANCH_ALIAS_VERSION,
11284 $this->getVersion(),
11285 Composer::RELEASE_DATE
11286 );
11287 }
11288
11289 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
11290 }
11291
11292
11293
11294
11295 protected function getDefaultInputDefinition()
11296 {
11297 $definition = parent::getDefaultInputDefinition();
11298 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
11299 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
11300 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
11301 $definition->addOption(new InputOption('--no-cache', null, InputOption::VALUE_NONE, 'Prevent use of the cache'));
11302
11303 return $definition;
11304 }
11305
11306 private function getPluginCommands()
11307 {
11308 $commands = array();
11309
11310 $composer = $this->getComposer(false, false);
11311 if (null === $composer) {
11312 $composer = Factory::createGlobal($this->io, false);
11313 }
11314
11315 if (null !== $composer) {
11316 $pm = $composer->getPluginManager();
11317 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
11318 $newCommands = $capability->getCommands();
11319 if (!is_array($newCommands)) {
11320 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
11321 }
11322 foreach ($newCommands as $command) {
11323 if (!$command instanceof Command\BaseCommand) {
11324 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
11325 }
11326 }
11327 $commands = array_merge($commands, $newCommands);
11328 }
11329 }
11330
11331 return $commands;
11332 }
11333
11334
11335
11336
11337
11338
11339 public function getInitialWorkingDirectory()
11340 {
11341 return $this->initialWorkingDirectory;
11342 }
11343 }
11344 <?php
11345
11346
11347
11348
11349
11350
11351
11352
11353
11354
11355
11356 namespace Composer\Console;
11357
11358 use Symfony\Component\Console\Formatter\OutputFormatter;
11359
11360
11361
11362
11363 class HtmlOutputFormatter extends OutputFormatter
11364 {
11365 private static $availableForegroundColors = array(
11366 30 => 'black',
11367 31 => 'red',
11368 32 => 'green',
11369 33 => 'yellow',
11370 34 => 'blue',
11371 35 => 'magenta',
11372 36 => 'cyan',
11373 37 => 'white',
11374 );
11375 private static $availableBackgroundColors = array(
11376 40 => 'black',
11377 41 => 'red',
11378 42 => 'green',
11379 43 => 'yellow',
11380 44 => 'blue',
11381 45 => 'magenta',
11382 46 => 'cyan',
11383 47 => 'white',
11384 );
11385 private static $availableOptions = array(
11386 1 => 'bold',
11387 4 => 'underscore',
11388
11389  
11390  
11391  );
11392
11393
11394
11395
11396 public function __construct(array $styles = array())
11397 {
11398 parent::__construct(true, $styles);
11399 }
11400
11401 public function format($message)
11402 {
11403 $formatted = parent::format($message);
11404
11405 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
11406
11407 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
11408 }
11409
11410 private function formatHtml($matches)
11411 {
11412 $out = '<span style="';
11413 foreach (explode(';', $matches[1]) as $code) {
11414 if (isset(self::$availableForegroundColors[$code])) {
11415 $out .= 'color:'.self::$availableForegroundColors[$code].';';
11416 } elseif (isset(self::$availableBackgroundColors[$code])) {
11417 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
11418 } elseif (isset(self::$availableOptions[$code])) {
11419 switch (self::$availableOptions[$code]) {
11420 case 'bold':
11421 $out .= 'font-weight:bold;';
11422 break;
11423
11424 case 'underscore':
11425 $out .= 'text-decoration:underline;';
11426 break;
11427 }
11428 }
11429 }
11430
11431 return $out.'">'.$matches[2].'</span>';
11432 }
11433 }
11434 <?php
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
11446 namespace Composer\DependencyResolver;
11447
11448
11449
11450
11451
11452
11453 class Decisions implements \Iterator, \Countable
11454 {
11455 const DECISION_LITERAL = 0;
11456 const DECISION_REASON = 1;
11457
11458 protected $pool;
11459 protected $decisionMap;
11460 protected $decisionQueue = array();
11461
11462 public function __construct($pool)
11463 {
11464 $this->pool = $pool;
11465 $this->decisionMap = array();
11466 }
11467
11468 public function decide($literal, $level, $why)
11469 {
11470 $this->addDecision($literal, $level);
11471 $this->decisionQueue[] = array(
11472 self::DECISION_LITERAL => $literal,
11473 self::DECISION_REASON => $why,
11474 );
11475 }
11476
11477 public function satisfy($literal)
11478 {
11479 $packageId = abs($literal);
11480
11481 return (
11482 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
11483 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
11484 );
11485 }
11486
11487 public function conflict($literal)
11488 {
11489 $packageId = abs($literal);
11490
11491 return (
11492 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
11493 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
11494 );
11495 }
11496
11497 public function decided($literalOrPackageId)
11498 {
11499 return !empty($this->decisionMap[abs($literalOrPackageId)]);
11500 }
11501
11502 public function undecided($literalOrPackageId)
11503 {
11504 return empty($this->decisionMap[abs($literalOrPackageId)]);
11505 }
11506
11507 public function decidedInstall($literalOrPackageId)
11508 {
11509 $packageId = abs($literalOrPackageId);
11510
11511 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
11512 }
11513
11514 public function decisionLevel($literalOrPackageId)
11515 {
11516 $packageId = abs($literalOrPackageId);
11517 if (isset($this->decisionMap[$packageId])) {
11518 return abs($this->decisionMap[$packageId]);
11519 }
11520
11521 return 0;
11522 }
11523
11524 public function decisionRule($literalOrPackageId)
11525 {
11526 $packageId = abs($literalOrPackageId);
11527
11528 foreach ($this->decisionQueue as $i => $decision) {
11529 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
11530 return $decision[self::DECISION_REASON];
11531 }
11532 }
11533
11534 return null;
11535 }
11536
11537 public function atOffset($queueOffset)
11538 {
11539 return $this->decisionQueue[$queueOffset];
11540 }
11541
11542 public function validOffset($queueOffset)
11543 {
11544 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
11545 }
11546
11547 public function lastReason()
11548 {
11549 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
11550 }
11551
11552 public function lastLiteral()
11553 {
11554 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
11555 }
11556
11557 public function reset()
11558 {
11559 while ($decision = array_pop($this->decisionQueue)) {
11560 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
11561 }
11562 }
11563
11564 public function resetToOffset($offset)
11565 {
11566 while (count($this->decisionQueue) > $offset + 1) {
11567 $decision = array_pop($this->decisionQueue);
11568 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
11569 }
11570 }
11571
11572 public function revertLast()
11573 {
11574 $this->decisionMap[abs($this->lastLiteral())] = 0;
11575 array_pop($this->decisionQueue);
11576 }
11577
11578 public function count()
11579 {
11580 return count($this->decisionQueue);
11581 }
11582
11583 public function rewind()
11584 {
11585 end($this->decisionQueue);
11586 }
11587
11588 public function current()
11589 {
11590 return current($this->decisionQueue);
11591 }
11592
11593 public function key()
11594 {
11595 return key($this->decisionQueue);
11596 }
11597
11598 public function next()
11599 {
11600 return prev($this->decisionQueue);
11601 }
11602
11603 public function valid()
11604 {
11605 return false !== current($this->decisionQueue);
11606 }
11607
11608 public function isEmpty()
11609 {
11610 return count($this->decisionQueue) === 0;
11611 }
11612
11613 protected function addDecision($literal, $level)
11614 {
11615 $packageId = abs($literal);
11616
11617 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
11618 if ($previousDecision != 0) {
11619 $literalString = $this->pool->literalToPrettyString($literal, array());
11620 $package = $this->pool->literalToPackage($literal);
11621 throw new SolverBugException(
11622 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
11623 );
11624 }
11625
11626 if ($literal > 0) {
11627 $this->decisionMap[$packageId] = $level;
11628 } else {
11629 $this->decisionMap[$packageId] = -$level;
11630 }
11631 }
11632
11633 public function __toString()
11634 {
11635 $decisionMap = $this->decisionMap;
11636 ksort($decisionMap);
11637 $str = '[';
11638 foreach ($decisionMap as $packageId => $level) {
11639 $str .= $packageId.':'.$level.',';
11640 }
11641 $str .= ']';
11642 return $str;
11643 }
11644 }
11645 <?php
11646
11647
11648
11649
11650
11651
11652
11653
11654
11655
11656
11657 namespace Composer\DependencyResolver;
11658
11659 use Composer\Package\PackageInterface;
11660 use Composer\Package\AliasPackage;
11661 use Composer\Package\BasePackage;
11662 use Composer\Semver\Constraint\Constraint;
11663
11664
11665
11666
11667
11668 class DefaultPolicy implements PolicyInterface
11669 {
11670 private $preferStable;
11671 private $preferLowest;
11672
11673 public function __construct($preferStable = false, $preferLowest = false)
11674 {
11675 $this->preferStable = $preferStable;
11676 $this->preferLowest = $preferLowest;
11677 }
11678
11679 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
11680 {
11681 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
11682 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
11683 }
11684
11685 $constraint = new Constraint($operator, $b->getVersion());
11686 $version = new Constraint('==', $a->getVersion());
11687
11688 return $constraint->matchSpecific($version, true);
11689 }
11690
11691 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
11692 {
11693 $packages = array();
11694
11695 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
11696 if ($candidate !== $package) {
11697 $packages[] = $candidate;
11698 }
11699 }
11700
11701 return $packages;
11702 }
11703
11704 public function getPriority(Pool $pool, PackageInterface $package)
11705 {
11706 return $pool->getPriority($package->getRepository());
11707 }
11708
11709 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
11710 {
11711 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
11712
11713 foreach ($packages as &$literals) {
11714 $policy = $this;
11715 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11716 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
11717 });
11718 }
11719
11720 foreach ($packages as &$literals) {
11721 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
11722
11723 $literals = $this->pruneToBestVersion($pool, $literals);
11724
11725 $literals = $this->pruneRemoteAliases($pool, $literals);
11726 }
11727
11728 $selected = call_user_func_array('array_merge', $packages);
11729
11730
11731  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
11732 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
11733 });
11734
11735 return $selected;
11736 }
11737
11738 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
11739 {
11740 $packages = array();
11741 foreach ($literals as $literal) {
11742 $packageName = $pool->literalToPackage($literal)->getName();
11743
11744 if (!isset($packages[$packageName])) {
11745 $packages[$packageName] = array();
11746 }
11747
11748 if (isset($installedMap[abs($literal)])) {
11749 array_unshift($packages[$packageName], $literal);
11750 } else {
11751 $packages[$packageName][] = $literal;
11752 }
11753 }
11754
11755 return $packages;
11756 }
11757
11758
11759
11760
11761 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
11762 {
11763 if ($a->getRepository() === $b->getRepository()) {
11764
11765  if ($a->getName() === $b->getName()) {
11766 $aAliased = $a instanceof AliasPackage;
11767 $bAliased = $b instanceof AliasPackage;
11768 if ($aAliased && !$bAliased) {
11769 return -1; 
11770  }
11771 if (!$aAliased && $bAliased) {
11772 return 1; 
11773  }
11774 }
11775
11776 if (!$ignoreReplace) {
11777
11778  if ($this->replaces($a, $b)) {
11779 return 1; 
11780  }
11781 if ($this->replaces($b, $a)) {
11782 return -1; 
11783  }
11784
11785
11786  
11787  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
11788 $requiredVendor = substr($requiredPackage, 0, $pos);
11789
11790 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
11791 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
11792
11793 if ($bIsSameVendor !== $aIsSameVendor) {
11794 return $aIsSameVendor ? -1 : 1;
11795 }
11796 }
11797 }
11798
11799
11800  if ($a->id === $b->id) {
11801 return 0;
11802 }
11803
11804 return ($a->id < $b->id) ? -1 : 1;
11805 }
11806
11807 if (isset($installedMap[$a->id])) {
11808 return -1;
11809 }
11810
11811 if (isset($installedMap[$b->id])) {
11812 return 1;
11813 }
11814
11815 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
11816 }
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826
11827
11828 protected function replaces(PackageInterface $source, PackageInterface $target)
11829 {
11830 foreach ($source->getReplaces() as $link) {
11831 if ($link->getTarget() === $target->getName()
11832
11833
11834  ) {
11835 return true;
11836 }
11837 }
11838
11839 return false;
11840 }
11841
11842 protected function pruneToBestVersion(Pool $pool, $literals)
11843 {
11844 $operator = $this->preferLowest ? '<' : '>';
11845 $bestLiterals = array($literals[0]);
11846 $bestPackage = $pool->literalToPackage($literals[0]);
11847 foreach ($literals as $i => $literal) {
11848 if (0 === $i) {
11849 continue;
11850 }
11851
11852 $package = $pool->literalToPackage($literal);
11853
11854 if ($this->versionCompare($package, $bestPackage, $operator)) {
11855 $bestPackage = $package;
11856 $bestLiterals = array($literal);
11857 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
11858 $bestLiterals[] = $literal;
11859 }
11860 }
11861
11862 return $bestLiterals;
11863 }
11864
11865
11866
11867
11868 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
11869 {
11870 $selected = array();
11871
11872 $priority = null;
11873
11874 foreach ($literals as $literal) {
11875 $package = $pool->literalToPackage($literal);
11876
11877 if (isset($installedMap[$package->id])) {
11878 $selected[] = $literal;
11879 continue;
11880 }
11881
11882 if (null === $priority) {
11883 $priority = $this->getPriority($pool, $package);
11884 }
11885
11886 if ($this->getPriority($pool, $package) != $priority) {
11887 break;
11888 }
11889
11890 $selected[] = $literal;
11891 }
11892
11893 return $selected;
11894 }
11895
11896
11897
11898
11899
11900
11901 protected function pruneRemoteAliases(Pool $pool, array $literals)
11902 {
11903 $hasLocalAlias = false;
11904
11905 foreach ($literals as $literal) {
11906 $package = $pool->literalToPackage($literal);
11907
11908 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
11909 $hasLocalAlias = true;
11910 break;
11911 }
11912 }
11913
11914 if (!$hasLocalAlias) {
11915 return $literals;
11916 }
11917
11918 $selected = array();
11919 foreach ($literals as $literal) {
11920 $package = $pool->literalToPackage($literal);
11921
11922 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
11923 $selected[] = $literal;
11924 }
11925 }
11926
11927 return $selected;
11928 }
11929 }
11930 <?php
11931
11932
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942 namespace Composer\DependencyResolver;
11943
11944 use Composer\Package\PackageInterface;
11945 use Composer\Package\Link;
11946
11947
11948
11949
11950 class GenericRule extends Rule
11951 {
11952 protected $literals;
11953
11954
11955
11956
11957
11958
11959
11960 public function __construct(array $literals, $reason, $reasonData, $job = null)
11961 {
11962 parent::__construct($reason, $reasonData, $job);
11963
11964
11965  sort($literals);
11966
11967 $this->literals = $literals;
11968 }
11969
11970 public function getLiterals()
11971 {
11972 return $this->literals;
11973 }
11974
11975 public function getHash()
11976 {
11977 $data = unpack('ihash', md5(implode(',', $this->literals), true));
11978
11979 return $data['hash'];
11980 }
11981
11982
11983
11984
11985
11986
11987
11988
11989
11990 public function equals(Rule $rule)
11991 {
11992 return $this->literals === $rule->getLiterals();
11993 }
11994
11995 public function isAssertion()
11996 {
11997 return 1 === count($this->literals);
11998 }
11999
12000
12001
12002
12003
12004
12005 public function __toString()
12006 {
12007 $result = $this->isDisabled() ? 'disabled(' : '(';
12008
12009 foreach ($this->literals as $i => $literal) {
12010 if ($i != 0) {
12011 $result .= '|';
12012 }
12013 $result .= $literal;
12014 }
12015
12016 $result .= ')';
12017
12018 return $result;
12019 }
12020 }
12021 <?php
12022
12023
12024
12025
12026
12027
12028
12029
12030
12031
12032
12033 namespace Composer\DependencyResolver\Operation;
12034
12035 use Composer\Package\PackageInterface;
12036
12037
12038
12039
12040
12041
12042 class InstallOperation extends SolverOperation
12043 {
12044 protected $package;
12045
12046
12047
12048
12049
12050
12051
12052 public function __construct(PackageInterface $package, $reason = null)
12053 {
12054 parent::__construct($reason);
12055
12056 $this->package = $package;
12057 }
12058
12059
12060
12061
12062
12063
12064 public function getPackage()
12065 {
12066 return $this->package;
12067 }
12068
12069
12070
12071
12072
12073
12074 public function getJobType()
12075 {
12076 return 'install';
12077 }
12078
12079
12080
12081
12082 public function __toString()
12083 {
12084 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
12085 }
12086 }
12087 <?php
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099 namespace Composer\DependencyResolver\Operation;
12100
12101 use Composer\Package\AliasPackage;
12102 use Composer\Package\PackageInterface;
12103
12104
12105
12106
12107
12108
12109 class MarkAliasInstalledOperation extends SolverOperation
12110 {
12111 protected $package;
12112
12113
12114
12115
12116
12117
12118
12119 public function __construct(AliasPackage $package, $reason = null)
12120 {
12121 parent::__construct($reason);
12122
12123 $this->package = $package;
12124 }
12125
12126
12127
12128
12129
12130
12131 public function getPackage()
12132 {
12133 return $this->package;
12134 }
12135
12136
12137
12138
12139
12140
12141 public function getJobType()
12142 {
12143 return 'markAliasInstalled';
12144 }
12145
12146
12147
12148
12149 public function __toString()
12150 {
12151 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
12152 }
12153 }
12154 <?php
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166 namespace Composer\DependencyResolver\Operation;
12167
12168 use Composer\Package\AliasPackage;
12169 use Composer\Package\PackageInterface;
12170
12171
12172
12173
12174
12175
12176 class MarkAliasUninstalledOperation extends SolverOperation
12177 {
12178 protected $package;
12179
12180
12181
12182
12183
12184
12185
12186 public function __construct(AliasPackage $package, $reason = null)
12187 {
12188 parent::__construct($reason);
12189
12190 $this->package = $package;
12191 }
12192
12193
12194
12195
12196
12197
12198 public function getPackage()
12199 {
12200 return $this->package;
12201 }
12202
12203
12204
12205
12206
12207
12208 public function getJobType()
12209 {
12210 return 'markAliasUninstalled';
12211 }
12212
12213
12214
12215
12216 public function __toString()
12217 {
12218 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
12219 }
12220 }
12221 <?php
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233 namespace Composer\DependencyResolver\Operation;
12234
12235
12236
12237
12238
12239
12240 interface OperationInterface
12241 {
12242
12243
12244
12245
12246
12247 public function getJobType();
12248
12249
12250
12251
12252
12253
12254 public function getReason();
12255
12256
12257
12258
12259
12260
12261 public function __toString();
12262 }
12263 <?php
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275 namespace Composer\DependencyResolver\Operation;
12276
12277 use Composer\Package\PackageInterface;
12278
12279
12280
12281
12282
12283
12284 abstract class SolverOperation implements OperationInterface
12285 {
12286 protected $reason;
12287
12288
12289
12290
12291
12292
12293 public function __construct($reason = null)
12294 {
12295 $this->reason = $reason;
12296 }
12297
12298
12299
12300
12301
12302
12303 public function getReason()
12304 {
12305 return $this->reason;
12306 }
12307
12308 protected function formatVersion(PackageInterface $package)
12309 {
12310 return $package->getFullPrettyVersion();
12311 }
12312 }
12313 <?php
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325 namespace Composer\DependencyResolver\Operation;
12326
12327 use Composer\Package\PackageInterface;
12328
12329
12330
12331
12332
12333
12334 class UninstallOperation extends SolverOperation
12335 {
12336 protected $package;
12337
12338
12339
12340
12341
12342
12343
12344 public function __construct(PackageInterface $package, $reason = null)
12345 {
12346 parent::__construct($reason);
12347
12348 $this->package = $package;
12349 }
12350
12351
12352
12353
12354
12355
12356 public function getPackage()
12357 {
12358 return $this->package;
12359 }
12360
12361
12362
12363
12364
12365
12366 public function getJobType()
12367 {
12368 return 'uninstall';
12369 }
12370
12371
12372
12373
12374 public function __toString()
12375 {
12376 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
12377 }
12378 }
12379 <?php
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391 namespace Composer\DependencyResolver\Operation;
12392
12393 use Composer\Package\PackageInterface;
12394 use Composer\Package\Version\VersionParser;
12395
12396
12397
12398
12399
12400
12401 class UpdateOperation extends SolverOperation
12402 {
12403 protected $initialPackage;
12404 protected $targetPackage;
12405
12406
12407
12408
12409
12410
12411
12412
12413 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
12414 {
12415 parent::__construct($reason);
12416
12417 $this->initialPackage = $initial;
12418 $this->targetPackage = $target;
12419 }
12420
12421
12422
12423
12424
12425
12426 public function getInitialPackage()
12427 {
12428 return $this->initialPackage;
12429 }
12430
12431
12432
12433
12434
12435
12436 public function getTargetPackage()
12437 {
12438 return $this->targetPackage;
12439 }
12440
12441
12442
12443
12444
12445
12446 public function getJobType()
12447 {
12448 return 'update';
12449 }
12450
12451
12452
12453
12454 public function __toString()
12455 {
12456 $actionName = VersionParser::isUpgrade($this->initialPackage->getVersion(), $this->targetPackage->getVersion()) ? 'Updating' : 'Downgrading';
12457
12458 return $actionName.' '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
12459 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
12460 }
12461 }
12462 <?php
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474 namespace Composer\DependencyResolver;
12475
12476 use Composer\Package\PackageInterface;
12477
12478
12479
12480
12481 interface PolicyInterface
12482 {
12483 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
12484
12485 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
12486
12487 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
12488 }
12489 <?php
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501 namespace Composer\DependencyResolver;
12502
12503 use Composer\Package\BasePackage;
12504 use Composer\Package\AliasPackage;
12505 use Composer\Package\Version\VersionParser;
12506 use Composer\Semver\Constraint\ConstraintInterface;
12507 use Composer\Semver\Constraint\Constraint;
12508 use Composer\Semver\Constraint\EmptyConstraint;
12509 use Composer\Repository\RepositoryInterface;
12510 use Composer\Repository\CompositeRepository;
12511 use Composer\Repository\ComposerRepository;
12512 use Composer\Repository\InstalledRepositoryInterface;
12513 use Composer\Repository\PlatformRepository;
12514 use Composer\Package\PackageInterface;
12515
12516
12517
12518
12519
12520
12521
12522 class Pool implements \Countable
12523 {
12524 const MATCH_NAME = -1;
12525 const MATCH_NONE = 0;
12526 const MATCH = 1;
12527 const MATCH_PROVIDE = 2;
12528 const MATCH_REPLACE = 3;
12529 const MATCH_FILTERED = 4;
12530
12531 protected $repositories = array();
12532 protected $providerRepos = array();
12533 protected $packages = array();
12534 protected $packageByName = array();
12535 protected $packageByExactName = array();
12536 protected $acceptableStabilities;
12537 protected $stabilityFlags;
12538 protected $versionParser;
12539 protected $providerCache = array();
12540 protected $filterRequires;
12541 protected $whitelist = null;
12542 protected $id = 1;
12543
12544 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
12545 {
12546 $this->versionParser = new VersionParser;
12547 $this->acceptableStabilities = array();
12548 foreach (BasePackage::$stabilities as $stability => $value) {
12549 if ($value <= BasePackage::$stabilities[$minimumStability]) {
12550 $this->acceptableStabilities[$stability] = $value;
12551 }
12552 }
12553 $this->stabilityFlags = $stabilityFlags;
12554 $this->filterRequires = $filterRequires;
12555 foreach ($filterRequires as $name => $constraint) {
12556 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
12557 unset($this->filterRequires[$name]);
12558 }
12559 }
12560 }
12561
12562 public function setWhitelist($whitelist)
12563 {
12564 $this->whitelist = $whitelist;
12565 $this->providerCache = array();
12566 }
12567
12568
12569
12570
12571
12572
12573
12574 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
12575 {
12576 if ($repo instanceof CompositeRepository) {
12577 $repos = $repo->getRepositories();
12578 } else {
12579 $repos = array($repo);
12580 }
12581
12582 foreach ($repos as $repo) {
12583 $this->repositories[] = $repo;
12584
12585 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
12586
12587 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
12588 $this->providerRepos[] = $repo;
12589 $repo->setRootAliases($rootAliases);
12590 $repo->resetPackageIds();
12591 } else {
12592 foreach ($repo->getPackages() as $package) {
12593 $names = $package->getNames();
12594 $stability = $package->getStability();
12595 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
12596 $package->setId($this->id++);
12597 $this->packages[] = $package;
12598 $this->packageByExactName[$package->getName()][$package->id] = $package;
12599
12600 foreach ($names as $provided) {
12601 $this->packageByName[$provided][] = $package;
12602 }
12603
12604
12605  $name = $package->getName();
12606 if (isset($rootAliases[$name][$package->getVersion()])) {
12607 $alias = $rootAliases[$name][$package->getVersion()];
12608 if ($package instanceof AliasPackage) {
12609 $package = $package->getAliasOf();
12610 }
12611 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
12612 $aliasPackage->setRootPackageAlias(true);
12613 $aliasPackage->setId($this->id++);
12614
12615 $package->getRepository()->addPackage($aliasPackage);
12616 $this->packages[] = $aliasPackage;
12617 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
12618
12619 foreach ($aliasPackage->getNames() as $name) {
12620 $this->packageByName[$name][] = $aliasPackage;
12621 }
12622 }
12623 }
12624 }
12625 }
12626 }
12627 }
12628
12629 public function getPriority(RepositoryInterface $repo)
12630 {
12631 $priority = array_search($repo, $this->repositories, true);
12632
12633 if (false === $priority) {
12634 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
12635 }
12636
12637 return -$priority;
12638 }
12639
12640
12641
12642
12643
12644
12645
12646 public function packageById($id)
12647 {
12648 return $this->packages[$id - 1];
12649 }
12650
12651
12652
12653
12654 public function count()
12655 {
12656 return count($this->packages);
12657 }
12658
12659
12660
12661
12662
12663
12664
12665
12666
12667
12668
12669
12670 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
12671 {
12672 if ($bypassFilters) {
12673 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
12674 }
12675
12676 $key = ((int) $mustMatchName).$constraint;
12677 if (isset($this->providerCache[$name][$key])) {
12678 return $this->providerCache[$name][$key];
12679 }
12680
12681 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
12682 }
12683
12684
12685
12686
12687 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
12688 {
12689 $candidates = array();
12690
12691 foreach ($this->providerRepos as $repo) {
12692 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
12693 $candidates[] = $candidate;
12694 if ($candidate->id < 1) {
12695 $candidate->setId($this->id++);
12696 $this->packages[$this->id - 2] = $candidate;
12697 }
12698 }
12699 }
12700
12701 if ($mustMatchName) {
12702 $candidates = array_filter($candidates, function ($candidate) use ($name) {
12703 return $candidate->getName() == $name;
12704 });
12705 if (isset($this->packageByExactName[$name])) {
12706 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
12707 }
12708 } elseif (isset($this->packageByName[$name])) {
12709 $candidates = array_merge($candidates, $this->packageByName[$name]);
12710 }
12711
12712 $matches = $provideMatches = array();
12713 $nameMatch = false;
12714
12715 foreach ($candidates as $candidate) {
12716 $aliasOfCandidate = null;
12717
12718
12719  
12720  if ($candidate instanceof AliasPackage) {
12721 $aliasOfCandidate = $candidate->getAliasOf();
12722 }
12723
12724 if ($this->whitelist !== null && !$bypassFilters && (
12725 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
12726 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
12727 )) {
12728 continue;
12729 }
12730 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
12731 case self::MATCH_NONE:
12732 break;
12733
12734 case self::MATCH_NAME:
12735 $nameMatch = true;
12736 break;
12737
12738 case self::MATCH:
12739 $nameMatch = true;
12740 $matches[] = $candidate;
12741 break;
12742
12743 case self::MATCH_PROVIDE:
12744 $provideMatches[] = $candidate;
12745 break;
12746
12747 case self::MATCH_REPLACE:
12748 $matches[] = $candidate;
12749 break;
12750
12751 case self::MATCH_FILTERED:
12752 break;
12753
12754 default:
12755 throw new \UnexpectedValueException('Unexpected match type');
12756 }
12757 }
12758
12759
12760  if ($nameMatch) {
12761 return $matches;
12762 }
12763
12764 return array_merge($matches, $provideMatches);
12765 }
12766
12767 public function literalToPackage($literal)
12768 {
12769 $packageId = abs($literal);
12770
12771 return $this->packageById($packageId);
12772 }
12773
12774 public function literalToPrettyString($literal, $installedMap)
12775 {
12776 $package = $this->literalToPackage($literal);
12777
12778 if (isset($installedMap[$package->id])) {
12779 $prefix = ($literal > 0 ? 'keep' : 'remove');
12780 } else {
12781 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
12782 }
12783
12784 return $prefix.' '.$package->getPrettyString();
12785 }
12786
12787 public function isPackageAcceptable($name, $stability)
12788 {
12789 foreach ((array) $name as $n) {
12790
12791  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
12792 return true;
12793 }
12794
12795
12796  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
12797 return true;
12798 }
12799 }
12800
12801 return false;
12802 }
12803
12804
12805
12806
12807
12808
12809
12810
12811
12812
12813 public function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
12814 {
12815 $candidateName = $candidate->getName();
12816 $candidateVersion = $candidate->getVersion();
12817 $isDev = $candidate->getStability() === 'dev';
12818 $isAlias = $candidate instanceof AliasPackage;
12819
12820 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
12821 $requireFilter = $this->filterRequires[$name];
12822 } else {
12823 $requireFilter = new EmptyConstraint;
12824 }
12825
12826 if ($candidateName === $name) {
12827 $pkgConstraint = new Constraint('==', $candidateVersion);
12828
12829 if ($constraint === null || $constraint->matches($pkgConstraint)) {
12830 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
12831 }
12832
12833 return self::MATCH_NAME;
12834 }
12835
12836 $provides = $candidate->getProvides();
12837 $replaces = $candidate->getReplaces();
12838
12839
12840  if (isset($replaces[0]) || isset($provides[0])) {
12841 foreach ($provides as $link) {
12842 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
12843 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
12844 }
12845 }
12846
12847 foreach ($replaces as $link) {
12848 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
12849 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
12850 }
12851 }
12852
12853 return self::MATCH_NONE;
12854 }
12855
12856 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
12857 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
12858 }
12859
12860 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
12861 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
12862 }
12863
12864 return self::MATCH_NONE;
12865 }
12866 }
12867 <?php
12868
12869
12870
12871
12872
12873
12874
12875
12876
12877
12878
12879 namespace Composer\DependencyResolver;
12880
12881 use Composer\Package\CompletePackageInterface;
12882
12883
12884
12885
12886
12887
12888 class Problem
12889 {
12890
12891
12892
12893
12894 protected $reasonSeen;
12895
12896
12897
12898
12899
12900 protected $reasons = array();
12901
12902 protected $section = 0;
12903
12904 protected $pool;
12905
12906 public function __construct(Pool $pool)
12907 {
12908 $this->pool = $pool;
12909 }
12910
12911
12912
12913
12914
12915
12916 public function addRule(Rule $rule)
12917 {
12918 $this->addReason(spl_object_hash($rule), array(
12919 'rule' => $rule,
12920 'job' => $rule->getJob(),
12921 ));
12922 }
12923
12924
12925
12926
12927
12928
12929 public function getReasons()
12930 {
12931 return $this->reasons;
12932 }
12933
12934
12935
12936
12937
12938
12939
12940 public function getPrettyString(array $installedMap = array())
12941 {
12942 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
12943
12944 if (count($reasons) === 1) {
12945 reset($reasons);
12946 $reason = current($reasons);
12947
12948 $job = $reason['job'];
12949
12950 $packageName = $job['packageName'];
12951 $constraint = $job['constraint'];
12952
12953 if (isset($constraint)) {
12954 $packages = $this->pool->whatProvides($packageName, $constraint);
12955 } else {
12956 $packages = array();
12957 }
12958
12959 if ($job && $job['cmd'] === 'install' && empty($packages)) {
12960
12961
12962  if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') {
12963 $version = phpversion();
12964 $available = $this->pool->whatProvides($packageName);
12965
12966 if (count($available)) {
12967 $firstAvailable = reset($available);
12968 $version = $firstAvailable->getPrettyVersion();
12969 $extra = $firstAvailable->getExtra();
12970 if ($firstAvailable instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) {
12971 $version .= '; ' . $firstAvailable->getDescription();
12972 }
12973 }
12974
12975 $msg = "\n    - This package requires ".$packageName.$this->constraintToText($constraint).' but ';
12976
12977 if (defined('HHVM_VERSION') || (count($available) && $packageName === 'hhvm')) {
12978 return $msg . 'your HHVM version does not satisfy that requirement.';
12979 }
12980
12981 if ($packageName === 'hhvm') {
12982 return $msg . 'you are running this with PHP and not HHVM.';
12983 }
12984
12985 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
12986 }
12987
12988
12989  if (0 === stripos($packageName, 'ext-')) {
12990 if (false !== strpos($packageName, ' ')) {
12991 return "\n    - The requested PHP extension ".$packageName.' should be required as '.str_replace(' ', '-', $packageName).'.';
12992 }
12993
12994 $ext = substr($packageName, 4);
12995 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
12996
12997 return "\n    - The requested PHP extension ".$packageName.$this->constraintToText($constraint).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
12998 }
12999
13000
13001  if (0 === stripos($packageName, 'lib-')) {
13002 if (strtolower($packageName) === 'lib-icu') {
13003 $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.';
13004
13005 return "\n    - The requested linked library ".$packageName.$this->constraintToText($constraint).' '.$error;
13006 }
13007
13008 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.';
13009 }
13010
13011 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) {
13012 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName);
13013
13014 return "\n    - The requested package ".$packageName.' could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.';
13015 }
13016
13017 if ($providers = $this->pool->whatProvides($packageName, $constraint, true, true)) {
13018 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' is satisfiable by '.$this->getPackageList($providers).' but these conflict with your requirements or minimum-stability.';
13019 }
13020
13021 if ($providers = $this->pool->whatProvides($packageName, null, true, true)) {
13022 return "\n    - The requested package ".$packageName.$this->constraintToText($constraint).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
13023 }
13024
13025 return "\n    - The requested package ".$packageName.' could not be found in any version, there may be a typo in the package name.';
13026 }
13027 }
13028
13029 $messages = array();
13030
13031 foreach ($reasons as $reason) {
13032 $rule = $reason['rule'];
13033 $job = $reason['job'];
13034
13035 if ($job) {
13036 $messages[] = $this->jobToText($job);
13037 } elseif ($rule) {
13038 if ($rule instanceof Rule) {
13039 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
13040 }
13041 }
13042 }
13043
13044 return "\n    - ".implode("\n    - ", $messages);
13045 }
13046
13047
13048
13049
13050
13051
13052
13053 protected function addReason($id, $reason)
13054 {
13055 if (!isset($this->reasonSeen[$id])) {
13056 $this->reasonSeen[$id] = true;
13057 $this->reasons[$this->section][] = $reason;
13058 }
13059 }
13060
13061 public function nextSection()
13062 {
13063 $this->section++;
13064 }
13065
13066
13067
13068
13069
13070
13071
13072 protected function jobToText($job)
13073 {
13074 $packageName = $job['packageName'];
13075 $constraint = $job['constraint'];
13076 switch ($job['cmd']) {
13077 case 'install':
13078 $packages = $this->pool->whatProvides($packageName, $constraint);
13079 if (!$packages) {
13080 return 'No package found to satisfy install request for '.$packageName.$this->constraintToText($constraint);
13081 }
13082
13083 return 'Installation request for '.$packageName.$this->constraintToText($constraint).' -> satisfiable by '.$this->getPackageList($packages).'.';
13084 case 'update':
13085 return 'Update request for '.$packageName.$this->constraintToText($constraint).'.';
13086 case 'remove':
13087 return 'Removal request for '.$packageName.$this->constraintToText($constraint).'';
13088 }
13089
13090 if (isset($constraint)) {
13091 $packages = $this->pool->whatProvides($packageName, $constraint);
13092 } else {
13093 $packages = array();
13094 }
13095
13096 return 'Job(cmd='.$job['cmd'].', target='.$packageName.', packages=['.$this->getPackageList($packages).'])';
13097 }
13098
13099 protected function getPackageList($packages)
13100 {
13101 $prepared = array();
13102 foreach ($packages as $package) {
13103 $prepared[$package->getName()]['name'] = $package->getPrettyName();
13104 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
13105 }
13106 foreach ($prepared as $name => $package) {
13107 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
13108 }
13109
13110 return implode(', ', $prepared);
13111 }
13112
13113
13114
13115
13116
13117
13118
13119 protected function constraintToText($constraint)
13120 {
13121 return $constraint ? ' '.$constraint->getPrettyString() : '';
13122 }
13123 }
13124 <?php
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136 namespace Composer\DependencyResolver;
13137
13138 use Composer\Semver\Constraint\ConstraintInterface;
13139
13140
13141
13142
13143 class Request
13144 {
13145 protected $jobs;
13146
13147 public function __construct()
13148 {
13149 $this->jobs = array();
13150 }
13151
13152 public function install($packageName, ConstraintInterface $constraint = null)
13153 {
13154 $this->addJob($packageName, 'install', $constraint);
13155 }
13156
13157 public function update($packageName, ConstraintInterface $constraint = null)
13158 {
13159 $this->addJob($packageName, 'update', $constraint);
13160 }
13161
13162 public function remove($packageName, ConstraintInterface $constraint = null)
13163 {
13164 $this->addJob($packageName, 'remove', $constraint);
13165 }
13166
13167
13168
13169
13170
13171
13172
13173
13174
13175 public function fix($packageName, ConstraintInterface $constraint = null)
13176 {
13177 $this->addJob($packageName, 'install', $constraint, true);
13178 }
13179
13180 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
13181 {
13182 $packageName = strtolower($packageName);
13183
13184 $this->jobs[] = array(
13185 'cmd' => $cmd,
13186 'packageName' => $packageName,
13187 'constraint' => $constraint,
13188 'fixed' => $fixed,
13189 );
13190 }
13191
13192 public function updateAll()
13193 {
13194 $this->jobs[] = array('cmd' => 'update-all');
13195 }
13196
13197 public function getJobs()
13198 {
13199 return $this->jobs;
13200 }
13201 }
13202 <?php
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214 namespace Composer\DependencyResolver;
13215
13216 use Composer\Package\CompletePackage;
13217 use Composer\Package\Link;
13218 use Composer\Package\PackageInterface;
13219
13220
13221
13222
13223
13224 abstract class Rule
13225 {
13226
13227  const RULE_INTERNAL_ALLOW_UPDATE = 1;
13228 const RULE_JOB_INSTALL = 2;
13229 const RULE_JOB_REMOVE = 3;
13230 const RULE_PACKAGE_CONFLICT = 6;
13231 const RULE_PACKAGE_REQUIRES = 7;
13232 const RULE_PACKAGE_OBSOLETES = 8;
13233 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
13234 const RULE_PACKAGE_SAME_NAME = 10;
13235 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
13236 const RULE_LEARNED = 12;
13237 const RULE_PACKAGE_ALIAS = 13;
13238
13239
13240  const BITFIELD_TYPE = 0;
13241 const BITFIELD_REASON = 8;
13242 const BITFIELD_DISABLED = 16;
13243
13244 protected $bitfield;
13245 protected $job;
13246 protected $reasonData;
13247
13248
13249
13250
13251
13252
13253 public function __construct($reason, $reasonData, $job = null)
13254 {
13255 $this->reasonData = $reasonData;
13256
13257 if ($job) {
13258 $this->job = $job;
13259 }
13260
13261 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
13262 ($reason << self::BITFIELD_REASON) |
13263 (255 << self::BITFIELD_TYPE);
13264 }
13265
13266 abstract public function getLiterals();
13267
13268 abstract public function getHash();
13269
13270 public function getJob()
13271 {
13272 return $this->job;
13273 }
13274
13275 abstract public function equals(Rule $rule);
13276
13277 public function getReason()
13278 {
13279 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
13280 }
13281
13282 public function getReasonData()
13283 {
13284 return $this->reasonData;
13285 }
13286
13287 public function getRequiredPackage()
13288 {
13289 if ($this->getReason() === self::RULE_JOB_INSTALL) {
13290 return $this->reasonData;
13291 }
13292
13293 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
13294 return $this->reasonData->getTarget();
13295 }
13296 }
13297
13298 public function setType($type)
13299 {
13300 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
13301 }
13302
13303 public function getType()
13304 {
13305 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
13306 }
13307
13308 public function disable()
13309 {
13310 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
13311 }
13312
13313 public function enable()
13314 {
13315 $this->bitfield &= ~(255 << self::BITFIELD_DISABLED);
13316 }
13317
13318 public function isDisabled()
13319 {
13320 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
13321 }
13322
13323 public function isEnabled()
13324 {
13325 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
13326 }
13327
13328 abstract public function isAssertion();
13329
13330 public function getPrettyString(Pool $pool, array $installedMap = array())
13331 {
13332 $literals = $this->getLiterals();
13333
13334 $ruleText = '';
13335 foreach ($literals as $i => $literal) {
13336 if ($i != 0) {
13337 $ruleText .= '|';
13338 }
13339 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
13340 }
13341
13342 switch ($this->getReason()) {
13343 case self::RULE_INTERNAL_ALLOW_UPDATE:
13344 return $ruleText;
13345
13346 case self::RULE_JOB_INSTALL:
13347 return "Install command rule ($ruleText)";
13348
13349 case self::RULE_JOB_REMOVE:
13350 return "Remove command rule ($ruleText)";
13351
13352 case self::RULE_PACKAGE_CONFLICT:
13353 $package1 = $pool->literalToPackage($literals[0]);
13354 $package2 = $pool->literalToPackage($literals[1]);
13355
13356 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
13357
13358 case self::RULE_PACKAGE_REQUIRES:
13359 $sourceLiteral = array_shift($literals);
13360 $sourcePackage = $pool->literalToPackage($sourceLiteral);
13361
13362 $requires = array();
13363 foreach ($literals as $literal) {
13364 $requires[] = $pool->literalToPackage($literal);
13365 }
13366
13367 $text = $this->reasonData->getPrettyString($sourcePackage);
13368 if ($requires) {
13369 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
13370 } else {
13371 $targetName = $this->reasonData->getTarget();
13372
13373 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
13374
13375  if (defined('HHVM_VERSION')) {
13376 return $text . ' -> your HHVM version does not satisfy that requirement.';
13377 }
13378
13379 $packages = $pool->whatProvides($targetName);
13380 $package = count($packages) ? current($packages) : phpversion();
13381
13382 if ($targetName === 'hhvm') {
13383 if ($package instanceof CompletePackage) {
13384 return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
13385 } else {
13386 return $text . ' -> you are running this with PHP and not HHVM.';
13387 }
13388 }
13389
13390
13391 if (!($package instanceof CompletePackage)) {
13392 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
13393 }
13394
13395 $extra = $package->getExtra();
13396
13397 if (!empty($extra['config.platform'])) {
13398 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
13399 } else {
13400 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
13401 }
13402
13403 return $text;
13404 }
13405
13406 if (0 === strpos($targetName, 'ext-')) {
13407
13408  $ext = substr($targetName, 4);
13409 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
13410
13411 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
13412 }
13413
13414 if (0 === strpos($targetName, 'lib-')) {
13415
13416  $lib = substr($targetName, 4);
13417
13418 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.';
13419 }
13420
13421 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
13422 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
13423 }
13424
13425 return $text . ' -> no matching package found.';
13426 }
13427
13428 return $text;
13429
13430 case self::RULE_PACKAGE_OBSOLETES:
13431 return $ruleText;
13432 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
13433 return $ruleText;
13434 case self::RULE_PACKAGE_SAME_NAME:
13435 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
13436 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
13437 return $ruleText;
13438 case self::RULE_LEARNED:
13439 return 'Conclusion: '.$ruleText;
13440 case self::RULE_PACKAGE_ALIAS:
13441 return $ruleText;
13442 default:
13443 return '('.$ruleText.')';
13444 }
13445 }
13446
13447
13448
13449
13450
13451
13452
13453 protected function formatPackagesUnique($pool, array $packages)
13454 {
13455 $prepared = array();
13456 foreach ($packages as $package) {
13457 if (!is_object($package)) {
13458 $package = $pool->literalToPackage($package);
13459 }
13460 $prepared[$package->getName()]['name'] = $package->getPrettyName();
13461 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
13462 }
13463 foreach ($prepared as $name => $package) {
13464 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
13465 }
13466
13467 return implode(', ', $prepared);
13468 }
13469 }
13470 <?php
13471
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481
13482 namespace Composer\DependencyResolver;
13483
13484 use Composer\Package\PackageInterface;
13485 use Composer\Package\Link;
13486
13487
13488
13489
13490 class Rule2Literals extends Rule
13491 {
13492 protected $literal1;
13493 protected $literal2;
13494
13495
13496
13497
13498
13499
13500
13501
13502 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
13503 {
13504 parent::__construct($reason, $reasonData, $job);
13505
13506 if ($literal1 < $literal2) {
13507 $this->literal1 = $literal1;
13508 $this->literal2 = $literal2;
13509 } else {
13510 $this->literal1 = $literal2;
13511 $this->literal2 = $literal1;
13512 }
13513 }
13514
13515 public function getLiterals()
13516 {
13517 return array($this->literal1, $this->literal2);
13518 }
13519
13520 public function getHash()
13521 {
13522 return $this->literal1.','.$this->literal2;
13523 }
13524
13525
13526
13527
13528
13529
13530
13531
13532
13533 public function equals(Rule $rule)
13534 {
13535
13536  if ($rule instanceof self) {
13537 if ($this->literal1 !== $rule->literal1) {
13538 return false;
13539 }
13540
13541 if ($this->literal2 !== $rule->literal2) {
13542 return false;
13543 }
13544
13545 return true;
13546 }
13547
13548 $literals = $rule->getLiterals();
13549 if (2 != count($literals)) {
13550 return false;
13551 }
13552
13553 if ($this->literal1 !== $literals[0]) {
13554 return false;
13555 }
13556
13557 if ($this->literal2 !== $literals[1]) {
13558 return false;
13559 }
13560
13561 return true;
13562 }
13563
13564 public function isAssertion()
13565 {
13566 return false;
13567 }
13568
13569
13570
13571
13572
13573
13574 public function __toString()
13575 {
13576 $result = $this->isDisabled() ? 'disabled(' : '(';
13577
13578 $result .= $this->literal1 . '|' . $this->literal2 . ')';
13579
13580 return $result;
13581 }
13582 }
13583 <?php
13584
13585
13586
13587
13588
13589
13590
13591
13592
13593
13594
13595 namespace Composer\DependencyResolver;
13596
13597
13598
13599
13600 class RuleSet implements \IteratorAggregate, \Countable
13601 {
13602
13603  const TYPE_PACKAGE = 0;
13604 const TYPE_JOB = 1;
13605 const TYPE_LEARNED = 4;
13606
13607
13608
13609
13610
13611
13612 public $ruleById;
13613
13614 protected static $types = array(
13615 255 => 'UNKNOWN',
13616 self::TYPE_PACKAGE => 'PACKAGE',
13617 self::TYPE_JOB => 'JOB',
13618 self::TYPE_LEARNED => 'LEARNED',
13619 );
13620
13621 protected $rules;
13622 protected $nextRuleId;
13623
13624 protected $rulesByHash;
13625
13626 public function __construct()
13627 {
13628 $this->nextRuleId = 0;
13629
13630 foreach ($this->getTypes() as $type) {
13631 $this->rules[$type] = array();
13632 }
13633
13634 $this->rulesByHash = array();
13635 }
13636
13637 public function add(Rule $rule, $type)
13638 {
13639 if (!isset(self::$types[$type])) {
13640 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
13641 }
13642
13643 $hash = $rule->getHash();
13644
13645
13646  if (isset($this->rulesByHash[$hash])) {
13647 $potentialDuplicates = $this->rulesByHash[$hash];
13648 if (is_array($potentialDuplicates)) {
13649 foreach ($potentialDuplicates as $potentialDuplicate) {
13650 if ($rule->equals($potentialDuplicate)) {
13651 return;
13652 }
13653 }
13654 } else {
13655 if ($rule->equals($potentialDuplicates)) {
13656 return;
13657 }
13658 }
13659 }
13660
13661 if (!isset($this->rules[$type])) {
13662 $this->rules[$type] = array();
13663 }
13664
13665 $this->rules[$type][] = $rule;
13666 $this->ruleById[$this->nextRuleId] = $rule;
13667 $rule->setType($type);
13668
13669 $this->nextRuleId++;
13670
13671 if (!isset($this->rulesByHash[$hash])) {
13672 $this->rulesByHash[$hash] = $rule;
13673 } elseif (is_array($this->rulesByHash[$hash])) {
13674 $this->rulesByHash[$hash][] = $rule;
13675 } else {
13676 $originalRule = $this->rulesByHash[$hash];
13677 $this->rulesByHash[$hash] = array($originalRule, $rule);
13678 }
13679 }
13680
13681 public function count()
13682 {
13683 return $this->nextRuleId;
13684 }
13685
13686 public function ruleById($id)
13687 {
13688 return $this->ruleById[$id];
13689 }
13690
13691 public function getRules()
13692 {
13693 return $this->rules;
13694 }
13695
13696 public function getIterator()
13697 {
13698 return new RuleSetIterator($this->getRules());
13699 }
13700
13701 public function getIteratorFor($types)
13702 {
13703 if (!is_array($types)) {
13704 $types = array($types);
13705 }
13706
13707 $allRules = $this->getRules();
13708 $rules = array();
13709
13710 foreach ($types as $type) {
13711 $rules[$type] = $allRules[$type];
13712 }
13713
13714 return new RuleSetIterator($rules);
13715 }
13716
13717 public function getIteratorWithout($types)
13718 {
13719 if (!is_array($types)) {
13720 $types = array($types);
13721 }
13722
13723 $rules = $this->getRules();
13724
13725 foreach ($types as $type) {
13726 unset($rules[$type]);
13727 }
13728
13729 return new RuleSetIterator($rules);
13730 }
13731
13732 public function getTypes()
13733 {
13734 $types = self::$types;
13735 unset($types[255]);
13736
13737 return array_keys($types);
13738 }
13739
13740 public function getPrettyString(Pool $pool = null)
13741 {
13742 $string = "\n";
13743 foreach ($this->rules as $type => $rules) {
13744 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
13745 foreach ($rules as $rule) {
13746 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
13747 }
13748 $string .= "\n\n";
13749 }
13750
13751 return $string;
13752 }
13753
13754 public function __toString()
13755 {
13756 return $this->getPrettyString(null);
13757 }
13758 }
13759 <?php
13760
13761
13762
13763
13764
13765
13766
13767
13768
13769
13770
13771 namespace Composer\DependencyResolver;
13772
13773 use Composer\Package\PackageInterface;
13774 use Composer\Package\AliasPackage;
13775 use Composer\Repository\PlatformRepository;
13776
13777
13778
13779
13780 class RuleSetGenerator
13781 {
13782 protected $policy;
13783 protected $pool;
13784 protected $rules;
13785 protected $jobs;
13786 protected $installedMap;
13787 protected $whitelistedMap;
13788 protected $addedMap;
13789 protected $conflictAddedMap;
13790 protected $addedPackages;
13791 protected $addedPackagesByNames;
13792
13793 public function __construct(PolicyInterface $policy, Pool $pool)
13794 {
13795 $this->policy = $policy;
13796 $this->pool = $pool;
13797 }
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812
13813 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
13814 {
13815 $literals = array(-$package->id);
13816
13817 foreach ($providers as $provider) {
13818
13819  if ($provider === $package) {
13820 return null;
13821 }
13822 $literals[] = $provider->id;
13823 }
13824
13825 return new GenericRule($literals, $reason, $reasonData);
13826 }
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838
13839
13840 protected function createInstallOneOfRule(array $packages, $reason, $job)
13841 {
13842 $literals = array();
13843 foreach ($packages as $package) {
13844 $literals[] = $package->id;
13845 }
13846
13847 return new GenericRule($literals, $reason, $job['packageName'], $job);
13848 }
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
13860
13861 protected function createRemoveRule(PackageInterface $package, $reason, $job)
13862 {
13863 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
13864 }
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874
13875
13876
13877
13878
13879
13880 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
13881 {
13882
13883  if ($issuer === $provider) {
13884 return null;
13885 }
13886
13887 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
13888 }
13889
13890
13891
13892
13893
13894
13895
13896
13897
13898
13899 private function addRule($type, Rule $newRule = null)
13900 {
13901 if (!$newRule) {
13902 return;
13903 }
13904
13905 $this->rules->add($newRule, $type);
13906 }
13907
13908 protected function whitelistFromPackage(PackageInterface $package)
13909 {
13910 $workQueue = new \SplQueue;
13911 $workQueue->enqueue($package);
13912
13913 while (!$workQueue->isEmpty()) {
13914 $package = $workQueue->dequeue();
13915 if (isset($this->whitelistedMap[$package->id])) {
13916 continue;
13917 }
13918
13919 $this->whitelistedMap[$package->id] = true;
13920
13921 foreach ($package->getRequires() as $link) {
13922 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
13923
13924 foreach ($possibleRequires as $require) {
13925 $workQueue->enqueue($require);
13926 }
13927 }
13928
13929 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
13930
13931 foreach ($obsoleteProviders as $provider) {
13932 if ($provider === $package) {
13933 continue;
13934 }
13935
13936 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
13937 $workQueue->enqueue($provider);
13938 }
13939 }
13940 }
13941 }
13942
13943 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
13944 {
13945 $workQueue = new \SplQueue;
13946 $workQueue->enqueue($package);
13947
13948 while (!$workQueue->isEmpty()) {
13949
13950 $package = $workQueue->dequeue();
13951 if (isset($this->addedMap[$package->id])) {
13952 continue;
13953 }
13954
13955 $this->addedMap[$package->id] = true;
13956
13957 $this->addedPackages[] = $package;
13958 foreach ($package->getNames() as $name) {
13959 $this->addedPackagesByNames[$name][] = $package;
13960 }
13961
13962 foreach ($package->getRequires() as $link) {
13963 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
13964 continue;
13965 }
13966
13967 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13968
13969 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
13970
13971 foreach ($possibleRequires as $require) {
13972 $workQueue->enqueue($require);
13973 }
13974 }
13975
13976 $packageName = $package->getName();
13977 $obsoleteProviders = $this->pool->whatProvides($packageName, null);
13978
13979 foreach ($obsoleteProviders as $provider) {
13980 if ($provider === $package) {
13981 continue;
13982 }
13983
13984 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
13985 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
13986 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
13987 $reason = ($packageName == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
13988 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $package));
13989 }
13990 }
13991 }
13992 }
13993
13994 protected function addConflictRules($ignorePlatformReqs = false)
13995 {
13996
13997 foreach ($this->addedPackages as $package) {
13998 foreach ($package->getConflicts() as $link) {
13999 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
14000 continue;
14001 }
14002
14003 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
14004 continue;
14005 }
14006
14007
14008 foreach ($this->addedPackagesByNames[$link->getTarget()] as $possibleConflict) {
14009 $conflictMatch = $this->pool->match($possibleConflict, $link->getTarget(), $link->getConstraint(), true);
14010
14011 if ($conflictMatch === Pool::MATCH || $conflictMatch === Pool::MATCH_REPLACE) {
14012 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $possibleConflict, Rule::RULE_PACKAGE_CONFLICT, $link));
14013 }
14014
14015 }
14016 }
14017
14018
14019  $isInstalled = isset($this->installedMap[$package->id]);
14020
14021 foreach ($package->getReplaces() as $link) {
14022 if (!isset($this->addedPackagesByNames[$link->getTarget()])) {
14023 continue;
14024 }
14025
14026
14027 foreach ($this->addedPackagesByNames[$link->getTarget()] as $provider) {
14028 if ($provider === $package) {
14029 continue;
14030 }
14031
14032 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
14033 $reason = $isInstalled ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
14034 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
14035 }
14036 }
14037 }
14038 }
14039 }
14040
14041 protected function obsoleteImpossibleForAlias($package, $provider)
14042 {
14043 $packageIsAlias = $package instanceof AliasPackage;
14044 $providerIsAlias = $provider instanceof AliasPackage;
14045
14046 $impossible = (
14047 ($packageIsAlias && $package->getAliasOf() === $provider) ||
14048 ($providerIsAlias && $provider->getAliasOf() === $package) ||
14049 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
14050 );
14051
14052 return $impossible;
14053 }
14054
14055 protected function whitelistFromJobs()
14056 {
14057 foreach ($this->jobs as $job) {
14058 switch ($job['cmd']) {
14059 case 'install':
14060 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
14061 foreach ($packages as $package) {
14062 $this->whitelistFromPackage($package);
14063 }
14064 break;
14065 }
14066 }
14067 }
14068
14069 protected function addRulesForJobs($ignorePlatformReqs)
14070 {
14071 foreach ($this->jobs as $job) {
14072 switch ($job['cmd']) {
14073 case 'install':
14074 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
14075 break;
14076 }
14077
14078 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14079 if ($packages) {
14080 foreach ($packages as $package) {
14081 if (!isset($this->installedMap[$package->id])) {
14082 $this->addRulesForPackage($package, $ignorePlatformReqs);
14083 }
14084 }
14085
14086 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
14087 $this->addRule(RuleSet::TYPE_JOB, $rule);
14088 }
14089 break;
14090 case 'remove':
14091
14092  
14093  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14094 foreach ($packages as $package) {
14095 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
14096 $this->addRule(RuleSet::TYPE_JOB, $rule);
14097 }
14098 break;
14099 }
14100 }
14101 }
14102
14103 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
14104 {
14105 $this->jobs = $jobs;
14106 $this->rules = new RuleSet;
14107 $this->installedMap = $installedMap;
14108
14109 $this->whitelistedMap = array();
14110 foreach ($this->installedMap as $package) {
14111 $this->whitelistFromPackage($package);
14112 }
14113 $this->whitelistFromJobs();
14114
14115 $this->pool->setWhitelist($this->whitelistedMap);
14116
14117 $this->addedMap = array();
14118 $this->conflictAddedMap = array();
14119 $this->addedPackages = array();
14120 $this->addedPackagesByNames = array();
14121 foreach ($this->installedMap as $package) {
14122 $this->addRulesForPackage($package, $ignorePlatformReqs);
14123 }
14124
14125 $this->addRulesForJobs($ignorePlatformReqs);
14126
14127 $this->addConflictRules($ignorePlatformReqs);
14128
14129
14130  $this->addedPackages = $this->addedPackagesByNames = null;
14131
14132 return $this->rules;
14133 }
14134 }
14135 <?php
14136
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147 namespace Composer\DependencyResolver;
14148
14149
14150
14151
14152 class RuleSetIterator implements \Iterator
14153 {
14154 protected $rules;
14155 protected $types;
14156
14157 protected $currentOffset;
14158 protected $currentType;
14159 protected $currentTypeOffset;
14160
14161 public function __construct(array $rules)
14162 {
14163 $this->rules = $rules;
14164 $this->types = array_keys($rules);
14165 sort($this->types);
14166
14167 $this->rewind();
14168 }
14169
14170 public function current()
14171 {
14172 return $this->rules[$this->currentType][$this->currentOffset];
14173 }
14174
14175 public function key()
14176 {
14177 return $this->currentType;
14178 }
14179
14180 public function next()
14181 {
14182 $this->currentOffset++;
14183
14184 if (!isset($this->rules[$this->currentType])) {
14185 return;
14186 }
14187
14188 if ($this->currentOffset >= count($this->rules[$this->currentType])) {
14189 $this->currentOffset = 0;
14190
14191 do {
14192 $this->currentTypeOffset++;
14193
14194 if (!isset($this->types[$this->currentTypeOffset])) {
14195 $this->currentType = -1;
14196 break;
14197 }
14198
14199 $this->currentType = $this->types[$this->currentTypeOffset];
14200 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
14201 }
14202 }
14203
14204 public function rewind()
14205 {
14206 $this->currentOffset = 0;
14207
14208 $this->currentTypeOffset = -1;
14209 $this->currentType = -1;
14210
14211 do {
14212 $this->currentTypeOffset++;
14213
14214 if (!isset($this->types[$this->currentTypeOffset])) {
14215 $this->currentType = -1;
14216 break;
14217 }
14218
14219 $this->currentType = $this->types[$this->currentTypeOffset];
14220 } while (isset($this->types[$this->currentTypeOffset]) && !count($this->rules[$this->currentType]));
14221 }
14222
14223 public function valid()
14224 {
14225 return isset($this->rules[$this->currentType])
14226 && isset($this->rules[$this->currentType][$this->currentOffset]);
14227 }
14228 }
14229 <?php
14230
14231
14232
14233
14234
14235
14236
14237
14238
14239
14240
14241 namespace Composer\DependencyResolver;
14242
14243
14244
14245
14246
14247
14248
14249
14250
14251 class RuleWatchChain extends \SplDoublyLinkedList
14252 {
14253 protected $offset = 0;
14254
14255
14256
14257
14258
14259
14260 public function seek($offset)
14261 {
14262 $this->rewind();
14263 for ($i = 0; $i < $offset; $i++, $this->next());
14264 }
14265
14266
14267
14268
14269
14270
14271
14272
14273
14274 public function remove()
14275 {
14276 $offset = $this->key();
14277 $this->offsetUnset($offset);
14278 $this->seek($offset);
14279 }
14280 }
14281 <?php
14282
14283
14284
14285
14286
14287
14288
14289
14290
14291
14292
14293 namespace Composer\DependencyResolver;
14294
14295
14296
14297
14298
14299
14300
14301
14302
14303
14304
14305 class RuleWatchGraph
14306 {
14307 protected $watchChains = array();
14308
14309
14310
14311
14312
14313
14314
14315
14316
14317
14318
14319
14320
14321 public function insert(RuleWatchNode $node)
14322 {
14323 if ($node->getRule()->isAssertion()) {
14324 return;
14325 }
14326
14327 foreach (array($node->watch1, $node->watch2) as $literal) {
14328 if (!isset($this->watchChains[$literal])) {
14329 $this->watchChains[$literal] = new RuleWatchChain;
14330 }
14331
14332 $this->watchChains[$literal]->unshift($node);
14333 }
14334 }
14335
14336
14337
14338
14339
14340
14341
14342
14343
14344
14345
14346
14347
14348
14349
14350
14351
14352
14353
14354
14355
14356
14357
14358
14359 public function propagateLiteral($decidedLiteral, $level, $decisions)
14360 {
14361
14362  
14363  
14364  $literal = -$decidedLiteral;
14365
14366 if (!isset($this->watchChains[$literal])) {
14367 return null;
14368 }
14369
14370 $chain = $this->watchChains[$literal];
14371
14372 $chain->rewind();
14373 while ($chain->valid()) {
14374 $node = $chain->current();
14375 $otherWatch = $node->getOtherWatch($literal);
14376
14377 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
14378 $ruleLiterals = $node->getRule()->getLiterals();
14379
14380 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
14381 return $literal !== $ruleLiteral &&
14382 $otherWatch !== $ruleLiteral &&
14383 !$decisions->conflict($ruleLiteral);
14384 });
14385
14386 if ($alternativeLiterals) {
14387 reset($alternativeLiterals);
14388 $this->moveWatch($literal, current($alternativeLiterals), $node);
14389 continue;
14390 }
14391
14392 if ($decisions->conflict($otherWatch)) {
14393 return $node->getRule();
14394 }
14395
14396 $decisions->decide($otherWatch, $level, $node->getRule());
14397 }
14398
14399 $chain->next();
14400 }
14401
14402 return null;
14403 }
14404
14405
14406
14407
14408
14409
14410
14411
14412
14413
14414 protected function moveWatch($fromLiteral, $toLiteral, $node)
14415 {
14416 if (!isset($this->watchChains[$toLiteral])) {
14417 $this->watchChains[$toLiteral] = new RuleWatchChain;
14418 }
14419
14420 $node->moveWatch($fromLiteral, $toLiteral);
14421 $this->watchChains[$fromLiteral]->remove();
14422 $this->watchChains[$toLiteral]->unshift($node);
14423 }
14424 }
14425 <?php
14426
14427
14428
14429
14430
14431
14432
14433
14434
14435
14436
14437 namespace Composer\DependencyResolver;
14438
14439
14440
14441
14442
14443
14444
14445
14446 class RuleWatchNode
14447 {
14448 public $watch1;
14449 public $watch2;
14450
14451 protected $rule;
14452
14453
14454
14455
14456
14457
14458 public function __construct($rule)
14459 {
14460 $this->rule = $rule;
14461
14462 $literals = $rule->getLiterals();
14463
14464 $literalCount = count($literals);
14465 $this->watch1 = $literalCount > 0 ? $literals[0] : 0;
14466 $this->watch2 = $literalCount > 1 ? $literals[1] : 0;
14467 }
14468
14469
14470
14471
14472
14473
14474
14475
14476
14477 public function watch2OnHighest(Decisions $decisions)
14478 {
14479 $literals = $this->rule->getLiterals();
14480
14481
14482  if (count($literals) < 3) {
14483 return;
14484 }
14485
14486 $watchLevel = 0;
14487
14488 foreach ($literals as $literal) {
14489 $level = $decisions->decisionLevel($literal);
14490
14491 if ($level > $watchLevel) {
14492 $this->watch2 = $literal;
14493 $watchLevel = $level;
14494 }
14495 }
14496 }
14497
14498
14499
14500
14501
14502
14503 public function getRule()
14504 {
14505 return $this->rule;
14506 }
14507
14508
14509
14510
14511
14512
14513
14514 public function getOtherWatch($literal)
14515 {
14516 if ($this->watch1 == $literal) {
14517 return $this->watch2;
14518 }
14519
14520 return $this->watch1;
14521 }
14522
14523
14524
14525
14526
14527
14528
14529 public function moveWatch($from, $to)
14530 {
14531 if ($this->watch1 == $from) {
14532 $this->watch1 = $to;
14533 } else {
14534 $this->watch2 = $to;
14535 }
14536 }
14537 }
14538 <?php
14539
14540
14541
14542
14543
14544
14545
14546
14547
14548
14549
14550 namespace Composer\DependencyResolver;
14551
14552 use Composer\IO\IOInterface;
14553 use Composer\Repository\RepositoryInterface;
14554 use Composer\Repository\PlatformRepository;
14555
14556
14557
14558
14559 class Solver
14560 {
14561 const BRANCH_LITERALS = 0;
14562 const BRANCH_LEVEL = 1;
14563
14564
14565 protected $policy;
14566
14567 protected $pool;
14568
14569 protected $installed;
14570
14571 protected $rules;
14572
14573 protected $ruleSetGenerator;
14574
14575 protected $jobs;
14576
14577
14578 protected $updateMap = array();
14579
14580 protected $watchGraph;
14581
14582 protected $decisions;
14583
14584 protected $installedMap;
14585
14586
14587 protected $propagateIndex;
14588
14589 protected $branches = array();
14590
14591 protected $problems = array();
14592
14593 protected $learnedPool = array();
14594
14595 protected $learnedWhy = array();
14596
14597
14598 public $testFlagLearnedPositiveLiteral = false;
14599
14600
14601 protected $io;
14602
14603
14604
14605
14606
14607
14608
14609 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
14610 {
14611 $this->io = $io;
14612 $this->policy = $policy;
14613 $this->pool = $pool;
14614 $this->installed = $installed;
14615 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
14616 }
14617
14618
14619
14620
14621 public function getRuleSetSize()
14622 {
14623 return count($this->rules);
14624 }
14625
14626
14627
14628 private function makeAssertionRuleDecisions()
14629 {
14630 $decisionStart = count($this->decisions) - 1;
14631
14632 $rulesCount = count($this->rules);
14633 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
14634 $rule = $this->rules->ruleById[$ruleIndex];
14635
14636 if (!$rule->isAssertion() || $rule->isDisabled()) {
14637 continue;
14638 }
14639
14640 $literals = $rule->getLiterals();
14641 $literal = $literals[0];
14642
14643 if (!$this->decisions->decided($literal)) {
14644 $this->decisions->decide($literal, 1, $rule);
14645 continue;
14646 }
14647
14648 if ($this->decisions->satisfy($literal)) {
14649 continue;
14650 }
14651
14652
14653  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
14654 $rule->disable();
14655 continue;
14656 }
14657
14658 $conflict = $this->decisions->decisionRule($literal);
14659
14660 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
14661 $problem = new Problem($this->pool);
14662
14663 $problem->addRule($rule);
14664 $problem->addRule($conflict);
14665 $this->disableProblem($rule);
14666 $this->problems[] = $problem;
14667 continue;
14668 }
14669
14670
14671  $problem = new Problem($this->pool);
14672 $problem->addRule($rule);
14673 $problem->addRule($conflict);
14674
14675
14676  
14677  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
14678 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
14679 continue;
14680 }
14681
14682 $assertRuleLiterals = $assertRule->getLiterals();
14683 $assertRuleLiteral = $assertRuleLiterals[0];
14684
14685 if (abs($literal) !== abs($assertRuleLiteral)) {
14686 continue;
14687 }
14688
14689 $problem->addRule($assertRule);
14690 $this->disableProblem($assertRule);
14691 }
14692 $this->problems[] = $problem;
14693
14694 $this->decisions->resetToOffset($decisionStart);
14695 $ruleIndex = -1;
14696 }
14697 }
14698
14699 protected function setupInstalledMap()
14700 {
14701 $this->installedMap = array();
14702 foreach ($this->installed->getPackages() as $package) {
14703 $this->installedMap[$package->id] = $package;
14704 }
14705 }
14706
14707
14708
14709
14710 protected function checkForRootRequireProblems($ignorePlatformReqs)
14711 {
14712 foreach ($this->jobs as $job) {
14713 switch ($job['cmd']) {
14714 case 'update':
14715 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
14716 foreach ($packages as $package) {
14717 if (isset($this->installedMap[$package->id])) {
14718 $this->updateMap[$package->id] = true;
14719 }
14720 }
14721 break;
14722
14723 case 'update-all':
14724 foreach ($this->installedMap as $package) {
14725 $this->updateMap[$package->id] = true;
14726 }
14727 break;
14728
14729 case 'install':
14730 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
14731 break;
14732 }
14733
14734 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
14735 $problem = new Problem($this->pool);
14736 $problem->addRule(new GenericRule(array(), null, null, $job));
14737 $this->problems[] = $problem;
14738 }
14739 break;
14740 }
14741 }
14742 }
14743
14744
14745
14746
14747
14748
14749 public function solve(Request $request, $ignorePlatformReqs = false)
14750 {
14751 $this->jobs = $request->getJobs();
14752
14753 $this->setupInstalledMap();
14754 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
14755 $this->checkForRootRequireProblems($ignorePlatformReqs);
14756 $this->decisions = new Decisions($this->pool);
14757 $this->watchGraph = new RuleWatchGraph;
14758
14759 foreach ($this->rules as $rule) {
14760 $this->watchGraph->insert(new RuleWatchNode($rule));
14761 }
14762
14763
14764 $this->makeAssertionRuleDecisions();
14765
14766 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
14767 $before = microtime(true);
14768 $this->runSat(true);
14769 $this->io->writeError('', true, IOInterface::DEBUG);
14770 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
14771
14772
14773  foreach ($this->installedMap as $packageId => $void) {
14774 if ($this->decisions->undecided($packageId)) {
14775 $this->decisions->decide(-$packageId, 1, null);
14776 }
14777 }
14778
14779 if ($this->problems) {
14780 throw new SolverProblemsException($this->problems, $this->installedMap);
14781 }
14782
14783 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
14784
14785 return $transaction->getOperations();
14786 }
14787
14788
14789
14790
14791
14792
14793
14794
14795
14796
14797 protected function propagate($level)
14798 {
14799 while ($this->decisions->validOffset($this->propagateIndex)) {
14800 $decision = $this->decisions->atOffset($this->propagateIndex);
14801
14802 $conflict = $this->watchGraph->propagateLiteral(
14803 $decision[Decisions::DECISION_LITERAL],
14804 $level,
14805 $this->decisions
14806 );
14807
14808 $this->propagateIndex++;
14809
14810 if ($conflict) {
14811 return $conflict;
14812 }
14813 }
14814
14815 return null;
14816 }
14817
14818
14819
14820
14821
14822
14823 private function revert($level)
14824 {
14825 while (!$this->decisions->isEmpty()) {
14826 $literal = $this->decisions->lastLiteral();
14827
14828 if ($this->decisions->undecided($literal)) {
14829 break;
14830 }
14831
14832 $decisionLevel = $this->decisions->decisionLevel($literal);
14833
14834 if ($decisionLevel <= $level) {
14835 break;
14836 }
14837
14838 $this->decisions->revertLast();
14839 $this->propagateIndex = count($this->decisions);
14840 }
14841
14842 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
14843 array_pop($this->branches);
14844 }
14845 }
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
14867 {
14868 $level++;
14869
14870 $this->decisions->decide($literal, $level, $rule);
14871
14872 while (true) {
14873 $rule = $this->propagate($level);
14874
14875 if (!$rule) {
14876 break;
14877 }
14878
14879 if ($level == 1) {
14880 return $this->analyzeUnsolvable($rule, $disableRules);
14881 }
14882
14883
14884  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
14885
14886 if ($newLevel <= 0 || $newLevel >= $level) {
14887 throw new SolverBugException(
14888 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
14889 );
14890 } elseif (!$newRule) {
14891 throw new SolverBugException(
14892 "No rule was learned from analyzing $rule at level $level."
14893 );
14894 }
14895
14896 $level = $newLevel;
14897
14898 $this->revert($level);
14899
14900 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
14901
14902 $this->learnedWhy[spl_object_hash($newRule)] = $why;
14903
14904 $ruleNode = new RuleWatchNode($newRule);
14905 $ruleNode->watch2OnHighest($this->decisions);
14906 $this->watchGraph->insert($ruleNode);
14907
14908 $this->decisions->decide($learnLiteral, $level, $newRule);
14909 }
14910
14911 return $level;
14912 }
14913
14914
14915
14916
14917
14918
14919
14920
14921 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
14922 {
14923
14924  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
14925
14926 $selectedLiteral = array_shift($literals);
14927
14928
14929  if (count($literals)) {
14930 $this->branches[] = array($literals, $level);
14931 }
14932
14933 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
14934 }
14935
14936
14937
14938
14939
14940
14941 protected function analyze($level, Rule $rule)
14942 {
14943 $analyzedRule = $rule;
14944 $ruleLevel = 1;
14945 $num = 0;
14946 $l1num = 0;
14947 $seen = array();
14948 $learnedLiterals = array(null);
14949
14950 $decisionId = count($this->decisions);
14951
14952 $this->learnedPool[] = array();
14953
14954 while (true) {
14955 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
14956
14957 foreach ($rule->getLiterals() as $literal) {
14958
14959  if ($this->decisions->satisfy($literal)) {
14960 continue;
14961 }
14962
14963 if (isset($seen[abs($literal)])) {
14964 continue;
14965 }
14966 $seen[abs($literal)] = true;
14967
14968 $l = $this->decisions->decisionLevel($literal);
14969
14970 if (1 === $l) {
14971 $l1num++;
14972 } elseif ($level === $l) {
14973 $num++;
14974 } else {
14975
14976  $learnedLiterals[] = $literal;
14977
14978 if ($l > $ruleLevel) {
14979 $ruleLevel = $l;
14980 }
14981 }
14982 }
14983
14984 $l1retry = true;
14985 while ($l1retry) {
14986 $l1retry = false;
14987
14988 if (!$num && !--$l1num) {
14989
14990  break 2;
14991 }
14992
14993 while (true) {
14994 if ($decisionId <= 0) {
14995 throw new SolverBugException(
14996 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
14997 );
14998 }
14999
15000 $decisionId--;
15001
15002 $decision = $this->decisions->atOffset($decisionId);
15003 $literal = $decision[Decisions::DECISION_LITERAL];
15004
15005 if (isset($seen[abs($literal)])) {
15006 break;
15007 }
15008 }
15009
15010 unset($seen[abs($literal)]);
15011
15012 if ($num && 0 === --$num) {
15013 if ($literal < 0) {
15014 $this->testFlagLearnedPositiveLiteral = true;
15015 }
15016 $learnedLiterals[0] = -$literal;
15017
15018 if (!$l1num) {
15019 break 2;
15020 }
15021
15022 foreach ($learnedLiterals as $i => $learnedLiteral) {
15023 if ($i !== 0) {
15024 unset($seen[abs($learnedLiteral)]);
15025 }
15026 }
15027
15028  $l1num++;
15029 $l1retry = true;
15030 }
15031 }
15032
15033 $decision = $this->decisions->atOffset($decisionId);
15034 $rule = $decision[Decisions::DECISION_REASON];
15035 }
15036
15037 $why = count($this->learnedPool) - 1;
15038
15039 if (!$learnedLiterals[0]) {
15040 throw new SolverBugException(
15041 "Did not find a learnable literal in analyzed rule $analyzedRule."
15042 );
15043 }
15044
15045 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
15046
15047 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
15048 }
15049
15050
15051
15052
15053
15054 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
15055 {
15056 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
15057 $why = spl_object_hash($conflictRule);
15058 $learnedWhy = $this->learnedWhy[$why];
15059 $problemRules = $this->learnedPool[$learnedWhy];
15060
15061 foreach ($problemRules as $problemRule) {
15062 $this->analyzeUnsolvableRule($problem, $problemRule);
15063 }
15064
15065 return;
15066 }
15067
15068 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
15069
15070  return;
15071 }
15072
15073 $problem->nextSection();
15074 $problem->addRule($conflictRule);
15075 }
15076
15077
15078
15079
15080
15081
15082 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
15083 {
15084 $problem = new Problem($this->pool);
15085 $problem->addRule($conflictRule);
15086
15087 $this->analyzeUnsolvableRule($problem, $conflictRule);
15088
15089 $this->problems[] = $problem;
15090
15091 $seen = array();
15092 $literals = $conflictRule->getLiterals();
15093
15094 foreach ($literals as $literal) {
15095
15096  if ($this->decisions->satisfy($literal)) {
15097 continue;
15098 }
15099 $seen[abs($literal)] = true;
15100 }
15101
15102 foreach ($this->decisions as $decision) {
15103 $literal = $decision[Decisions::DECISION_LITERAL];
15104
15105
15106  if (!isset($seen[abs($literal)])) {
15107 continue;
15108 }
15109
15110 $why = $decision[Decisions::DECISION_REASON];
15111
15112 $problem->addRule($why);
15113 $this->analyzeUnsolvableRule($problem, $why);
15114
15115 $literals = $why->getLiterals();
15116
15117 foreach ($literals as $literal) {
15118
15119  if ($this->decisions->satisfy($literal)) {
15120 continue;
15121 }
15122 $seen[abs($literal)] = true;
15123 }
15124 }
15125
15126 if ($disableRules) {
15127 foreach ($this->problems[count($this->problems) - 1] as $reason) {
15128 $this->disableProblem($reason['rule']);
15129 }
15130
15131 $this->resetSolver();
15132
15133 return 1;
15134 }
15135
15136 return 0;
15137 }
15138
15139
15140
15141
15142 private function disableProblem(Rule $why)
15143 {
15144 $job = $why->getJob();
15145
15146 if (!$job) {
15147 $why->disable();
15148
15149 return;
15150 }
15151
15152
15153  foreach ($this->rules as $rule) {
15154
15155 if ($job === $rule->getJob()) {
15156 $rule->disable();
15157 }
15158 }
15159 }
15160
15161 private function resetSolver()
15162 {
15163 $this->decisions->reset();
15164
15165 $this->propagateIndex = 0;
15166 $this->branches = array();
15167
15168 $this->enableDisableLearnedRules();
15169 $this->makeAssertionRuleDecisions();
15170 }
15171
15172
15173
15174
15175
15176
15177
15178
15179 private function enableDisableLearnedRules()
15180 {
15181 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
15182 $why = $this->learnedWhy[spl_object_hash($rule)];
15183 $problemRules = $this->learnedPool[$why];
15184
15185 $foundDisabled = false;
15186 foreach ($problemRules as $problemRule) {
15187 if ($problemRule->isDisabled()) {
15188 $foundDisabled = true;
15189 break;
15190 }
15191 }
15192
15193 if ($foundDisabled && $rule->isEnabled()) {
15194 $rule->disable();
15195 } elseif (!$foundDisabled && $rule->isDisabled()) {
15196 $rule->enable();
15197 }
15198 }
15199 }
15200
15201
15202
15203
15204 private function runSat($disableRules = true)
15205 {
15206 $this->propagateIndex = 0;
15207
15208
15209
15210
15211
15212
15213
15214
15215
15216
15217
15218 $decisionQueue = array();
15219
15220
15221
15222 $disableRules = array();
15223
15224 $level = 1;
15225 $systemLevel = $level + 1;
15226
15227 while (true) {
15228 if (1 === $level) {
15229 $conflictRule = $this->propagate($level);
15230 if (null !== $conflictRule) {
15231 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
15232 continue;
15233 }
15234
15235 return;
15236 }
15237 }
15238
15239
15240  if ($level < $systemLevel) {
15241 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
15242 foreach ($iterator as $rule) {
15243 if ($rule->isEnabled()) {
15244 $decisionQueue = array();
15245 $noneSatisfied = true;
15246
15247 foreach ($rule->getLiterals() as $literal) {
15248 if ($this->decisions->satisfy($literal)) {
15249 $noneSatisfied = false;
15250 break;
15251 }
15252 if ($literal > 0 && $this->decisions->undecided($literal)) {
15253 $decisionQueue[] = $literal;
15254 }
15255 }
15256
15257 if ($noneSatisfied && count($decisionQueue)) {
15258
15259  
15260  if (count($this->installed) != count($this->updateMap)) {
15261 $prunedQueue = array();
15262 foreach ($decisionQueue as $literal) {
15263 if (isset($this->installedMap[abs($literal)])) {
15264 $prunedQueue[] = $literal;
15265 if (isset($this->updateMap[abs($literal)])) {
15266 $prunedQueue = $decisionQueue;
15267 break;
15268 }
15269 }
15270 }
15271 $decisionQueue = $prunedQueue;
15272 }
15273 }
15274
15275 if ($noneSatisfied && count($decisionQueue)) {
15276 $oLevel = $level;
15277 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
15278
15279 if (0 === $level) {
15280 return;
15281 }
15282 if ($level <= $oLevel) {
15283 break;
15284 }
15285 }
15286 }
15287 }
15288
15289 $systemLevel = $level + 1;
15290
15291
15292  $iterator->next();
15293 if ($iterator->valid()) {
15294 continue;
15295 }
15296 }
15297
15298 if ($level < $systemLevel) {
15299 $systemLevel = $level;
15300 }
15301
15302 $rulesCount = count($this->rules);
15303 $pass = 1;
15304
15305 $this->io->writeError('Looking at all rules.', true, IOInterface::DEBUG);
15306 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
15307 if ($i == $rulesCount) {
15308 if (1 === $pass) {
15309 $this->io->writeError("Something's changed, looking at all rules again (pass #$pass)", false, IOInterface::DEBUG);
15310 } else {
15311 $this->io->overwriteError("Something's changed, looking at all rules again (pass #$pass)", false, null, IOInterface::DEBUG);
15312 }
15313
15314 $i = 0;
15315 $pass++;
15316 }
15317
15318 $rule = $this->rules->ruleById[$i];
15319 $literals = $rule->getLiterals();
15320
15321 if ($rule->isDisabled()) {
15322 continue;
15323 }
15324
15325 $decisionQueue = array();
15326
15327
15328  
15329  
15330  
15331  
15332  
15333  foreach ($literals as $literal) {
15334 if ($literal <= 0) {
15335 if (!$this->decisions->decidedInstall($literal)) {
15336 continue 2; 
15337  }
15338 } else {
15339 if ($this->decisions->decidedInstall($literal)) {
15340 continue 2; 
15341  }
15342 if ($this->decisions->undecided($literal)) {
15343 $decisionQueue[] = $literal;
15344 }
15345 }
15346 }
15347
15348
15349  if (count($decisionQueue) < 2) {
15350 continue;
15351 }
15352
15353 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
15354
15355 if (0 === $level) {
15356 return;
15357 }
15358
15359
15360  $rulesCount = count($this->rules);
15361 $n = -1;
15362 }
15363
15364 if ($level < $systemLevel) {
15365 continue;
15366 }
15367
15368
15369  if (count($this->branches)) {
15370 $lastLiteral = null;
15371 $lastLevel = null;
15372 $lastBranchIndex = 0;
15373 $lastBranchOffset = 0;
15374
15375 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
15376 list($literals, $l) = $this->branches[$i];
15377
15378 foreach ($literals as $offset => $literal) {
15379 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
15380 $lastLiteral = $literal;
15381 $lastBranchIndex = $i;
15382 $lastBranchOffset = $offset;
15383 $lastLevel = $l;
15384 }
15385 }
15386 }
15387
15388 if ($lastLiteral) {
15389 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
15390
15391 $level = $lastLevel;
15392 $this->revert($level);
15393
15394 $why = $this->decisions->lastReason();
15395
15396 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
15397
15398 if ($level == 0) {
15399 return;
15400 }
15401
15402 continue;
15403 }
15404 }
15405
15406 break;
15407 }
15408 }
15409 }
15410 <?php
15411
15412
15413
15414
15415
15416
15417
15418
15419
15420
15421
15422 namespace Composer\DependencyResolver;
15423
15424
15425
15426
15427 class SolverBugException extends \RuntimeException
15428 {
15429 public function __construct($message)
15430 {
15431 parent::__construct(
15432 $message."\nThis exception was most likely caused by a bug in Composer.\n".
15433 "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"
15434 );
15435 }
15436 }
15437 <?php
15438
15439
15440
15441
15442
15443
15444
15445
15446
15447
15448
15449 namespace Composer\DependencyResolver;
15450
15451 use Composer\Util\IniHelper;
15452
15453
15454
15455
15456 class SolverProblemsException extends \RuntimeException
15457 {
15458 protected $problems;
15459 protected $installedMap;
15460
15461 public function __construct(array $problems, array $installedMap)
15462 {
15463 $this->problems = $problems;
15464 $this->installedMap = $installedMap;
15465
15466 parent::__construct($this->createMessage(), 2);
15467 }
15468
15469 protected function createMessage()
15470 {
15471 $text = "\n";
15472 $hasExtensionProblems = false;
15473 foreach ($this->problems as $i => $problem) {
15474 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
15475
15476 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
15477 $hasExtensionProblems = true;
15478 }
15479 }
15480
15481 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
15482 $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.";
15483 }
15484
15485 if ($hasExtensionProblems) {
15486 $text .= $this->createExtensionHint();
15487 }
15488
15489 return $text;
15490 }
15491
15492 public function getProblems()
15493 {
15494 return $this->problems;
15495 }
15496
15497 private function createExtensionHint()
15498 {
15499 $paths = IniHelper::getAll();
15500
15501 if (count($paths) === 1 && empty($paths[0])) {
15502 return '';
15503 }
15504
15505 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
15506 $text .= implode("\n    - ", $paths);
15507 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
15508
15509 return $text;
15510 }
15511
15512 private function hasExtensionProblems(array $reasonSets)
15513 {
15514 foreach ($reasonSets as $reasonSet) {
15515 foreach ($reasonSet as $reason) {
15516 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
15517 return true;
15518 }
15519 }
15520 }
15521
15522 return false;
15523 }
15524 }
15525 <?php
15526
15527
15528
15529
15530
15531
15532
15533
15534
15535
15536
15537 namespace Composer\DependencyResolver;
15538
15539 use Composer\Package\AliasPackage;
15540
15541
15542
15543
15544 class Transaction
15545 {
15546 protected $policy;
15547 protected $pool;
15548 protected $installedMap;
15549 protected $decisions;
15550 protected $transaction;
15551
15552 public function __construct($policy, $pool, $installedMap, $decisions)
15553 {
15554 $this->policy = $policy;
15555 $this->pool = $pool;
15556 $this->installedMap = $installedMap;
15557 $this->decisions = $decisions;
15558 $this->transaction = array();
15559 }
15560
15561 public function getOperations()
15562 {
15563 $installMeansUpdateMap = $this->findUpdates();
15564
15565 $updateMap = array();
15566 $installMap = array();
15567 $uninstallMap = array();
15568
15569 foreach ($this->decisions as $i => $decision) {
15570 $literal = $decision[Decisions::DECISION_LITERAL];
15571 $reason = $decision[Decisions::DECISION_REASON];
15572
15573 $package = $this->pool->literalToPackage($literal);
15574
15575
15576  if (($literal > 0) == isset($this->installedMap[$package->id])) {
15577 continue;
15578 }
15579
15580 if ($literal > 0) {
15581 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
15582 $source = $installMeansUpdateMap[abs($literal)];
15583
15584 $updateMap[$package->id] = array(
15585 'package' => $package,
15586 'source' => $source,
15587 'reason' => $reason,
15588 );
15589
15590
15591  unset($installMeansUpdateMap[abs($literal)]);
15592 $ignoreRemove[$source->id] = true;
15593 } else {
15594 $installMap[$package->id] = array(
15595 'package' => $package,
15596 'reason' => $reason,
15597 );
15598 }
15599 }
15600 }
15601
15602 foreach ($this->decisions as $i => $decision) {
15603 $literal = $decision[Decisions::DECISION_LITERAL];
15604 $reason = $decision[Decisions::DECISION_REASON];
15605 $package = $this->pool->literalToPackage($literal);
15606
15607 if ($literal <= 0 &&
15608 isset($this->installedMap[$package->id]) &&
15609 !isset($ignoreRemove[$package->id])) {
15610 $uninstallMap[$package->id] = array(
15611 'package' => $package,
15612 'reason' => $reason,
15613 );
15614 }
15615 }
15616
15617 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
15618
15619 return $this->transaction;
15620 }
15621
15622 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
15623 {
15624 $queue = array_map(
15625 function ($operation) {
15626 return $operation['package'];
15627 },
15628 $this->findRootPackages($installMap, $updateMap)
15629 );
15630
15631 $visited = array();
15632
15633 while (!empty($queue)) {
15634 $package = array_pop($queue);
15635 $packageId = $package->id;
15636
15637 if (!isset($visited[$packageId])) {
15638 $queue[] = $package;
15639
15640 if ($package instanceof AliasPackage) {
15641 $queue[] = $package->getAliasOf();
15642 } else {
15643 foreach ($package->getRequires() as $link) {
15644 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
15645
15646 foreach ($possibleRequires as $require) {
15647 $queue[] = $require;
15648 }
15649 }
15650 }
15651
15652 $visited[$package->id] = true;
15653 } else {
15654 if (isset($installMap[$packageId])) {
15655 $this->install(
15656 $installMap[$packageId]['package'],
15657 $installMap[$packageId]['reason']
15658 );
15659 unset($installMap[$packageId]);
15660 }
15661 if (isset($updateMap[$packageId])) {
15662 $this->update(
15663 $updateMap[$packageId]['source'],
15664 $updateMap[$packageId]['package'],
15665 $updateMap[$packageId]['reason']
15666 );
15667 unset($updateMap[$packageId]);
15668 }
15669 }
15670 }
15671
15672 foreach ($uninstallMap as $uninstall) {
15673 $this->uninstall($uninstall['package'], $uninstall['reason']);
15674 }
15675 }
15676
15677 protected function findRootPackages($installMap, $updateMap)
15678 {
15679 $packages = $installMap + $updateMap;
15680 $roots = $packages;
15681
15682 foreach ($packages as $packageId => $operation) {
15683 $package = $operation['package'];
15684
15685 if (!isset($roots[$packageId])) {
15686 continue;
15687 }
15688
15689 foreach ($package->getRequires() as $link) {
15690 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
15691
15692 foreach ($possibleRequires as $require) {
15693 if ($require !== $package) {
15694 unset($roots[$require->id]);
15695 }
15696 }
15697 }
15698 }
15699
15700 return $roots;
15701 }
15702
15703 protected function findUpdates()
15704 {
15705 $installMeansUpdateMap = array();
15706
15707 foreach ($this->decisions as $i => $decision) {
15708 $literal = $decision[Decisions::DECISION_LITERAL];
15709 $package = $this->pool->literalToPackage($literal);
15710
15711 if ($package instanceof AliasPackage) {
15712 continue;
15713 }
15714
15715
15716  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
15717 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
15718
15719 $literals = array($package->id);
15720
15721 foreach ($updates as $update) {
15722 $literals[] = $update->id;
15723 }
15724
15725 foreach ($literals as $updateLiteral) {
15726 if ($updateLiteral !== $literal) {
15727 $installMeansUpdateMap[abs($updateLiteral)] = $package;
15728 }
15729 }
15730 }
15731 }
15732
15733 return $installMeansUpdateMap;
15734 }
15735
15736 protected function install($package, $reason)
15737 {
15738 if ($package instanceof AliasPackage) {
15739 return $this->markAliasInstalled($package, $reason);
15740 }
15741
15742 $this->transaction[] = new Operation\InstallOperation($package, $reason);
15743 }
15744
15745 protected function update($from, $to, $reason)
15746 {
15747 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
15748 }
15749
15750 protected function uninstall($package, $reason)
15751 {
15752 if ($package instanceof AliasPackage) {
15753 return $this->markAliasUninstalled($package, $reason);
15754 }
15755
15756 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
15757 }
15758
15759 protected function markAliasInstalled($package, $reason)
15760 {
15761 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
15762 }
15763
15764 protected function markAliasUninstalled($package, $reason)
15765 {
15766 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
15767 }
15768 }
15769 <?php
15770
15771
15772
15773
15774
15775
15776
15777
15778
15779
15780
15781 namespace Composer\Downloader;
15782
15783 use Composer\Package\PackageInterface;
15784 use Symfony\Component\Finder\Finder;
15785 use Composer\IO\IOInterface;
15786
15787
15788
15789
15790
15791
15792
15793
15794 abstract class ArchiveDownloader extends FileDownloader
15795 {
15796
15797
15798
15799
15800
15801 public function download(PackageInterface $package, $path, $output = true)
15802 {
15803 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
15804 $retries = 3;
15805 while ($retries--) {
15806 $fileName = parent::download($package, $path, $output);
15807
15808 if ($output) {
15809 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
15810 }
15811
15812 try {
15813 $this->filesystem->ensureDirectoryExists($temporaryDir);
15814 try {
15815 $this->extract($fileName, $temporaryDir);
15816 } catch (\Exception $e) {
15817
15818  parent::clearLastCacheWrite($package);
15819 throw $e;
15820 }
15821
15822 $this->filesystem->unlink($fileName);
15823
15824 $contentDir = $this->getFolderContent($temporaryDir);
15825
15826
15827  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
15828 $contentDir = $this->getFolderContent((string) reset($contentDir));
15829 }
15830
15831
15832  foreach ($contentDir as $file) {
15833 $file = (string) $file;
15834 $this->filesystem->rename($file, $path . '/' . basename($file));
15835 }
15836
15837 $this->filesystem->removeDirectory($temporaryDir);
15838 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
15839 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
15840 }
15841 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
15842 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
15843 }
15844 } catch (\Exception $e) {
15845
15846  $this->filesystem->removeDirectory($path);
15847 $this->filesystem->removeDirectory($temporaryDir);
15848
15849
15850  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
15851 $this->io->writeError('');
15852 if ($this->io->isDebug()) {
15853 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
15854 } else {
15855 $this->io->writeError('    Invalid zip file, retrying...');
15856 }
15857 usleep(500000);
15858 continue;
15859 }
15860
15861 throw $e;
15862 }
15863
15864 break;
15865 }
15866 }
15867
15868
15869
15870
15871 protected function getFileName(PackageInterface $package, $path)
15872 {
15873 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
15874 }
15875
15876
15877
15878
15879
15880
15881
15882
15883
15884 abstract protected function extract($file, $path);
15885
15886
15887
15888
15889
15890
15891
15892 private function getFolderContent($dir)
15893 {
15894 $finder = Finder::create()
15895 ->ignoreVCS(false)
15896 ->ignoreDotFiles(false)
15897 ->notName('.DS_Store')
15898 ->depth(0)
15899 ->in($dir);
15900
15901 return iterator_to_array($finder);
15902 }
15903 }
15904 <?php
15905
15906
15907
15908
15909
15910
15911
15912
15913
15914
15915
15916 namespace Composer\Downloader;
15917
15918 use Composer\Package\PackageInterface;
15919
15920
15921
15922
15923
15924
15925 interface ChangeReportInterface
15926 {
15927
15928
15929
15930
15931
15932
15933
15934 public function getLocalChanges(PackageInterface $package, $path);
15935 }
15936 <?php
15937
15938
15939
15940
15941
15942
15943
15944
15945
15946
15947
15948 namespace Composer\Downloader;
15949
15950 use Composer\Package\PackageInterface;
15951 use Composer\IO\IOInterface;
15952 use Composer\Util\Filesystem;
15953
15954
15955
15956
15957
15958
15959 class DownloadManager
15960 {
15961 private $io;
15962 private $preferDist = false;
15963 private $preferSource = false;
15964 private $packagePreferences = array();
15965 private $filesystem;
15966 private $downloaders = array();
15967
15968
15969
15970
15971
15972
15973
15974
15975 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
15976 {
15977 $this->io = $io;
15978 $this->preferSource = $preferSource;
15979 $this->filesystem = $filesystem ?: new Filesystem();
15980 }
15981
15982
15983
15984
15985
15986
15987
15988 public function setPreferSource($preferSource)
15989 {
15990 $this->preferSource = $preferSource;
15991
15992 return $this;
15993 }
15994
15995
15996
15997
15998
15999
16000
16001 public function setPreferDist($preferDist)
16002 {
16003 $this->preferDist = $preferDist;
16004
16005 return $this;
16006 }
16007
16008
16009
16010
16011
16012
16013
16014 public function setPreferences(array $preferences)
16015 {
16016 $this->packagePreferences = $preferences;
16017
16018 return $this;
16019 }
16020
16021
16022
16023
16024
16025
16026
16027
16028 public function setOutputProgress($outputProgress)
16029 {
16030 foreach ($this->downloaders as $downloader) {
16031 $downloader->setOutputProgress($outputProgress);
16032 }
16033
16034 return $this;
16035 }
16036
16037
16038
16039
16040
16041
16042
16043
16044 public function setDownloader($type, DownloaderInterface $downloader)
16045 {
16046 $type = strtolower($type);
16047 $this->downloaders[$type] = $downloader;
16048
16049 return $this;
16050 }
16051
16052
16053
16054
16055
16056
16057
16058
16059 public function getDownloader($type)
16060 {
16061 $type = strtolower($type);
16062 if (!isset($this->downloaders[$type])) {
16063 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
16064 }
16065
16066 return $this->downloaders[$type];
16067 }
16068
16069
16070
16071
16072
16073
16074
16075
16076
16077
16078 public function getDownloaderForInstalledPackage(PackageInterface $package)
16079 {
16080 $installationSource = $package->getInstallationSource();
16081
16082 if ('metapackage' === $package->getType()) {
16083 return;
16084 }
16085
16086 if ('dist' === $installationSource) {
16087 $downloader = $this->getDownloader($package->getDistType());
16088 } elseif ('source' === $installationSource) {
16089 $downloader = $this->getDownloader($package->getSourceType());
16090 } else {
16091 throw new \InvalidArgumentException(
16092 'Package '.$package.' seems not been installed properly'
16093 );
16094 }
16095
16096 if ($installationSource !== $downloader->getInstallationSource()) {
16097 throw new \LogicException(sprintf(
16098 'Downloader "%s" is a %s type downloader and can not be used to download %s for package %s',
16099 get_class($downloader),
16100 $downloader->getInstallationSource(),
16101 $installationSource,
16102 $package
16103 ));
16104 }
16105
16106 return $downloader;
16107 }
16108
16109
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119 public function download(PackageInterface $package, $targetDir, $preferSource = null)
16120 {
16121 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
16122 $sourceType = $package->getSourceType();
16123 $distType = $package->getDistType();
16124
16125 $sources = array();
16126 if ($sourceType) {
16127 $sources[] = 'source';
16128 }
16129 if ($distType) {
16130 $sources[] = 'dist';
16131 }
16132
16133 if (empty($sources)) {
16134 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
16135 }
16136
16137 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
16138 $sources = array_reverse($sources);
16139 }
16140
16141 $this->filesystem->ensureDirectoryExists($targetDir);
16142
16143 foreach ($sources as $i => $source) {
16144 if (isset($e)) {
16145 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
16146 }
16147 $package->setInstallationSource($source);
16148 try {
16149 $downloader = $this->getDownloaderForInstalledPackage($package);
16150 if ($downloader) {
16151 $downloader->download($package, $targetDir);
16152 }
16153 break;
16154 } catch (\RuntimeException $e) {
16155 if ($i === count($sources) - 1) {
16156 throw $e;
16157 }
16158
16159 $this->io->writeError(
16160 '    <warning>Failed to download '.
16161 $package->getPrettyName().
16162 ' from ' . $source . ': '.
16163 $e->getMessage().'</warning>'
16164 );
16165 }
16166 }
16167 }
16168
16169
16170
16171
16172
16173
16174
16175
16176
16177
16178 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
16179 {
16180 $downloader = $this->getDownloaderForInstalledPackage($initial);
16181 if (!$downloader) {
16182 return;
16183 }
16184
16185 $installationSource = $initial->getInstallationSource();
16186
16187 if ('dist' === $installationSource) {
16188 $initialType = $initial->getDistType();
16189 $targetType = $target->getDistType();
16190 } else {
16191 $initialType = $initial->getSourceType();
16192 $targetType = $target->getSourceType();
16193 }
16194
16195
16196  if ($target->isDev() && 'dist' === $installationSource) {
16197 $downloader->remove($initial, $targetDir);
16198 $this->download($target, $targetDir);
16199
16200 return;
16201 }
16202
16203 if ($initialType === $targetType) {
16204 $target->setInstallationSource($installationSource);
16205 try {
16206 $downloader->update($initial, $target, $targetDir);
16207
16208 return;
16209 } catch (\RuntimeException $e) {
16210 if (!$this->io->isInteractive()) {
16211 throw $e;
16212 }
16213 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
16214 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
16215 throw $e;
16216 }
16217 }
16218 }
16219
16220 $downloader->remove($initial, $targetDir);
16221 $this->download($target, $targetDir, 'source' === $installationSource);
16222 }
16223
16224
16225
16226
16227
16228
16229
16230 public function remove(PackageInterface $package, $targetDir)
16231 {
16232 $downloader = $this->getDownloaderForInstalledPackage($package);
16233 if ($downloader) {
16234 $downloader->remove($package, $targetDir);
16235 }
16236 }
16237
16238
16239
16240
16241
16242
16243
16244
16245 protected function resolvePackageInstallPreference(PackageInterface $package)
16246 {
16247 foreach ($this->packagePreferences as $pattern => $preference) {
16248 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
16249 if (preg_match($pattern, $package->getName())) {
16250 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
16251 return 'dist';
16252 }
16253
16254 return 'source';
16255 }
16256 }
16257
16258 return $package->isDev() ? 'source' : 'dist';
16259 }
16260 }
16261 <?php
16262
16263
16264
16265
16266
16267
16268
16269
16270
16271
16272
16273 namespace Composer\Downloader;
16274
16275 use Composer\Package\PackageInterface;
16276
16277
16278
16279
16280
16281
16282
16283 interface DownloaderInterface
16284 {
16285
16286
16287
16288
16289
16290 public function getInstallationSource();
16291
16292
16293
16294
16295
16296
16297
16298 public function download(PackageInterface $package, $path);
16299
16300
16301
16302
16303
16304
16305
16306
16307 public function update(PackageInterface $initial, PackageInterface $target, $path);
16308
16309
16310
16311
16312
16313
16314
16315 public function remove(PackageInterface $package, $path);
16316
16317
16318
16319
16320
16321
16322
16323 public function setOutputProgress($outputProgress);
16324 }
16325 <?php
16326
16327
16328
16329
16330
16331
16332
16333
16334
16335
16336
16337 namespace Composer\Downloader;
16338
16339 use Composer\Package\PackageInterface;
16340
16341
16342
16343
16344
16345
16346 interface DvcsDownloaderInterface
16347 {
16348
16349
16350
16351
16352
16353
16354
16355 public function getUnpushedChanges(PackageInterface $package, $path);
16356 }
16357 <?php
16358
16359
16360
16361
16362
16363
16364
16365
16366
16367
16368
16369 namespace Composer\Downloader;
16370
16371 use Composer\Config;
16372 use Composer\Cache;
16373 use Composer\Factory;
16374 use Composer\IO\IOInterface;
16375 use Composer\IO\NullIO;
16376 use Composer\Package\Comparer\Comparer;
16377 use Composer\Package\PackageInterface;
16378 use Composer\Package\Version\VersionParser;
16379 use Composer\Plugin\PluginEvents;
16380 use Composer\Plugin\PreFileDownloadEvent;
16381 use Composer\EventDispatcher\EventDispatcher;
16382 use Composer\Util\Filesystem;
16383 use Composer\Util\RemoteFilesystem;
16384 use Composer\Util\Url as UrlUtil;
16385
16386
16387
16388
16389
16390
16391
16392
16393
16394 class FileDownloader implements DownloaderInterface, ChangeReportInterface
16395 {
16396 protected $io;
16397 protected $config;
16398 protected $rfs;
16399 protected $filesystem;
16400 protected $cache;
16401 protected $outputProgress = true;
16402 private $lastCacheWrites = array();
16403 private $eventDispatcher;
16404
16405
16406
16407
16408
16409
16410
16411
16412
16413
16414
16415 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
16416 {
16417 $this->io = $io;
16418 $this->config = $config;
16419 $this->eventDispatcher = $eventDispatcher;
16420 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
16421 $this->filesystem = $filesystem ?: new Filesystem();
16422 $this->cache = $cache;
16423
16424 if ($this->cache && $this->cache->gcIsNecessary()) {
16425 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
16426 }
16427 }
16428
16429
16430
16431
16432 public function getInstallationSource()
16433 {
16434 return 'dist';
16435 }
16436
16437
16438
16439
16440 public function download(PackageInterface $package, $path, $output = true)
16441 {
16442 if (!$package->getDistUrl()) {
16443 throw new \InvalidArgumentException('The given package is missing url information');
16444 }
16445
16446 if ($output) {
16447 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
16448 }
16449
16450 $urls = $package->getDistUrls();
16451 while ($url = array_shift($urls)) {
16452 try {
16453 $fileName = $this->doDownload($package, $path, $url);
16454 break;
16455 } catch (\Exception $e) {
16456 if ($this->io->isDebug()) {
16457 $this->io->writeError('');
16458 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
16459 } elseif (count($urls)) {
16460 $this->io->writeError('');
16461 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
16462 }
16463
16464 if (!count($urls)) {
16465 throw $e;
16466 }
16467 }
16468 }
16469
16470 if ($output) {
16471 $this->io->writeError('');
16472 }
16473
16474 return $fileName;
16475 }
16476
16477 protected function doDownload(PackageInterface $package, $path, $url)
16478 {
16479 $this->filesystem->emptyDirectory($path);
16480
16481 $fileName = $this->getFileName($package, $path);
16482
16483 $processedUrl = $this->processUrl($package, $url);
16484 $origin = RemoteFilesystem::getOrigin($processedUrl);
16485
16486 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
16487 if ($this->eventDispatcher) {
16488 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
16489 }
16490 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
16491
16492 try {
16493 $checksum = $package->getDistSha1Checksum();
16494 $cacheKey = $this->getCacheKey($package, $processedUrl);
16495
16496
16497  if ($this->cache && (!$checksum || $checksum === $this->cache->sha1($cacheKey)) && $this->cache->copyTo($cacheKey, $fileName)) {
16498 $this->io->writeError('Loading from cache', false);
16499 } else {
16500
16501  if (!$this->outputProgress) {
16502 $this->io->writeError('Downloading', false);
16503 }
16504
16505
16506  $retries = 3;
16507 while ($retries--) {
16508 try {
16509 $rfs->copy($origin, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
16510 break;
16511 } catch (TransportException $e) {
16512
16513  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
16514 throw $e;
16515 }
16516 $this->io->writeError('');
16517 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
16518 usleep(500000);
16519 }
16520 }
16521
16522 if (!$this->outputProgress) {
16523 $this->io->writeError(' (<comment>100%</comment>)', false);
16524 }
16525
16526 if ($this->cache) {
16527 $this->lastCacheWrites[$package->getName()] = $cacheKey;
16528 $this->cache->copyFrom($cacheKey, $fileName);
16529 }
16530 }
16531
16532 if (!file_exists($fileName)) {
16533 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
16534 .' directory is writable and you have internet connectivity');
16535 }
16536
16537 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
16538 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
16539 }
16540 } catch (\Exception $e) {
16541
16542  $this->filesystem->removeDirectory($path);
16543 $this->clearLastCacheWrite($package);
16544 throw $e;
16545 }
16546
16547 return $fileName;
16548 }
16549
16550
16551
16552
16553 public function setOutputProgress($outputProgress)
16554 {
16555 $this->outputProgress = $outputProgress;
16556
16557 return $this;
16558 }
16559
16560 protected function clearLastCacheWrite(PackageInterface $package)
16561 {
16562 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
16563 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
16564 unset($this->lastCacheWrites[$package->getName()]);
16565 }
16566 }
16567
16568
16569
16570
16571 public function update(PackageInterface $initial, PackageInterface $target, $path)
16572 {
16573 $name = $target->getName();
16574 $from = $initial->getFullPrettyVersion();
16575 $to = $target->getFullPrettyVersion();
16576
16577 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
16578 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
16579
16580 $this->remove($initial, $path, false);
16581 $this->download($target, $path, false);
16582
16583 $this->io->writeError('');
16584 }
16585
16586
16587
16588
16589 public function remove(PackageInterface $package, $path, $output = true)
16590 {
16591 if ($output) {
16592 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
16593 }
16594 if (!$this->filesystem->removeDirectory($path)) {
16595 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
16596 }
16597 }
16598
16599
16600
16601
16602
16603
16604
16605
16606 protected function getFileName(PackageInterface $package, $path)
16607 {
16608 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
16609 }
16610
16611
16612
16613
16614
16615
16616
16617
16618
16619 protected function processUrl(PackageInterface $package, $url)
16620 {
16621 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
16622 throw new \RuntimeException('You must enable the openssl extension to download files via https');
16623 }
16624
16625 if ($package->getDistReference()) {
16626 $url = UrlUtil::updateDistReference($this->config, $url, $package->getDistReference());
16627 }
16628
16629 return $url;
16630 }
16631
16632 private function getCacheKey(PackageInterface $package, $processedUrl)
16633 {
16634
16635  
16636  
16637  
16638  $cacheKey = sha1($processedUrl);
16639
16640 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
16641 }
16642
16643
16644
16645
16646
16647 public function getLocalChanges(PackageInterface $package, $targetDir)
16648 {
16649 $prevIO = $this->io;
16650 $prevProgress = $this->outputProgress;
16651
16652 $this->io = new NullIO;
16653 $this->io->loadConfiguration($this->config);
16654 $this->outputProgress = false;
16655 $e = null;
16656
16657 try {
16658 $this->download($package, $targetDir.'_compare', false);
16659
16660 $comparer = new Comparer();
16661 $comparer->setSource($targetDir.'_compare');
16662 $comparer->setUpdate($targetDir);
16663 $comparer->doCompare();
16664 $output = $comparer->getChanged(true, true);
16665 $this->filesystem->removeDirectory($targetDir.'_compare');
16666 } catch (\Exception $e) {
16667 }
16668
16669 $this->io = $prevIO;
16670 $this->outputProgress = $prevProgress;
16671
16672 if ($e) {
16673 throw $e;
16674 }
16675
16676 return trim($output);
16677 }
16678 }
16679 <?php
16680
16681
16682
16683
16684
16685
16686
16687
16688
16689
16690
16691 namespace Composer\Downloader;
16692
16693
16694
16695
16696
16697
16698 class FilesystemException extends \Exception
16699 {
16700 public function __construct($message = '', $code = 0, \Exception $previous = null)
16701 {
16702 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
16703 }
16704 }
16705 <?php
16706
16707
16708
16709
16710
16711
16712
16713
16714
16715
16716
16717 namespace Composer\Downloader;
16718
16719 use Composer\Package\PackageInterface;
16720 use Composer\Util\ProcessExecutor;
16721
16722
16723
16724
16725 class FossilDownloader extends VcsDownloader
16726 {
16727
16728
16729
16730 public function doDownload(PackageInterface $package, $path, $url)
16731 {
16732
16733  $this->config->prohibitUrlByConfig($url, $this->io);
16734
16735 $url = ProcessExecutor::escape($url);
16736 $ref = ProcessExecutor::escape($package->getSourceReference());
16737 $repoFile = $path . '.fossil';
16738 $this->io->writeError("Cloning ".$package->getSourceReference());
16739 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
16740 if (0 !== $this->process->execute($command, $ignoredOutput)) {
16741 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16742 }
16743 $command = sprintf('fossil open %s --nested', ProcessExecutor::escape($repoFile));
16744 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16745 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16746 }
16747 $command = sprintf('fossil update %s', $ref);
16748 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16749 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16750 }
16751 }
16752
16753
16754
16755
16756 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16757 {
16758
16759  $this->config->prohibitUrlByConfig($url, $this->io);
16760
16761 $url = ProcessExecutor::escape($url);
16762 $ref = ProcessExecutor::escape($target->getSourceReference());
16763 $this->io->writeError(" Updating to ".$target->getSourceReference());
16764
16765 if (!$this->hasMetadataRepository($path)) {
16766 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16767 }
16768
16769 $command = sprintf('fossil pull && fossil up %s', $ref);
16770 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
16771 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16772 }
16773 }
16774
16775
16776
16777
16778 public function getLocalChanges(PackageInterface $package, $path)
16779 {
16780 if (!$this->hasMetadataRepository($path)) {
16781 return null;
16782 }
16783
16784 $this->process->execute('fossil changes', $output, realpath($path));
16785
16786 return trim($output) ?: null;
16787 }
16788
16789
16790
16791
16792 protected function getCommitLogs($fromReference, $toReference, $path)
16793 {
16794 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', ProcessExecutor::escape($toReference));
16795
16796 if (0 !== $this->process->execute($command, $output, realpath($path))) {
16797 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16798 }
16799
16800 $log = '';
16801 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
16802
16803 foreach ($this->process->splitLines($output) as $line) {
16804 if (preg_match($match, $line)) {
16805 break;
16806 }
16807 $log .= $line;
16808 }
16809
16810 return $log;
16811 }
16812
16813
16814
16815
16816 protected function hasMetadataRepository($path)
16817 {
16818 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
16819 }
16820 }
16821 <?php
16822
16823
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833 namespace Composer\Downloader;
16834
16835 use Composer\Config;
16836 use Composer\IO\IOInterface;
16837 use Composer\Package\PackageInterface;
16838 use Composer\Util\Filesystem;
16839 use Composer\Util\Git as GitUtil;
16840 use Composer\Util\Platform;
16841 use Composer\Util\ProcessExecutor;
16842 use Composer\Cache;
16843
16844
16845
16846
16847 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
16848 {
16849 private $hasStashedChanges = false;
16850 private $hasDiscardedChanges = false;
16851 private $gitUtil;
16852
16853 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
16854 {
16855 parent::__construct($io, $config, $process, $fs);
16856 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
16857 }
16858
16859
16860
16861
16862 public function doDownload(PackageInterface $package, $path, $url)
16863 {
16864 GitUtil::cleanEnv();
16865 $path = $this->normalizePath($path);
16866 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
16867 $ref = $package->getSourceReference();
16868 $flag = Platform::isWindows() ? '/D ' : '';
16869
16870
16871  $gitVersion = $this->gitUtil->getVersion();
16872 $msg = "Cloning ".$this->getShortHash($ref);
16873
16874 $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%';
16875 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=') && Cache::isUsable($cachePath)) {
16876 $this->io->writeError('', true, IOInterface::DEBUG);
16877 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
16878 try {
16879 if (!$this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref)) {
16880 $this->io->writeError('<error>Failed to update '.$url.' in cache, package installation for '.$package->getPrettyName().' might fail.</error>');
16881 }
16882 if (is_dir($cachePath)) {
16883 $command =
16884 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% '
16885 . '&& cd '.$flag.'%path% '
16886 . '&& git remote set-url origin %sanitizedUrl% && git remote add composer %sanitizedUrl%';
16887 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
16888 }
16889 } catch (\RuntimeException $e) {
16890 if (0 === strpos(get_class($e), 'PHPUnit')) {
16891 throw $e;
16892 }
16893 }
16894 }
16895 $this->io->writeError($msg);
16896
16897 $commandCallable = function ($url) use ($path, $command, $cachePath) {
16898 return str_replace(
16899 array('%url%', '%path%', '%cachePath%', '%sanitizedUrl%'),
16900 array(
16901 ProcessExecutor::escape($url),
16902 ProcessExecutor::escape($path),
16903 ProcessExecutor::escape($cachePath),
16904 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url)),
16905 ),
16906 $command
16907 );
16908 };
16909
16910 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
16911 if ($url !== $package->getSourceUrl()) {
16912 $this->updateOriginUrl($path, $package->getSourceUrl());
16913 } else {
16914 $this->setPushUrl($path, $url);
16915 }
16916
16917 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
16918 if ($package->getDistReference() === $package->getSourceReference()) {
16919 $package->setDistReference($newRef);
16920 }
16921 $package->setSourceReference($newRef);
16922 }
16923 }
16924
16925
16926
16927
16928 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16929 {
16930 GitUtil::cleanEnv();
16931 if (!$this->hasMetadataRepository($path)) {
16932 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16933 }
16934
16935 $updateOriginUrl = false;
16936 if (
16937 0 === $this->process->execute('git remote -v', $output, $path)
16938 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
16939 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
16940 ) {
16941 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
16942 $updateOriginUrl = true;
16943 }
16944 }
16945
16946 $ref = $target->getSourceReference();
16947 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
16948 $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';
16949
16950 $commandCallable = function ($url) use ($command, $ref) {
16951 return sprintf(
16952 $command,
16953 ProcessExecutor::escape($url),
16954 ProcessExecutor::escape($ref.'^{commit}'),
16955 ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url))
16956 );
16957 };
16958
16959 $this->gitUtil->runCommand($commandCallable, $url, $path);
16960 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
16961 if ($target->getDistReference() === $target->getSourceReference()) {
16962 $target->setDistReference($newRef);
16963 }
16964 $target->setSourceReference($newRef);
16965 }
16966
16967 if ($updateOriginUrl) {
16968 $this->updateOriginUrl($path, $target->getSourceUrl());
16969 }
16970 }
16971
16972
16973
16974
16975 public function getLocalChanges(PackageInterface $package, $path)
16976 {
16977 GitUtil::cleanEnv();
16978 if (!$this->hasMetadataRepository($path)) {
16979 return;
16980 }
16981
16982 $command = 'git status --porcelain --untracked-files=no';
16983 if (0 !== $this->process->execute($command, $output, $path)) {
16984 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
16985 }
16986
16987 return trim($output) ?: null;
16988 }
16989
16990 public function getUnpushedChanges(PackageInterface $package, $path)
16991 {
16992 GitUtil::cleanEnv();
16993 $path = $this->normalizePath($path);
16994 if (!$this->hasMetadataRepository($path)) {
16995 return;
16996 }
16997
16998 $command = 'git show-ref --head -d';
16999 if (0 !== $this->process->execute($command, $output, $path)) {
17000 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17001 }
17002
17003 $refs = trim($output);
17004 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
17005
17006  return;
17007 }
17008
17009 $headRef = $match[1];
17010 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
17011
17012  return;
17013 }
17014
17015
17016  $branch = $matches[1][0];
17017 $unpushedChanges = null;
17018
17019
17020  for ($i = 0; $i <= 1; $i++) {
17021
17022  foreach ($matches[1] as $candidate) {
17023 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
17024 $branch = $candidate;
17025 $remoteBranch = $match[1];
17026 break;
17027 }
17028 }
17029
17030
17031  
17032  
17033  if (!isset($remoteBranch)) {
17034 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
17035 } else {
17036 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
17037 if (0 !== $this->process->execute($command, $output, $path)) {
17038 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17039 }
17040
17041 $unpushedChanges = trim($output) ?: null;
17042 }
17043
17044
17045  
17046  if ($unpushedChanges && $i === 0) {
17047 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
17048 }
17049
17050
17051  if (!$unpushedChanges) {
17052 break;
17053 }
17054 }
17055
17056 return $unpushedChanges;
17057 }
17058
17059
17060
17061
17062 protected function cleanChanges(PackageInterface $package, $path, $update)
17063 {
17064 GitUtil::cleanEnv();
17065 $path = $this->normalizePath($path);
17066
17067 $unpushed = $this->getUnpushedChanges($package, $path);
17068 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
17069 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
17070 }
17071
17072 if (!$changes = $this->getLocalChanges($package, $path)) {
17073 return;
17074 }
17075
17076 if (!$this->io->isInteractive()) {
17077 $discardChanges = $this->config->get('discard-changes');
17078 if (true === $discardChanges) {
17079 return $this->discardChanges($path);
17080 }
17081 if ('stash' === $discardChanges) {
17082 if (!$update) {
17083 return parent::cleanChanges($package, $path, $update);
17084 }
17085
17086 return $this->stashChanges($path);
17087 }
17088
17089 return parent::cleanChanges($package, $path, $update);
17090 }
17091
17092 $changes = array_map(function ($elem) {
17093 return '    '.$elem;
17094 }, preg_split('{\s*\r?\n\s*}', $changes));
17095 $this->io->writeError('    <error>The package has modified files:</error>');
17096 $this->io->writeError(array_slice($changes, 0, 10));
17097 if (count($changes) > 10) {
17098 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
17099 }
17100
17101 while (true) {
17102 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
17103 case 'y':
17104 $this->discardChanges($path);
17105 break 2;
17106
17107 case 's':
17108 if (!$update) {
17109 goto help;
17110 }
17111
17112 $this->stashChanges($path);
17113 break 2;
17114
17115 case 'n':
17116 throw new \RuntimeException('Update aborted');
17117
17118 case 'v':
17119 $this->io->writeError($changes);
17120 break;
17121
17122 case 'd':
17123 $this->viewDiff($path);
17124 break;
17125
17126 case '?':
17127 default:
17128 help:
17129 $this->io->writeError(array(
17130 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
17131 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
17132 '    v - view modified files',
17133 '    d - view local modifications (diff)',
17134 ));
17135 if ($update) {
17136 $this->io->writeError('    s - stash changes and try to reapply them after the update');
17137 }
17138 $this->io->writeError('    ? - print help');
17139 break;
17140 }
17141 }
17142 }
17143
17144
17145
17146
17147 protected function reapplyChanges($path)
17148 {
17149 $path = $this->normalizePath($path);
17150 if ($this->hasStashedChanges) {
17151 $this->hasStashedChanges = false;
17152 $this->io->writeError('    <info>Re-applying stashed changes</info>');
17153 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
17154 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
17155 }
17156 }
17157
17158 $this->hasDiscardedChanges = false;
17159 }
17160
17161
17162
17163
17164
17165
17166
17167
17168
17169
17170
17171 protected function updateToCommit($path, $reference, $branch, $date)
17172 {
17173 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
17174
17175
17176  
17177  
17178  
17179  
17180  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
17181 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
17182
17183 $branches = null;
17184 if (0 === $this->process->execute('git branch -r', $output, $path)) {
17185 $branches = $output;
17186 }
17187
17188
17189  $gitRef = $reference;
17190 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
17191 && $branches
17192 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
17193 ) {
17194 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
17195 if (0 === $this->process->execute($command, $output, $path)) {
17196 return;
17197 }
17198 }
17199
17200
17201  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
17202
17203  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
17204 $branch = 'v' . $branch;
17205 }
17206
17207 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
17208 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
17209 if (0 === $this->process->execute($command, $output, $path)
17210 || 0 === $this->process->execute($fallbackCommand, $output, $path)
17211 ) {
17212 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
17213 if (0 === $this->process->execute($command, $output, $path)) {
17214 return;
17215 }
17216 }
17217 }
17218
17219 $command = sprintf($template, ProcessExecutor::escape($gitRef));
17220 if (0 === $this->process->execute($command, $output, $path)) {
17221 return;
17222 }
17223
17224
17225  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
17226 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
17227 }
17228
17229 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
17230 }
17231
17232 protected function updateOriginUrl($path, $url)
17233 {
17234 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
17235 $this->setPushUrl($path, $url);
17236 }
17237
17238 protected function setPushUrl($path, $url)
17239 {
17240
17241  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
17242 $protocols = $this->config->get('github-protocols');
17243 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
17244 if (!in_array('ssh', $protocols, true)) {
17245 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
17246 }
17247 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
17248 $this->process->execute($cmd, $ignoredOutput, $path);
17249 }
17250 }
17251
17252
17253
17254
17255 protected function getCommitLogs($fromReference, $toReference, $path)
17256 {
17257 $path = $this->normalizePath($path);
17258 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
17259
17260 if (0 !== $this->process->execute($command, $output, $path)) {
17261 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17262 }
17263
17264 return $output;
17265 }
17266
17267
17268
17269
17270
17271 protected function discardChanges($path)
17272 {
17273 $path = $this->normalizePath($path);
17274 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
17275 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
17276 }
17277
17278 $this->hasDiscardedChanges = true;
17279 }
17280
17281
17282
17283
17284
17285 protected function stashChanges($path)
17286 {
17287 $path = $this->normalizePath($path);
17288 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
17289 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
17290 }
17291
17292 $this->hasStashedChanges = true;
17293 }
17294
17295
17296
17297
17298
17299 protected function viewDiff($path)
17300 {
17301 $path = $this->normalizePath($path);
17302 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
17303 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
17304 }
17305
17306 $this->io->writeError($output);
17307 }
17308
17309 protected function normalizePath($path)
17310 {
17311 if (Platform::isWindows() && strlen($path) > 0) {
17312 $basePath = $path;
17313 $removed = array();
17314
17315 while (!is_dir($basePath) && $basePath !== '\\') {
17316 array_unshift($removed, basename($basePath));
17317 $basePath = dirname($basePath);
17318 }
17319
17320 if ($basePath === '\\') {
17321 return $path;
17322 }
17323
17324 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
17325 }
17326
17327 return $path;
17328 }
17329
17330
17331
17332
17333 protected function hasMetadataRepository($path)
17334 {
17335 $path = $this->normalizePath($path);
17336
17337 return is_dir($path.'/.git');
17338 }
17339
17340 protected function getShortHash($reference)
17341 {
17342 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
17343 return substr($reference, 0, 10);
17344 }
17345
17346 return $reference;
17347 }
17348 }
17349 <?php
17350
17351
17352
17353
17354
17355
17356
17357
17358
17359
17360
17361 namespace Composer\Downloader;
17362
17363 use Composer\Config;
17364 use Composer\Cache;
17365 use Composer\EventDispatcher\EventDispatcher;
17366 use Composer\Package\PackageInterface;
17367 use Composer\Util\Platform;
17368 use Composer\Util\ProcessExecutor;
17369 use Composer\Util\RemoteFilesystem;
17370 use Composer\IO\IOInterface;
17371
17372
17373
17374
17375
17376
17377 class GzipDownloader extends ArchiveDownloader
17378 {
17379 protected $process;
17380
17381 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17382 {
17383 $this->process = $process ?: new ProcessExecutor($io);
17384 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17385 }
17386
17387 protected function extract($file, $path)
17388 {
17389 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
17390
17391
17392  if (!Platform::isWindows()) {
17393 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
17394
17395 if (0 === $this->process->execute($command, $ignoredOutput)) {
17396 return;
17397 }
17398
17399 if (extension_loaded('zlib')) {
17400
17401  $this->extractUsingExt($file, $targetFilepath);
17402
17403 return;
17404 }
17405
17406 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17407 throw new \RuntimeException($processError);
17408 }
17409
17410
17411  $this->extractUsingExt($file, $targetFilepath);
17412 }
17413
17414
17415
17416
17417 protected function getFileName(PackageInterface $package, $path)
17418 {
17419 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17420 }
17421
17422 private function extractUsingExt($file, $targetFilepath)
17423 {
17424 $archiveFile = gzopen($file, 'rb');
17425 $targetFile = fopen($targetFilepath, 'wb');
17426 while ($string = gzread($archiveFile, 4096)) {
17427 fwrite($targetFile, $string, Platform::strlen($string));
17428 }
17429 gzclose($archiveFile);
17430 fclose($targetFile);
17431 }
17432 }
17433 <?php
17434
17435
17436
17437
17438
17439
17440
17441
17442
17443
17444
17445 namespace Composer\Downloader;
17446
17447 use Composer\Package\PackageInterface;
17448 use Composer\Util\ProcessExecutor;
17449 use Composer\Util\Hg as HgUtils;
17450
17451
17452
17453
17454 class HgDownloader extends VcsDownloader
17455 {
17456
17457
17458
17459 public function doDownload(PackageInterface $package, $path, $url)
17460 {
17461 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
17462
17463 $cloneCommand = function ($url) use ($path) {
17464 return sprintf('hg clone %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($path));
17465 };
17466
17467 $hgUtils->runCommand($cloneCommand, $url, $path);
17468
17469 $ref = ProcessExecutor::escape($package->getSourceReference());
17470 $command = sprintf('hg up %s', $ref);
17471 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
17472 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17473 }
17474 }
17475
17476
17477
17478
17479 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
17480 {
17481 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
17482
17483 $ref = $target->getSourceReference();
17484 $this->io->writeError(" Updating to ".$target->getSourceReference());
17485
17486 if (!$this->hasMetadataRepository($path)) {
17487 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
17488 }
17489
17490 $command = function ($url) use ($ref) {
17491 return sprintf('hg pull %s && hg up %s', ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
17492 };
17493
17494 $hgUtils->runCommand($command, $url, $path);
17495 }
17496
17497
17498
17499
17500 public function getLocalChanges(PackageInterface $package, $path)
17501 {
17502 if (!is_dir($path.'/.hg')) {
17503 return null;
17504 }
17505
17506 $this->process->execute('hg st', $output, realpath($path));
17507
17508 return trim($output) ?: null;
17509 }
17510
17511
17512
17513
17514 protected function getCommitLogs($fromReference, $toReference, $path)
17515 {
17516 $command = sprintf('hg log -r %s:%s --style compact', ProcessExecutor::escape($fromReference), ProcessExecutor::escape($toReference));
17517
17518 if (0 !== $this->process->execute($command, $output, realpath($path))) {
17519 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17520 }
17521
17522 return $output;
17523 }
17524
17525
17526
17527
17528 protected function hasMetadataRepository($path)
17529 {
17530 return is_dir($path . '/.hg');
17531 }
17532 }
17533 <?php
17534
17535
17536
17537
17538
17539
17540
17541
17542
17543
17544
17545 namespace Composer\Downloader;
17546
17547 use Composer\Package\Archiver\ArchivableFilesFinder;
17548 use Composer\Package\Dumper\ArrayDumper;
17549 use Composer\Package\PackageInterface;
17550 use Composer\Package\Version\VersionGuesser;
17551 use Composer\Package\Version\VersionParser;
17552 use Composer\Util\Platform;
17553 use Composer\Util\ProcessExecutor;
17554 use Composer\Util\Filesystem as ComposerFilesystem;
17555 use Symfony\Component\Filesystem\Exception\IOException;
17556 use Symfony\Component\Filesystem\Filesystem;
17557
17558
17559
17560
17561
17562
17563
17564 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
17565 {
17566 const STRATEGY_SYMLINK = 10;
17567 const STRATEGY_MIRROR = 20;
17568
17569
17570
17571
17572 public function download(PackageInterface $package, $path, $output = true)
17573 {
17574 $url = $package->getDistUrl();
17575 $realUrl = realpath($url);
17576 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
17577 throw new \RuntimeException(sprintf(
17578 'Source path "%s" is not found for package %s',
17579 $url,
17580 $package->getName()
17581 ));
17582 }
17583
17584 if (realpath($path) === $realUrl) {
17585 if ($output) {
17586 $this->io->writeError(sprintf(
17587 '  - Installing <info>%s</info> (<comment>%s</comment>): Source already present',
17588 $package->getName(),
17589 $package->getFullPrettyVersion()
17590 ));
17591 }
17592
17593 return;
17594 }
17595
17596 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
17597
17598  
17599  
17600  
17601  throw new \RuntimeException(sprintf(
17602 'Package %s cannot install to "%s" inside its source at "%s"',
17603 $package->getName(),
17604 realpath($path),
17605 $realUrl
17606 ));
17607 }
17608
17609
17610  $transportOptions = $package->getTransportOptions() + array('symlink' => null, 'relative' => true);
17611
17612
17613  $currentStrategy = self::STRATEGY_SYMLINK;
17614 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
17615
17616 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
17617 if ($mirrorPathRepos) {
17618 $currentStrategy = self::STRATEGY_MIRROR;
17619 }
17620
17621 if (true === $transportOptions['symlink']) {
17622 $currentStrategy = self::STRATEGY_SYMLINK;
17623 $allowedStrategies = array(self::STRATEGY_SYMLINK);
17624 } elseif (false === $transportOptions['symlink']) {
17625 $currentStrategy = self::STRATEGY_MIRROR;
17626 $allowedStrategies = array(self::STRATEGY_MIRROR);
17627 }
17628
17629
17630  if (Platform::isWindows() && self::STRATEGY_SYMLINK === $currentStrategy && !$this->safeJunctions()) {
17631 $currentStrategy = self::STRATEGY_MIRROR;
17632 $allowedStrategies = array(self::STRATEGY_MIRROR);
17633 }
17634
17635 $fileSystem = new Filesystem();
17636 $this->filesystem->removeDirectory($path);
17637
17638 if ($output) {
17639 $this->io->writeError(sprintf(
17640 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
17641 $package->getName(),
17642 $package->getFullPrettyVersion()
17643 ), false);
17644 }
17645
17646 $isFallback = false;
17647 if (self::STRATEGY_SYMLINK == $currentStrategy) {
17648 try {
17649 if (Platform::isWindows()) {
17650
17651  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
17652 $this->filesystem->junction($realUrl, $path);
17653 } else {
17654 $absolutePath = $path;
17655 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
17656 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
17657 }
17658 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
17659 $path = rtrim($path, "/");
17660 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
17661 if ($transportOptions['relative']) {
17662 $fileSystem->symlink($shortestPath, $path);
17663 } else {
17664 $fileSystem->symlink($realUrl, $path);
17665 }
17666 }
17667 } catch (IOException $e) {
17668 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
17669 $this->io->writeError('');
17670 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
17671 $currentStrategy = self::STRATEGY_MIRROR;
17672 $isFallback = true;
17673 } else {
17674 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
17675 }
17676 }
17677 }
17678
17679
17680  if (self::STRATEGY_MIRROR == $currentStrategy) {
17681 $fs = new ComposerFilesystem();
17682 $realUrl = $fs->normalizePath($realUrl);
17683
17684 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
17685 $iterator = new ArchivableFilesFinder($realUrl, array());
17686 $fileSystem->mirror($realUrl, $path, $iterator);
17687 }
17688
17689 $this->io->writeError('');
17690 }
17691
17692
17693
17694
17695 public function remove(PackageInterface $package, $path, $output = true)
17696 {
17697 $realUrl = realpath($package->getDistUrl());
17698
17699 if (realpath($path) === $realUrl) {
17700 if ($output) {
17701 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>), source is still present in $path");
17702 }
17703
17704 return;
17705 }
17706
17707
17708
17709
17710
17711
17712 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
17713 if ($output) {
17714 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
17715 }
17716 if (!$this->filesystem->removeJunction($path)) {
17717 $this->io->writeError("    <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>");
17718 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
17719 }
17720 } else {
17721 parent::remove($package, $path, $output);
17722 }
17723 }
17724
17725
17726
17727
17728 public function getVcsReference(PackageInterface $package, $path)
17729 {
17730 $parser = new VersionParser;
17731 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
17732 $dumper = new ArrayDumper;
17733
17734 $packageConfig = $dumper->dump($package);
17735 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
17736 return $packageVersion['commit'];
17737 }
17738 }
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748
17749
17750
17751
17752
17753 private function safeJunctions()
17754 {
17755
17756  return function_exists('proc_open') &&
17757 (PHP_WINDOWS_VERSION_MAJOR > 6 ||
17758 (PHP_WINDOWS_VERSION_MAJOR === 6 && PHP_WINDOWS_VERSION_MINOR >= 1));
17759 }
17760 }
17761 <?php
17762
17763
17764
17765
17766
17767
17768
17769
17770
17771
17772
17773 namespace Composer\Downloader;
17774
17775 use Composer\Util\Filesystem;
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786 class PearPackageExtractor
17787 {
17788 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
17789
17790 private $filesystem;
17791 private $file;
17792
17793 public function __construct($file)
17794 {
17795 if (!is_file($file)) {
17796 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
17797 }
17798
17799 $this->filesystem = new Filesystem();
17800 $this->file = $file;
17801 }
17802
17803
17804
17805
17806
17807
17808
17809
17810
17811
17812 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
17813 {
17814 $extractionPath = $target.'/tarball';
17815
17816 try {
17817 $archive = new \PharData($this->file);
17818 $archive->extractTo($extractionPath, null, true);
17819
17820 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
17821 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
17822 }
17823
17824 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
17825 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
17826 $this->filesystem->removeDirectory($extractionPath);
17827 } catch (\Exception $exception) {
17828 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
17829 }
17830 }
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840
17841 private function copyFiles($files, $source, $target, $roles, $vars)
17842 {
17843 foreach ($files as $file) {
17844 $from = $this->combine($source, $file['from']);
17845 $to = $this->combine($target, $roles[$file['role']]);
17846 $to = $this->combine($to, $file['to']);
17847 $tasks = $file['tasks'];
17848 $this->copyFile($from, $to, $tasks, $vars);
17849 }
17850 }
17851
17852 private function copyFile($from, $to, $tasks, $vars)
17853 {
17854 if (!is_file($from)) {
17855 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
17856 }
17857
17858 $this->filesystem->ensureDirectoryExists(dirname($to));
17859
17860 if (0 == count($tasks)) {
17861 $copied = copy($from, $to);
17862 } else {
17863 $content = file_get_contents($from);
17864 $replacements = array();
17865 foreach ($tasks as $task) {
17866 $pattern = $task['from'];
17867 $varName = $task['to'];
17868 if (isset($vars[$varName])) {
17869 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
17870 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
17871 } else {
17872 $replacements[$pattern] = $vars[$varName];
17873 }
17874 }
17875 }
17876 $content = strtr($content, $replacements);
17877
17878 $copied = file_put_contents($to, $content);
17879 }
17880
17881 if (false === $copied) {
17882 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
17883 }
17884 }
17885
17886
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896 private function buildCopyActions($source, array $roles, $vars)
17897 {
17898
17899 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
17900 if (false === $package) {
17901 throw new \RuntimeException('Package definition file is not valid.');
17902 }
17903
17904 $packageSchemaVersion = $package['version'];
17905 if ('1.0' == $packageSchemaVersion) {
17906 $children = $package->release->filelist->children();
17907 $packageName = (string) $package->name;
17908 $packageVersion = (string) $package->release->version;
17909 $sourceDir = $packageName . '-' . $packageVersion;
17910 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
17911 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
17912 $children = $package->contents->children();
17913 $packageName = (string) $package->name;
17914 $packageVersion = (string) $package->version->release;
17915 $sourceDir = $packageName . '-' . $packageVersion;
17916 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
17917
17918 $namespaces = $package->getNamespaces();
17919 $package->registerXPathNamespace('ns', $namespaces['']);
17920 $releaseNodes = $package->xpath('ns:phprelease');
17921 $this->applyRelease($result, $releaseNodes, $vars);
17922 } else {
17923 throw new \RuntimeException('Unsupported schema version of package definition file.');
17924 }
17925
17926 return $result;
17927 }
17928
17929 private function applyRelease(&$actions, $releaseNodes, $vars)
17930 {
17931 foreach ($releaseNodes as $releaseNode) {
17932 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
17933 if ($requiredOs && $vars['os'] != $requiredOs) {
17934 continue;
17935 }
17936
17937 if ($releaseNode->filelist) {
17938 foreach ($releaseNode->filelist->children() as $action) {
17939 if ('install' == $action->getName()) {
17940 $name = (string) $action['name'];
17941 $as = (string) $action['as'];
17942 if (isset($actions[$name])) {
17943 $actions[$name]['to'] = $as;
17944 }
17945 } elseif ('ignore' == $action->getName()) {
17946 $name = (string) $action['name'];
17947 unset($actions[$name]);
17948 } else {
17949
17950  }
17951 }
17952 }
17953 break;
17954 }
17955 }
17956
17957 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
17958 {
17959 $result = array();
17960
17961
17962  foreach ($children as $child) {
17963
17964 if ($child->getName() == 'dir') {
17965 $dirSource = $this->combine($source, (string) $child['name']);
17966 $dirTarget = $child['baseinstalldir'] ?: $target;
17967 $dirRole = $child['role'] ?: $role;
17968 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
17969 $result = array_merge($result, $dirFiles);
17970 } elseif ($child->getName() == 'file') {
17971 $fileRole = (string) $child['role'] ?: $role;
17972 if (isset($targetRoles[$fileRole])) {
17973 $fileName = (string) ($child['name'] ?: $child[0]); 
17974  $fileSource = $this->combine($source, $fileName);
17975 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
17976 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
17977 $fileTarget = $packageName . '/' . $fileTarget;
17978 }
17979 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
17980 }
17981 }
17982 }
17983
17984 return $result;
17985 }
17986
17987 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
17988 {
17989 $result = array();
17990
17991
17992  foreach ($children as $child) {
17993
17994 if ('dir' == $child->getName()) {
17995 $dirSource = $this->combine($source, $child['name']);
17996 $dirTarget = $child['baseinstalldir'] ?: $target;
17997 $dirRole = $child['role'] ?: $role;
17998 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
17999 $result = array_merge($result, $dirFiles);
18000 } elseif ('file' == $child->getName()) {
18001 $fileRole = (string) $child['role'] ?: $role;
18002 if (isset($targetRoles[$fileRole])) {
18003 $fileSource = $this->combine($source, (string) $child['name']);
18004 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
18005 $fileTasks = array();
18006 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
18007 if ('replace' == $taskNode->getName()) {
18008 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
18009 }
18010 }
18011 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
18012 $fileTarget = $packageName . '/' . $fileTarget;
18013 }
18014 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
18015 }
18016 }
18017 }
18018
18019 return $result;
18020 }
18021
18022 private function combine($left, $right)
18023 {
18024 return rtrim($left, '/') . '/' . ltrim($right, '/');
18025 }
18026 }
18027 <?php
18028
18029
18030
18031
18032
18033
18034
18035
18036
18037
18038
18039 namespace Composer\Downloader;
18040
18041 use Composer\Package\PackageInterface;
18042 use Composer\Repository\VcsRepository;
18043 use Composer\Util\Perforce;
18044
18045
18046
18047
18048 class PerforceDownloader extends VcsDownloader
18049 {
18050
18051 protected $perforce;
18052
18053
18054
18055
18056 public function doDownload(PackageInterface $package, $path, $url)
18057 {
18058 $ref = $package->getSourceReference();
18059 $label = $this->getLabelFromSourceReference($ref);
18060
18061 $this->io->writeError('Cloning ' . $ref);
18062 $this->initPerforce($package, $path, $url);
18063 $this->perforce->setStream($ref);
18064 $this->perforce->p4Login();
18065 $this->perforce->writeP4ClientSpec();
18066 $this->perforce->connectClient();
18067 $this->perforce->syncCodeBase($label);
18068 $this->perforce->cleanupClientSpec();
18069 }
18070
18071 private function getLabelFromSourceReference($ref)
18072 {
18073 $pos = strpos($ref, '@');
18074 if (false !== $pos) {
18075 return substr($ref, $pos + 1);
18076 }
18077
18078 return null;
18079 }
18080
18081 public function initPerforce(PackageInterface $package, $path, $url)
18082 {
18083 if (!empty($this->perforce)) {
18084 $this->perforce->initializePath($path);
18085
18086 return;
18087 }
18088
18089 $repository = $package->getRepository();
18090 $repoConfig = null;
18091 if ($repository instanceof VcsRepository) {
18092 $repoConfig = $this->getRepoConfig($repository);
18093 }
18094 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
18095 }
18096
18097 private function getRepoConfig(VcsRepository $repository)
18098 {
18099 return $repository->getRepoConfig();
18100 }
18101
18102
18103
18104
18105 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
18106 {
18107 $this->doDownload($target, $path, $url);
18108 }
18109
18110
18111
18112
18113 public function getLocalChanges(PackageInterface $package, $path)
18114 {
18115 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
18116 }
18117
18118
18119
18120
18121 protected function getCommitLogs($fromReference, $toReference, $path)
18122 {
18123 return $this->perforce->getCommitLogs($fromReference, $toReference);
18124 }
18125
18126 public function setPerforce($perforce)
18127 {
18128 $this->perforce = $perforce;
18129 }
18130
18131
18132
18133
18134 protected function hasMetadataRepository($path)
18135 {
18136 return true;
18137 }
18138 }
18139 <?php
18140
18141
18142
18143
18144
18145
18146
18147
18148
18149
18150
18151 namespace Composer\Downloader;
18152
18153
18154
18155
18156
18157
18158 class PharDownloader extends ArchiveDownloader
18159 {
18160
18161
18162
18163 protected function extract($file, $path)
18164 {
18165
18166  $archive = new \Phar($file);
18167 $archive->extractTo($path, null, true);
18168
18169
18170
18171
18172
18173 }
18174 }
18175 <?php
18176
18177
18178
18179
18180
18181
18182
18183
18184
18185
18186
18187 namespace Composer\Downloader;
18188
18189 use Composer\Config;
18190 use Composer\Cache;
18191 use Composer\EventDispatcher\EventDispatcher;
18192 use Composer\Util\IniHelper;
18193 use Composer\Util\Platform;
18194 use Composer\Util\ProcessExecutor;
18195 use Composer\Util\RemoteFilesystem;
18196 use Composer\IO\IOInterface;
18197 use RarArchive;
18198
18199
18200
18201
18202
18203
18204
18205
18206 class RarDownloader extends ArchiveDownloader
18207 {
18208 protected $process;
18209
18210 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18211 {
18212 $this->process = $process ?: new ProcessExecutor($io);
18213 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
18214 }
18215
18216 protected function extract($file, $path)
18217 {
18218 $processError = null;
18219
18220
18221  if (!Platform::isWindows()) {
18222 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
18223
18224 if (0 === $this->process->execute($command, $ignoredOutput)) {
18225 return;
18226 }
18227
18228 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
18229 }
18230
18231 if (!class_exists('RarArchive')) {
18232
18233  $iniMessage = IniHelper::getMessage();
18234
18235 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
18236 . $iniMessage . "\n" . $processError;
18237
18238 if (!Platform::isWindows()) {
18239 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
18240 }
18241
18242 throw new \RuntimeException($error);
18243 }
18244
18245 $rarArchive = RarArchive::open($file);
18246
18247 if (false === $rarArchive) {
18248 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
18249 }
18250
18251 $entries = $rarArchive->getEntries();
18252
18253 if (false === $entries) {
18254 throw new \RuntimeException('Could not retrieve RAR archive entries');
18255 }
18256
18257 foreach ($entries as $entry) {
18258 if (false === $entry->extract($path)) {
18259 throw new \RuntimeException('Could not extract entry');
18260 }
18261 }
18262
18263 $rarArchive->close();
18264 }
18265 }
18266 <?php
18267
18268
18269
18270
18271
18272
18273
18274
18275
18276
18277
18278 namespace Composer\Downloader;
18279
18280 use Composer\Package\PackageInterface;
18281 use Composer\Util\Svn as SvnUtil;
18282 use Composer\Repository\VcsRepository;
18283 use Composer\Util\ProcessExecutor;
18284
18285
18286
18287
18288
18289 class SvnDownloader extends VcsDownloader
18290 {
18291 protected $cacheCredentials = true;
18292
18293
18294
18295
18296 public function doDownload(PackageInterface $package, $path, $url)
18297 {
18298 SvnUtil::cleanEnv();
18299 $ref = $package->getSourceReference();
18300
18301 $repo = $package->getRepository();
18302 if ($repo instanceof VcsRepository) {
18303 $repoConfig = $repo->getRepoConfig();
18304 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
18305 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
18306 }
18307 }
18308
18309 $this->io->writeError(" Checking out ".$package->getSourceReference());
18310 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
18311 }
18312
18313
18314
18315
18316 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
18317 {
18318 SvnUtil::cleanEnv();
18319 $ref = $target->getSourceReference();
18320
18321 if (!$this->hasMetadataRepository($path)) {
18322 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
18323 }
18324
18325 $util = new SvnUtil($url, $this->io, $this->config);
18326 $flags = "";
18327 if (version_compare($util->binaryVersion(), '1.7.0', '>=')) {
18328 $flags .= ' --ignore-ancestry';
18329 }
18330
18331 $this->io->writeError(" Checking out " . $ref);
18332 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
18333 }
18334
18335
18336
18337
18338 public function getLocalChanges(PackageInterface $package, $path)
18339 {
18340 if (!$this->hasMetadataRepository($path)) {
18341 return null;
18342 }
18343
18344 $this->process->execute('svn status --ignore-externals', $output, $path);
18345
18346 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
18347 }
18348
18349
18350
18351
18352
18353
18354
18355
18356
18357
18358
18359
18360
18361 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
18362 {
18363 $util = new SvnUtil($baseUrl, $this->io, $this->config);
18364 $util->setCacheCredentials($this->cacheCredentials);
18365 try {
18366 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
18367 } catch (\RuntimeException $e) {
18368 throw new \RuntimeException(
18369 'Package could not be downloaded, '.$e->getMessage()
18370 );
18371 }
18372 }
18373
18374
18375
18376
18377 protected function cleanChanges(PackageInterface $package, $path, $update)
18378 {
18379 if (!$changes = $this->getLocalChanges($package, $path)) {
18380 return;
18381 }
18382
18383 if (!$this->io->isInteractive()) {
18384 if (true === $this->config->get('discard-changes')) {
18385 return $this->discardChanges($path);
18386 }
18387
18388 return parent::cleanChanges($package, $path, $update);
18389 }
18390
18391 $changes = array_map(function ($elem) {
18392 return '    '.$elem;
18393 }, preg_split('{\s*\r?\n\s*}', $changes));
18394 $countChanges = count($changes);
18395 $this->io->writeError(sprintf('    <error>The package has modified file%s:</error>', $countChanges === 1 ? '' : 's'));
18396 $this->io->writeError(array_slice($changes, 0, 10));
18397 if ($countChanges > 10) {
18398 $remainingChanges = $countChanges - 10;
18399 $this->io->writeError(
18400 sprintf(
18401 '    <info>'.$remainingChanges.' more file%s modified, choose "v" to view the full list</info>',
18402 $remainingChanges === 1 ? '' : 's'
18403 )
18404 );
18405 }
18406
18407 while (true) {
18408 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
18409 case 'y':
18410 $this->discardChanges($path);
18411 break 2;
18412
18413 case 'n':
18414 throw new \RuntimeException('Update aborted');
18415
18416 case 'v':
18417 $this->io->writeError($changes);
18418 break;
18419
18420 case '?':
18421 default:
18422 $this->io->writeError(array(
18423 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
18424 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
18425 '    v - view modified files',
18426 '    ? - print help',
18427 ));
18428 break;
18429 }
18430 }
18431 }
18432
18433
18434
18435
18436 protected function getCommitLogs($fromReference, $toReference, $path)
18437 {
18438 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
18439
18440  $command = sprintf('svn info --non-interactive --xml %s', ProcessExecutor::escape($path));
18441 if (0 !== $this->process->execute($command, $output, $path)) {
18442 throw new \RuntimeException(
18443 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
18444 );
18445 }
18446
18447 $urlPattern = '#<url>(.*)</url>#';
18448 if (preg_match($urlPattern, $output, $matches)) {
18449 $baseUrl = $matches[1];
18450 } else {
18451 throw new \RuntimeException(
18452 'Unable to determine svn url for path '. $path
18453 );
18454 }
18455
18456
18457  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
18458 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
18459
18460 $command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision));
18461
18462 $util = new SvnUtil($baseUrl, $this->io, $this->config);
18463 $util->setCacheCredentials($this->cacheCredentials);
18464 try {
18465 return $util->executeLocal($command, $path, null, $this->io->isVerbose());
18466 } catch (\RuntimeException $e) {
18467 throw new \RuntimeException(
18468 'Failed to execute ' . $command . "\n\n".$e->getMessage()
18469 );
18470 }
18471 }
18472
18473 return "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
18474 }
18475
18476 protected function discardChanges($path)
18477 {
18478 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
18479 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
18480 }
18481 }
18482
18483
18484
18485
18486 protected function hasMetadataRepository($path)
18487 {
18488 return is_dir($path.'/.svn');
18489 }
18490 }
18491 <?php
18492
18493
18494
18495
18496
18497
18498
18499
18500
18501
18502
18503 namespace Composer\Downloader;
18504
18505
18506
18507
18508
18509
18510 class TarDownloader extends ArchiveDownloader
18511 {
18512
18513
18514
18515 protected function extract($file, $path)
18516 {
18517
18518  $archive = new \PharData($file);
18519 $archive->extractTo($path, null, true);
18520 }
18521 }
18522 <?php
18523
18524
18525
18526
18527
18528
18529
18530
18531
18532
18533
18534 namespace Composer\Downloader;
18535
18536
18537
18538
18539 class TransportException extends \RuntimeException
18540 {
18541 protected $headers;
18542 protected $response;
18543 protected $statusCode;
18544
18545 public function setHeaders($headers)
18546 {
18547 $this->headers = $headers;
18548 }
18549
18550 public function getHeaders()
18551 {
18552 return $this->headers;
18553 }
18554
18555 public function setResponse($response)
18556 {
18557 $this->response = $response;
18558 }
18559
18560 public function getResponse()
18561 {
18562 return $this->response;
18563 }
18564
18565 public function setStatusCode($statusCode)
18566 {
18567 $this->statusCode = $statusCode;
18568 }
18569
18570 public function getStatusCode()
18571 {
18572 return $this->statusCode;
18573 }
18574 }
18575 <?php
18576
18577
18578
18579
18580
18581
18582
18583
18584
18585
18586
18587 namespace Composer\Downloader;
18588
18589 use Composer\Package\PackageInterface;
18590
18591
18592
18593
18594
18595
18596 interface VcsCapableDownloaderInterface
18597 {
18598
18599
18600
18601
18602
18603
18604
18605 public function getVcsReference(PackageInterface $package, $path);
18606 }
18607 <?php
18608
18609
18610
18611
18612
18613
18614
18615
18616
18617
18618
18619 namespace Composer\Downloader;
18620
18621 use Composer\Config;
18622 use Composer\Package\Dumper\ArrayDumper;
18623 use Composer\Package\PackageInterface;
18624 use Composer\Package\Version\VersionGuesser;
18625 use Composer\Package\Version\VersionParser;
18626 use Composer\Util\ProcessExecutor;
18627 use Composer\IO\IOInterface;
18628 use Composer\Util\Filesystem;
18629
18630
18631
18632
18633 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
18634 {
18635
18636 protected $io;
18637
18638 protected $config;
18639
18640 protected $process;
18641
18642 protected $filesystem;
18643
18644 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
18645 {
18646 $this->io = $io;
18647 $this->config = $config;
18648 $this->process = $process ?: new ProcessExecutor($io);
18649 $this->filesystem = $fs ?: new Filesystem($this->process);
18650 }
18651
18652
18653
18654
18655 public function getInstallationSource()
18656 {
18657 return 'source';
18658 }
18659
18660
18661
18662
18663 public function download(PackageInterface $package, $path)
18664 {
18665 if (!$package->getSourceReference()) {
18666 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
18667 }
18668
18669 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
18670 $this->filesystem->emptyDirectory($path);
18671
18672 $urls = $package->getSourceUrls();
18673 while ($url = array_shift($urls)) {
18674 try {
18675 if (Filesystem::isLocalPath($url)) {
18676
18677  
18678  $needle = 'file://';
18679 $isFileProtocol = false;
18680 if (0 === strpos($url, $needle)) {
18681 $url = substr($url, strlen($needle));
18682 $isFileProtocol = true;
18683 }
18684
18685
18686  if (false !== strpos($url, '%')) {
18687 $url = rawurldecode($url);
18688 }
18689
18690 $url = realpath($url);
18691
18692 if ($isFileProtocol) {
18693 $url = $needle . $url;
18694 }
18695 }
18696 $this->doDownload($package, $path, $url);
18697 break;
18698 } catch (\Exception $e) {
18699
18700  if ($e instanceof \PHPUnit_Framework_Exception) {
18701 throw $e;
18702 }
18703 if ($this->io->isDebug()) {
18704 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
18705 } elseif (count($urls)) {
18706 $this->io->writeError('    Failed, trying the next URL');
18707 }
18708 if (!count($urls)) {
18709 throw $e;
18710 }
18711 }
18712 }
18713 }
18714
18715
18716
18717
18718 public function update(PackageInterface $initial, PackageInterface $target, $path)
18719 {
18720 if (!$target->getSourceReference()) {
18721 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
18722 }
18723
18724 $name = $target->getName();
18725 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
18726 if ($target->getSourceType() === 'svn') {
18727 $from = $initial->getSourceReference();
18728 $to = $target->getSourceReference();
18729 } else {
18730 $from = substr($initial->getSourceReference(), 0, 7);
18731 $to = substr($target->getSourceReference(), 0, 7);
18732 }
18733 $name .= ' '.$initial->getPrettyVersion();
18734 } else {
18735 $from = $initial->getFullPrettyVersion();
18736 $to = $target->getFullPrettyVersion();
18737 }
18738
18739 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
18740 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
18741
18742 $this->cleanChanges($initial, $path, true);
18743 $urls = $target->getSourceUrls();
18744
18745 $exception = null;
18746 while ($url = array_shift($urls)) {
18747 try {
18748 if (Filesystem::isLocalPath($url)) {
18749 $url = realpath($url);
18750 }
18751 $this->doUpdate($initial, $target, $path, $url);
18752
18753 $exception = null;
18754 break;
18755 } catch (\Exception $exception) {
18756
18757  if ($exception instanceof \PHPUnit_Framework_Exception) {
18758 throw $exception;
18759 }
18760 if ($this->io->isDebug()) {
18761 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
18762 } elseif (count($urls)) {
18763 $this->io->writeError('    Failed, trying the next URL');
18764 }
18765 }
18766 }
18767
18768 $this->reapplyChanges($path);
18769
18770
18771  
18772  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
18773 $message = 'Pulling in changes:';
18774 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
18775
18776 if (!trim($logs)) {
18777 $message = 'Rolling back changes:';
18778 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
18779 }
18780
18781 if (trim($logs)) {
18782 $logs = implode("\n", array_map(function ($line) {
18783 return '      ' . $line;
18784 }, explode("\n", $logs)));
18785
18786
18787  $logs = str_replace('<', '\<', $logs);
18788
18789 $this->io->writeError('    '.$message);
18790 $this->io->writeError($logs);
18791 }
18792 }
18793
18794 if (!$urls && $exception) {
18795 throw $exception;
18796 }
18797 }
18798
18799
18800
18801
18802 public function remove(PackageInterface $package, $path)
18803 {
18804 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
18805 $this->cleanChanges($package, $path, false);
18806 if (!$this->filesystem->removeDirectory($path)) {
18807 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
18808 }
18809 }
18810
18811
18812
18813
18814
18815 public function setOutputProgress($outputProgress)
18816 {
18817 return $this;
18818 }
18819
18820
18821
18822
18823 public function getVcsReference(PackageInterface $package, $path)
18824 {
18825 $parser = new VersionParser;
18826 $guesser = new VersionGuesser($this->config, $this->process, $parser);
18827 $dumper = new ArrayDumper;
18828
18829 $packageConfig = $dumper->dump($package);
18830 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
18831 return $packageVersion['commit'];
18832 }
18833 }
18834
18835
18836
18837
18838
18839
18840
18841
18842
18843
18844 protected function cleanChanges(PackageInterface $package, $path, $update)
18845 {
18846
18847  if (null !== $this->getLocalChanges($package, $path)) {
18848 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
18849 }
18850 }
18851
18852
18853
18854
18855
18856
18857
18858 protected function reapplyChanges($path)
18859 {
18860 }
18861
18862
18863
18864
18865
18866
18867
18868
18869 abstract protected function doDownload(PackageInterface $package, $path, $url);
18870
18871
18872
18873
18874
18875
18876
18877
18878
18879 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
18880
18881
18882
18883
18884
18885
18886
18887
18888
18889 abstract protected function getCommitLogs($fromReference, $toReference, $path);
18890
18891
18892
18893
18894
18895
18896
18897
18898 abstract protected function hasMetadataRepository($path);
18899 }
18900 <?php
18901
18902
18903
18904
18905
18906
18907
18908
18909
18910
18911
18912 namespace Composer\Downloader;
18913
18914 use Composer\Config;
18915 use Composer\Cache;
18916 use Composer\EventDispatcher\EventDispatcher;
18917 use Composer\Package\PackageInterface;
18918 use Composer\Util\ProcessExecutor;
18919 use Composer\Util\RemoteFilesystem;
18920 use Composer\IO\IOInterface;
18921
18922
18923
18924
18925
18926
18927
18928 class XzDownloader extends ArchiveDownloader
18929 {
18930 protected $process;
18931
18932 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18933 {
18934 $this->process = $process ?: new ProcessExecutor($io);
18935
18936 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
18937 }
18938
18939 protected function extract($file, $path)
18940 {
18941 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
18942
18943 if (0 === $this->process->execute($command, $ignoredOutput)) {
18944 return;
18945 }
18946
18947 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
18948
18949 throw new \RuntimeException($processError);
18950 }
18951
18952
18953
18954
18955 protected function getFileName(PackageInterface $package, $path)
18956 {
18957 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
18958 }
18959 }
18960 <?php
18961
18962
18963
18964
18965
18966
18967
18968
18969
18970
18971
18972 namespace Composer\Downloader;
18973
18974 use Composer\Config;
18975 use Composer\Cache;
18976 use Composer\EventDispatcher\EventDispatcher;
18977 use Composer\Package\PackageInterface;
18978 use Composer\Util\IniHelper;
18979 use Composer\Util\Platform;
18980 use Composer\Util\ProcessExecutor;
18981 use Composer\Util\RemoteFilesystem;
18982 use Composer\IO\IOInterface;
18983 use Symfony\Component\Process\ExecutableFinder;
18984 use ZipArchive;
18985
18986
18987
18988
18989 class ZipDownloader extends ArchiveDownloader
18990 {
18991 protected static $hasSystemUnzip;
18992 private static $hasZipArchive;
18993 private static $isWindows;
18994
18995 protected $process;
18996 private $zipArchiveObject;
18997
18998 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
18999 {
19000 $this->process = $process ?: new ProcessExecutor($io);
19001 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
19002 }
19003
19004
19005
19006
19007 public function download(PackageInterface $package, $path, $output = true)
19008 {
19009 if (null === self::$hasSystemUnzip) {
19010 $finder = new ExecutableFinder;
19011 self::$hasSystemUnzip = (bool) $finder->find('unzip');
19012 }
19013
19014 if (null === self::$hasZipArchive) {
19015 self::$hasZipArchive = class_exists('ZipArchive');
19016 }
19017
19018 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
19019
19020  $iniMessage = IniHelper::getMessage();
19021 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
19022
19023 throw new \RuntimeException($error);
19024 }
19025
19026 if (null === self::$isWindows) {
19027 self::$isWindows = Platform::isWindows();
19028
19029 if (!self::$isWindows && !self::$hasSystemUnzip) {
19030 $this->io->writeError("<warning>As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.</warning>");
19031 $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>");
19032 $this->io->writeError("<warning>Installing 'unzip' may remediate them.</warning>");
19033 }
19034 }
19035
19036 return parent::download($package, $path, $output);
19037 }
19038
19039
19040
19041
19042
19043
19044
19045
19046
19047 protected function extractWithSystemUnzip($file, $path, $isLastChance)
19048 {
19049 if (!self::$hasZipArchive) {
19050
19051  $isLastChance = true;
19052 }
19053
19054 if (!self::$hasSystemUnzip && !$isLastChance) {
19055
19056  
19057  return $this->extractWithZipArchive($file, $path, true);
19058 }
19059
19060 $processError = null;
19061
19062  $overwrite = $isLastChance ? '-o' : '';
19063
19064 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
19065
19066 try {
19067 if (0 === $exitCode = $this->process->execute($command, $ignoredOutput)) {
19068 return true;
19069 }
19070
19071 $processError = new \RuntimeException('Failed to execute ('.$exitCode.') '.$command."\n\n".$this->process->getErrorOutput());
19072 } catch (\Exception $e) {
19073 $processError = $e;
19074 }
19075
19076 if ($isLastChance) {
19077 throw $processError;
19078 }
19079
19080 $this->io->writeError('    '.$processError->getMessage());
19081 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
19082 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
19083
19084 return $this->extractWithZipArchive($file, $path, true);
19085 }
19086
19087
19088
19089
19090
19091
19092
19093
19094
19095 protected function extractWithZipArchive($file, $path, $isLastChance)
19096 {
19097 if (!self::$hasSystemUnzip) {
19098
19099  $isLastChance = true;
19100 }
19101
19102 if (!self::$hasZipArchive && !$isLastChance) {
19103
19104  
19105  return $this->extractWithSystemUnzip($file, $path, true);
19106 }
19107
19108 $processError = null;
19109 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
19110
19111 try {
19112 if (true === ($retval = $zipArchive->open($file))) {
19113 $extractResult = $zipArchive->extractTo($path);
19114
19115 if (true === $extractResult) {
19116 $zipArchive->close();
19117
19118 return true;
19119 }
19120
19121 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
19122 } else {
19123 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
19124 }
19125 } catch (\ErrorException $e) {
19126 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
19127 } catch (\Exception $e) {
19128 $processError = $e;
19129 }
19130
19131 if ($isLastChance) {
19132 throw $processError;
19133 }
19134
19135 $this->io->writeError('    '.$processError->getMessage());
19136 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
19137
19138 return $this->extractWithSystemUnzip($file, $path, true);
19139 }
19140
19141
19142
19143
19144
19145
19146
19147 public function extract($file, $path)
19148 {
19149
19150  if (self::$isWindows) {
19151 $this->extractWithZipArchive($file, $path, false);
19152 } else {
19153 $this->extractWithSystemUnzip($file, $path, false);
19154 }
19155 }
19156
19157
19158
19159
19160
19161
19162
19163
19164 protected function getErrorMessage($retval, $file)
19165 {
19166 switch ($retval) {
19167 case ZipArchive::ER_EXISTS:
19168 return sprintf("File '%s' already exists.", $file);
19169 case ZipArchive::ER_INCONS:
19170 return sprintf("Zip archive '%s' is inconsistent.", $file);
19171 case ZipArchive::ER_INVAL:
19172 return sprintf("Invalid argument (%s)", $file);
19173 case ZipArchive::ER_MEMORY:
19174 return sprintf("Malloc failure (%s)", $file);
19175 case ZipArchive::ER_NOENT:
19176 return sprintf("No such zip file: '%s'", $file);
19177 case ZipArchive::ER_NOZIP:
19178 return sprintf("'%s' is not a zip archive.", $file);
19179 case ZipArchive::ER_OPEN:
19180 return sprintf("Can't open zip file: %s", $file);
19181 case ZipArchive::ER_READ:
19182 return sprintf("Zip read error (%s)", $file);
19183 case ZipArchive::ER_SEEK:
19184 return sprintf("Zip seek error (%s)", $file);
19185 default:
19186 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
19187 }
19188 }
19189 }
19190 <?php
19191
19192
19193
19194
19195
19196
19197
19198
19199
19200
19201
19202 namespace Composer\EventDispatcher;
19203
19204
19205
19206
19207
19208
19209 class Event
19210 {
19211
19212
19213
19214 protected $name;
19215
19216
19217
19218
19219 protected $args;
19220
19221
19222
19223
19224 protected $flags;
19225
19226
19227
19228
19229 private $propagationStopped = false;
19230
19231
19232
19233
19234
19235
19236
19237
19238 public function __construct($name, array $args = array(), array $flags = array())
19239 {
19240 $this->name = $name;
19241 $this->args = $args;
19242 $this->flags = $flags;
19243 }
19244
19245
19246
19247
19248
19249
19250 public function getName()
19251 {
19252 return $this->name;
19253 }
19254
19255
19256
19257
19258
19259
19260 public function getArguments()
19261 {
19262 return $this->args;
19263 }
19264
19265
19266
19267
19268
19269
19270 public function getFlags()
19271 {
19272 return $this->flags;
19273 }
19274
19275
19276
19277
19278
19279
19280 public function isPropagationStopped()
19281 {
19282 return $this->propagationStopped;
19283 }
19284
19285
19286
19287
19288 public function stopPropagation()
19289 {
19290 $this->propagationStopped = true;
19291 }
19292 }
19293 <?php
19294
19295
19296
19297
19298
19299
19300
19301
19302
19303
19304
19305 namespace Composer\EventDispatcher;
19306
19307 use Composer\DependencyResolver\PolicyInterface;
19308 use Composer\DependencyResolver\Pool;
19309 use Composer\DependencyResolver\Request;
19310 use Composer\Installer\InstallerEvent;
19311 use Composer\IO\IOInterface;
19312 use Composer\Composer;
19313 use Composer\DependencyResolver\Operation\OperationInterface;
19314 use Composer\Repository\CompositeRepository;
19315 use Composer\Script;
19316 use Composer\Installer\PackageEvent;
19317 use Composer\Installer\BinaryInstaller;
19318 use Composer\Util\ProcessExecutor;
19319 use Composer\Script\Event as ScriptEvent;
19320 use Symfony\Component\Process\PhpExecutableFinder;
19321
19322
19323
19324
19325
19326
19327
19328
19329
19330
19331
19332
19333
19334
19335 class EventDispatcher
19336 {
19337 protected $composer;
19338 protected $io;
19339 protected $loader;
19340 protected $process;
19341 protected $listeners;
19342 private $eventStack;
19343
19344
19345
19346
19347
19348
19349
19350
19351 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
19352 {
19353 $this->composer = $composer;
19354 $this->io = $io;
19355 $this->process = $process ?: new ProcessExecutor($io);
19356 $this->eventStack = array();
19357 }
19358
19359
19360
19361
19362
19363
19364
19365
19366
19367 public function dispatch($eventName, Event $event = null)
19368 {
19369 if (null === $event) {
19370 $event = new Event($eventName);
19371 }
19372
19373 return $this->doDispatch($event);
19374 }
19375
19376
19377
19378
19379
19380
19381
19382
19383
19384
19385
19386 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
19387 {
19388 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
19389 }
19390
19391
19392
19393
19394
19395
19396
19397
19398
19399
19400
19401
19402
19403
19404
19405
19406 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
19407 {
19408 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
19409 }
19410
19411
19412
19413
19414
19415
19416
19417
19418
19419
19420
19421
19422
19423
19424
19425 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
19426 {
19427 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
19428 }
19429
19430
19431
19432
19433
19434
19435
19436
19437
19438 protected function doDispatch(Event $event)
19439 {
19440 $listeners = $this->getListeners($event);
19441
19442 $this->pushEvent($event);
19443
19444 $return = 0;
19445 foreach ($listeners as $callable) {
19446
19447 $this->ensureBinDirIsInPath();
19448
19449 if (!is_string($callable)) {
19450 if (!is_callable($callable)) {
19451 $className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
19452
19453 throw new \RuntimeException('Subscriber '.$className.'::'.$callable[1].' for event '.$event->getName().' is not callable, make sure the function is defined and public');
19454 }
19455 $event = $this->checkListenerExpectedEvent($callable, $event);
19456 $return = false === call_user_func($callable, $event) ? 1 : 0;
19457 } elseif ($this->isComposerScript($callable)) {
19458 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
19459
19460 $script = explode(' ', substr($callable, 1));
19461 $scriptName = $script[0];
19462 unset($script[0]);
19463
19464 $args = array_merge($script, $event->getArguments());
19465 $flags = $event->getFlags();
19466 if (substr($callable, 0, 10) === '@composer ') {
19467 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
19468 if (0 !== ($exitCode = $this->process->execute($exec))) {
19469 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
19470
19471 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
19472 }
19473 } else {
19474 if (!$this->getListeners(new Event($scriptName))) {
19475 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
19476 }
19477
19478 try {
19479 $scriptEvent = new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags);
19480 $scriptEvent->setOriginatingEvent($event);
19481 $return = $this->dispatch($scriptName, $scriptEvent);
19482 } catch (ScriptExecutionException $e) {
19483 $this->io->writeError(sprintf('<error>Script %s was called via %s</error>', $callable, $event->getName()), true, IOInterface::QUIET);
19484 throw $e;
19485 }
19486 }
19487 } elseif ($this->isPhpScript($callable)) {
19488 $className = substr($callable, 0, strpos($callable, '::'));
19489 $methodName = substr($callable, strpos($callable, '::') + 2);
19490
19491 if (!class_exists($className)) {
19492 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
19493 continue;
19494 }
19495 if (!is_callable($callable)) {
19496 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
19497 continue;
19498 }
19499
19500 try {
19501 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
19502 } catch (\Exception $e) {
19503 $message = "Script %s handling the %s event terminated with an exception";
19504 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
19505 throw $e;
19506 }
19507 } else {
19508 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
19509 $exec = $callable . ($args === '' ? '' : ' '.$args);
19510 if ($this->io->isVerbose()) {
19511 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
19512 } else {
19513 $this->io->writeError(sprintf('> %s', $exec));
19514 }
19515
19516 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
19517 if ($possibleLocalBinaries) {
19518 foreach ($possibleLocalBinaries as $localExec) {
19519 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
19520 $caller = BinaryInstaller::determineBinaryCaller($localExec);
19521 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
19522 break;
19523 }
19524 }
19525 }
19526
19527 if (substr($exec, 0, 8) === '@putenv ') {
19528 putenv(substr($exec, 8));
19529
19530 continue;
19531 } elseif (substr($exec, 0, 5) === '@php ') {
19532 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
19533 } else {
19534 $finder = new PhpExecutableFinder();
19535 $phpPath = $finder->find(false);
19536 if ($phpPath) {
19537 $_SERVER['PHP_BINARY'] = $phpPath;
19538 putenv('PHP_BINARY=' . $_SERVER['PHP_BINARY']);
19539 }
19540 }
19541
19542
19543  
19544  
19545  if (substr($exec, 0, 9) === 'composer ') {
19546 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($exec, 8);
19547 }
19548
19549 if (0 !== ($exitCode = $this->process->execute($exec))) {
19550 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
19551
19552 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
19553 }
19554 }
19555
19556 if ($event->isPropagationStopped()) {
19557 break;
19558 }
19559 }
19560
19561 $this->popEvent();
19562
19563 return $return;
19564 }
19565
19566 protected function getPhpExecCommand()
19567 {
19568 $finder = new PhpExecutableFinder();
19569 $phpPath = $finder->find(false);
19570 if (!$phpPath) {
19571 throw new \RuntimeException('Failed to locate PHP binary to execute '.$phpPath);
19572 }
19573 $phpArgs = $finder->findArguments();
19574 $phpArgs = $phpArgs ? ' ' . implode(' ', $phpArgs) : '';
19575 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
19576 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
19577 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
19578
19579 return ProcessExecutor::escape($phpPath) . $phpArgs . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
19580 }
19581
19582
19583
19584
19585
19586
19587 protected function executeEventPhpScript($className, $methodName, Event $event)
19588 {
19589 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
19590
19591 if ($this->io->isVerbose()) {
19592 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
19593 } else {
19594 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
19595 }
19596
19597 return $className::$methodName($event);
19598 }
19599
19600
19601
19602
19603
19604
19605 protected function checkListenerExpectedEvent($target, Event $event)
19606 {
19607 if (in_array($event->getName(), array(
19608 'init',
19609 'command',
19610 'pre-file-download',
19611 ), true)) {
19612 return $event;
19613 }
19614
19615 try {
19616 $reflected = new \ReflectionParameter($target, 0);
19617 } catch (\Exception $e) {
19618 return $event;
19619 }
19620
19621 $expected = null;
19622 $isClass = false;
19623 if (\PHP_VERSION_ID >= 70000) {
19624 $reflectionType = $reflected->getType();
19625 if ($reflectionType) {
19626 $expected = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string)$reflectionType;
19627 $isClass = !$reflectionType->isBuiltin();
19628 }
19629 } else {
19630 $expected = $reflected->getClass() ? $reflected->getClass()->getName() : null;
19631 $isClass = null !== $expected;
19632 }
19633
19634 if (!$isClass) {
19635 return $event;
19636 }
19637
19638
19639  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
19640 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);
19641 $event = new \Composer\Script\CommandEvent(
19642 $event->getName(),
19643 $event->getComposer(),
19644 $event->getIO(),
19645 $event->isDevMode(),
19646 $event->getArguments()
19647 );
19648 }
19649 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
19650 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);
19651 $event = new \Composer\Script\PackageEvent(
19652 $event->getName(),
19653 $event->getComposer(),
19654 $event->getIO(),
19655 $event->isDevMode(),
19656 $event->getPolicy(),
19657 $event->getPool(),
19658 $event->getInstalledRepo(),
19659 $event->getRequest(),
19660 $event->getOperations(),
19661 $event->getOperation()
19662 );
19663 }
19664 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
19665 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);
19666 $event = new \Composer\Script\Event(
19667 $event->getName(),
19668 $event->getComposer(),
19669 $event->getIO(),
19670 $event->isDevMode(),
19671 $event->getArguments(),
19672 $event->getFlags()
19673 );
19674 }
19675
19676 return $event;
19677 }
19678
19679 private function serializeCallback($cb)
19680 {
19681 if (is_array($cb) && count($cb) === 2) {
19682 if (is_object($cb[0])) {
19683 $cb[0] = get_class($cb[0]);
19684 }
19685 if (is_string($cb[0]) && is_string($cb[1])) {
19686 $cb = implode('::', $cb);
19687 }
19688 }
19689 if (is_string($cb)) {
19690 return $cb;
19691 }
19692
19693 return var_export($cb, true);
19694 }
19695
19696
19697
19698
19699
19700
19701
19702
19703 public function addListener($eventName, $listener, $priority = 0)
19704 {
19705 $this->listeners[$eventName][$priority][] = $listener;
19706 }
19707
19708
19709
19710
19711
19712
19713
19714
19715 public function addSubscriber(EventSubscriberInterface $subscriber)
19716 {
19717 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
19718 if (is_string($params)) {
19719 $this->addListener($eventName, array($subscriber, $params));
19720 } elseif (is_string($params[0])) {
19721 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
19722 } else {
19723 foreach ($params as $listener) {
19724 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
19725 }
19726 }
19727 }
19728 }
19729
19730
19731
19732
19733
19734
19735
19736 protected function getListeners(Event $event)
19737 {
19738 $scriptListeners = $this->getScriptListeners($event);
19739
19740 if (!isset($this->listeners[$event->getName()][0])) {
19741 $this->listeners[$event->getName()][0] = array();
19742 }
19743 krsort($this->listeners[$event->getName()]);
19744
19745 $listeners = $this->listeners;
19746 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
19747
19748 return call_user_func_array('array_merge', $listeners[$event->getName()]);
19749 }
19750
19751
19752
19753
19754
19755
19756
19757 public function hasEventListeners(Event $event)
19758 {
19759 $listeners = $this->getListeners($event);
19760
19761 return count($listeners) > 0;
19762 }
19763
19764
19765
19766
19767
19768
19769
19770 protected function getScriptListeners(Event $event)
19771 {
19772 $package = $this->composer->getPackage();
19773 $scripts = $package->getScripts();
19774
19775 if (empty($scripts[$event->getName()])) {
19776 return array();
19777 }
19778
19779 if ($this->loader) {
19780 $this->loader->unregister();
19781 }
19782
19783 $generator = $this->composer->getAutoloadGenerator();
19784 if ($event instanceof ScriptEvent) {
19785 $generator->setDevMode($event->isDevMode());
19786 }
19787
19788 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
19789 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
19790 $map = $generator->parseAutoloads($packageMap, $package);
19791 $this->loader = $generator->createLoader($map);
19792 $this->loader->register();
19793
19794 return $scripts[$event->getName()];
19795 }
19796
19797
19798
19799
19800
19801
19802
19803 protected function isPhpScript($callable)
19804 {
19805 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
19806 }
19807
19808
19809
19810
19811
19812
19813
19814 protected function isComposerScript($callable)
19815 {
19816 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5) && '@putenv ' !== substr($callable, 0, 8);
19817 }
19818
19819
19820
19821
19822
19823
19824
19825
19826 protected function pushEvent(Event $event)
19827 {
19828 $eventName = $event->getName();
19829 if (in_array($eventName, $this->eventStack)) {
19830 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
19831 }
19832
19833 return array_push($this->eventStack, $eventName);
19834 }
19835
19836
19837
19838
19839
19840
19841 protected function popEvent()
19842 {
19843 return array_pop($this->eventStack);
19844 }
19845
19846 private function ensureBinDirIsInPath()
19847 {
19848 $pathStr = 'PATH';
19849 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
19850 $pathStr = 'Path';
19851 }
19852
19853
19854  $binDir = $this->composer->getConfig()->get('bin-dir');
19855 if (is_dir($binDir)) {
19856 $binDir = realpath($binDir);
19857 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
19858 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
19859 putenv($pathStr.'='.$_SERVER[$pathStr]);
19860 }
19861 }
19862 }
19863 }
19864 <?php
19865
19866
19867
19868
19869
19870
19871
19872
19873
19874
19875
19876 namespace Composer\EventDispatcher;
19877
19878
19879
19880
19881
19882
19883
19884
19885
19886
19887
19888
19889
19890 interface EventSubscriberInterface
19891 {
19892
19893
19894
19895
19896
19897
19898
19899
19900
19901
19902
19903
19904
19905
19906
19907
19908
19909
19910 public static function getSubscribedEvents();
19911 }
19912 <?php
19913
19914
19915
19916
19917
19918
19919
19920
19921
19922
19923
19924 namespace Composer\EventDispatcher;
19925
19926
19927
19928
19929 class ScriptExecutionException extends \RuntimeException
19930 {
19931 }
19932 <?php
19933
19934
19935
19936
19937
19938
19939
19940
19941
19942
19943
19944 namespace Composer\Exception;
19945
19946
19947
19948
19949 class NoSslException extends \RuntimeException
19950 {
19951 }
19952 <?php
19953
19954
19955
19956
19957
19958
19959
19960
19961
19962
19963
19964 namespace Composer;
19965
19966 use Composer\Config\JsonConfigSource;
19967 use Composer\Json\JsonFile;
19968 use Composer\IO\IOInterface;
19969 use Composer\Package\Archiver;
19970 use Composer\Package\Version\VersionGuesser;
19971 use Composer\Repository\RepositoryManager;
19972 use Composer\Repository\RepositoryFactory;
19973 use Composer\Repository\WritableRepositoryInterface;
19974 use Composer\Util\Filesystem;
19975 use Composer\Util\Platform;
19976 use Composer\Util\ProcessExecutor;
19977 use Composer\Util\RemoteFilesystem;
19978 use Composer\Util\Silencer;
19979 use Composer\Plugin\PluginEvents;
19980 use Composer\EventDispatcher\Event;
19981 use Seld\JsonLint\DuplicateKeyException;
19982 use Symfony\Component\Console\Formatter\OutputFormatter;
19983 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
19984 use Symfony\Component\Console\Output\ConsoleOutput;
19985 use Composer\EventDispatcher\EventDispatcher;
19986 use Composer\Autoload\AutoloadGenerator;
19987 use Composer\Package\Version\VersionParser;
19988 use Composer\Downloader\TransportException;
19989 use Seld\JsonLint\JsonParser;
19990
19991
19992
19993
19994
19995
19996
19997
19998
19999 class Factory
20000 {
20001
20002
20003
20004
20005 protected static function getHomeDir()
20006 {
20007 $home = getenv('COMPOSER_HOME');
20008 if ($home) {
20009 return $home;
20010 }
20011
20012 if (Platform::isWindows()) {
20013 if (!getenv('APPDATA')) {
20014 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
20015 }
20016
20017 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
20018 }
20019
20020 $userDir = self::getUserDir();
20021 if (is_dir($userDir . '/.composer')) {
20022 return $userDir . '/.composer';
20023 }
20024
20025 if (self::useXdg()) {
20026
20027  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
20028
20029 return $xdgConfig . '/composer';
20030 }
20031
20032 return $userDir . '/.composer';
20033 }
20034
20035
20036
20037
20038
20039 protected static function getCacheDir($home)
20040 {
20041 $cacheDir = getenv('COMPOSER_CACHE_DIR');
20042 if ($cacheDir) {
20043 return $cacheDir;
20044 }
20045
20046 $homeEnv = getenv('COMPOSER_HOME');
20047 if ($homeEnv) {
20048 return $homeEnv . '/cache';
20049 }
20050
20051 if (Platform::isWindows()) {
20052 if ($cacheDir = getenv('LOCALAPPDATA')) {
20053 $cacheDir .= '/Composer';
20054 } else {
20055 $cacheDir = $home . '/cache';
20056 }
20057
20058 return rtrim(strtr($cacheDir, '\\', '/'), '/');
20059 }
20060
20061 $userDir = self::getUserDir();
20062 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
20063 return $home . '/cache';
20064 }
20065
20066 if (self::useXdg()) {
20067 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
20068
20069 return $xdgCache . '/composer';
20070 }
20071
20072 return $home . '/cache';
20073 }
20074
20075
20076
20077
20078
20079 protected static function getDataDir($home)
20080 {
20081 $homeEnv = getenv('COMPOSER_HOME');
20082 if ($homeEnv) {
20083 return $homeEnv;
20084 }
20085
20086 if (Platform::isWindows()) {
20087 return strtr($home, '\\', '/');
20088 }
20089
20090 $userDir = self::getUserDir();
20091 if ($home !== $userDir . '/.composer' && self::useXdg()) {
20092 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
20093
20094 return $xdgData . '/composer';
20095 }
20096
20097 return $home;
20098 }
20099
20100
20101
20102
20103
20104 public static function createConfig(IOInterface $io = null, $cwd = null)
20105 {
20106 $cwd = $cwd ?: getcwd();
20107
20108 $config = new Config(true, $cwd);
20109
20110
20111  $home = self::getHomeDir();
20112 $config->merge(array('config' => array(
20113 'home' => $home,
20114 'cache-dir' => self::getCacheDir($home),
20115 'data-dir' => self::getDataDir($home),
20116 )));
20117
20118
20119  $file = new JsonFile($config->get('home').'/config.json');
20120 if ($file->exists()) {
20121 if ($io && $io->isDebug()) {
20122 $io->writeError('Loading config file ' . $file->getPath());
20123 }
20124 $config->merge($file->read());
20125 }
20126 $config->setConfigSource(new JsonConfigSource($file));
20127
20128 $htaccessProtect = (bool) $config->get('htaccess-protect');
20129 if ($htaccessProtect) {
20130
20131  
20132  
20133  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
20134 foreach ($dirs as $dir) {
20135 if (!file_exists($dir . '/.htaccess')) {
20136 if (!is_dir($dir)) {
20137 Silencer::call('mkdir', $dir, 0777, true);
20138 }
20139 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
20140 }
20141 }
20142 }
20143
20144
20145  $file = new JsonFile($config->get('home').'/auth.json');
20146 if ($file->exists()) {
20147 if ($io && $io->isDebug()) {
20148 $io->writeError('Loading config file ' . $file->getPath());
20149 }
20150 $config->merge(array('config' => $file->read()));
20151 }
20152 $config->setAuthConfigSource(new JsonConfigSource($file, true));
20153
20154
20155  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
20156 $authData = json_decode($composerAuthEnv, true);
20157
20158 if (null === $authData) {
20159 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
20160 }
20161
20162 if ($io && $io->isDebug()) {
20163 $io->writeError('Loading auth config from COMPOSER_AUTH');
20164 }
20165 $config->merge(array('config' => $authData));
20166 }
20167
20168 return $config;
20169 }
20170
20171 public static function getComposerFile()
20172 {
20173 return trim(getenv('COMPOSER')) ?: './composer.json';
20174 }
20175
20176 public static function createAdditionalStyles()
20177 {
20178 return array(
20179 'highlight' => new OutputFormatterStyle('red'),
20180 'warning' => new OutputFormatterStyle('black', 'yellow'),
20181 );
20182 }
20183
20184
20185
20186
20187
20188
20189 public static function createOutput()
20190 {
20191 $styles = self::createAdditionalStyles();
20192 $formatter = new OutputFormatter(false, $styles);
20193
20194 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
20195 }
20196
20197
20198
20199
20200 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
20201 {
20202 return RepositoryFactory::defaultRepos($io, $config, $rm);
20203 }
20204
20205
20206
20207
20208
20209
20210
20211
20212
20213
20214
20215
20216
20217 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
20218 {
20219 $cwd = $cwd ?: getcwd();
20220
20221
20222  if (null === $localConfig) {
20223 $localConfig = static::getComposerFile();
20224 }
20225
20226 if (is_string($localConfig)) {
20227 $composerFile = $localConfig;
20228
20229 $file = new JsonFile($localConfig, null, $io);
20230
20231 if (!$file->exists()) {
20232 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
20233 $message = 'Composer could not find a composer.json file in '.$cwd;
20234 } else {
20235 $message = 'Composer could not find the config file: '.$localConfig;
20236 }
20237 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
20238 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
20239 }
20240
20241 $file->validateSchema(JsonFile::LAX_SCHEMA);
20242 $jsonParser = new JsonParser;
20243 try {
20244 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
20245 } catch (DuplicateKeyException $e) {
20246 $details = $e->getDetails();
20247 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
20248 }
20249
20250 $localConfig = $file->read();
20251 }
20252
20253
20254  $config = static::createConfig($io, $cwd);
20255 $config->merge($localConfig);
20256 if (isset($composerFile)) {
20257 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
20258 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
20259
20260 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
20261 if ($localAuthFile->exists()) {
20262 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
20263 $config->merge(array('config' => $localAuthFile->read()));
20264 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
20265 }
20266 }
20267
20268 $vendorDir = $config->get('vendor-dir');
20269
20270
20271  $composer = new Composer();
20272 $composer->setConfig($config);
20273
20274 if ($fullLoad) {
20275
20276  $io->loadConfiguration($config);
20277 }
20278
20279 $rfs = self::createRemoteFilesystem($io, $config);
20280
20281
20282  $dispatcher = new EventDispatcher($composer, $io);
20283 $composer->setEventDispatcher($dispatcher);
20284
20285
20286  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
20287 $composer->setRepositoryManager($rm);
20288
20289
20290  $this->addLocalRepository($io, $rm, $vendorDir);
20291
20292
20293  
20294  if (!$fullLoad && !isset($localConfig['version'])) {
20295 $localConfig['version'] = '1.0.0';
20296 }
20297
20298
20299  $parser = new VersionParser;
20300 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
20301 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
20302 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
20303 $composer->setPackage($package);
20304
20305
20306  $im = $this->createInstallationManager();
20307 $composer->setInstallationManager($im);
20308
20309 if ($fullLoad) {
20310
20311  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
20312 $composer->setDownloadManager($dm);
20313
20314
20315  $generator = new AutoloadGenerator($dispatcher, $io);
20316 $composer->setAutoloadGenerator($generator);
20317
20318
20319  $am = $this->createArchiveManager($config, $dm);
20320 $composer->setArchiveManager($am);
20321 }
20322
20323
20324  $this->createDefaultInstallers($im, $composer, $io);
20325
20326 if ($fullLoad) {
20327 $globalComposer = null;
20328 if (realpath($config->get('home')) !== $cwd) {
20329 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
20330 }
20331
20332 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
20333 $composer->setPluginManager($pm);
20334
20335 $pm->loadInstalledPlugins();
20336 }
20337
20338
20339  if ($fullLoad && isset($composerFile)) {
20340 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
20341 ? substr($composerFile, 0, -4).'lock'
20342 : $composerFile . '.lock';
20343
20344 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
20345 $composer->setLocker($locker);
20346 }
20347
20348 if ($fullLoad) {
20349 $initEvent = new Event(PluginEvents::INIT);
20350 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
20351
20352
20353  
20354  if ($rm->getLocalRepository()) {
20355 $this->purgePackages($rm->getLocalRepository(), $im);
20356 }
20357 }
20358
20359 return $composer;
20360 }
20361
20362
20363
20364
20365
20366
20367 public static function createGlobal(IOInterface $io, $disablePlugins = false)
20368 {
20369 $factory = new static();
20370
20371 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
20372 }
20373
20374
20375
20376
20377
20378 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
20379 {
20380 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
20381 }
20382
20383
20384
20385
20386
20387 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
20388 {
20389 $composer = null;
20390 try {
20391 $composer = $this->createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
20392 } catch (\Exception $e) {
20393 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
20394 }
20395
20396 return $composer;
20397 }
20398
20399
20400
20401
20402
20403
20404
20405 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
20406 {
20407 $cache = null;
20408 if ($config->get('cache-files-ttl') > 0) {
20409 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
20410 }
20411
20412 $dm = new Downloader\DownloadManager($io);
20413 switch ($preferred = $config->get('preferred-install')) {
20414 case 'dist':
20415 $dm->setPreferDist(true);
20416 break;
20417 case 'source':
20418 $dm->setPreferSource(true);
20419 break;
20420 case 'auto':
20421 default:
20422
20423  break;
20424 }
20425
20426 if (is_array($preferred)) {
20427 $dm->setPreferences($preferred);
20428 }
20429
20430 $executor = new ProcessExecutor($io);
20431 $fs = new Filesystem($executor);
20432
20433 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
20434 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
20435 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
20436 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
20437 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
20438 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20439 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20440 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20441 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20442 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
20443 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20444 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20445 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
20446
20447 return $dm;
20448 }
20449
20450
20451
20452
20453
20454
20455 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
20456 {
20457 if (null === $dm) {
20458 $io = new IO\NullIO();
20459 $io->loadConfiguration($config);
20460 $dm = $this->createDownloadManager($io, $config);
20461 }
20462
20463 $am = new Archiver\ArchiveManager($dm);
20464 $am->addArchiver(new Archiver\ZipArchiver);
20465 $am->addArchiver(new Archiver\PharArchiver);
20466
20467 return $am;
20468 }
20469
20470
20471
20472
20473
20474
20475
20476
20477 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
20478 {
20479 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
20480 }
20481
20482
20483
20484
20485 protected function createInstallationManager()
20486 {
20487 return new Installer\InstallationManager();
20488 }
20489
20490
20491
20492
20493
20494
20495 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
20496 {
20497 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
20498 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
20499 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
20500 $im->addInstaller(new Installer\MetapackageInstaller($io));
20501 }
20502
20503
20504
20505
20506
20507 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
20508 {
20509 foreach ($repo->getPackages() as $package) {
20510 if (!$im->isPackageInstalled($repo, $package)) {
20511 $repo->removePackage($package);
20512 }
20513 }
20514 }
20515
20516
20517
20518
20519
20520
20521
20522
20523 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
20524 {
20525 $factory = new static();
20526
20527 return $factory->createComposer($io, $config, $disablePlugins);
20528 }
20529
20530
20531
20532
20533
20534
20535
20536 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
20537 {
20538 static $warned = false;
20539 $disableTls = false;
20540 if ($config && $config->get('disable-tls') === true) {
20541 if (!$warned) {
20542 $io->writeError('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
20543 }
20544 $warned = true;
20545 $disableTls = true;
20546 } elseif (!extension_loaded('openssl')) {
20547 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
20548 . '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.');
20549 }
20550 $remoteFilesystemOptions = array();
20551 if ($disableTls === false) {
20552 if ($config && $config->get('cafile')) {
20553 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
20554 }
20555 if ($config && $config->get('capath')) {
20556 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
20557 }
20558 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
20559 }
20560 try {
20561 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
20562 } catch (TransportException $e) {
20563 if (false !== strpos($e->getMessage(), 'cafile')) {
20564 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
20565 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
20566 if (PHP_VERSION_ID < 50600) {
20567 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
20568 }
20569 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
20570 }
20571 throw $e;
20572 }
20573
20574 return $remoteFilesystem;
20575 }
20576
20577
20578
20579
20580 private static function useXdg()
20581 {
20582 foreach (array_keys($_SERVER) as $key) {
20583 if (substr($key, 0, 4) === 'XDG_') {
20584 return true;
20585 }
20586 }
20587
20588 return false;
20589 }
20590
20591
20592
20593
20594
20595 private static function getUserDir()
20596 {
20597 $home = getenv('HOME');
20598 if (!$home) {
20599 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
20600 }
20601
20602 return rtrim(strtr($home, '\\', '/'), '/');
20603 }
20604 }
20605 <?php
20606
20607
20608
20609
20610
20611
20612
20613
20614
20615
20616
20617 namespace Composer\IO;
20618
20619 use Composer\Config;
20620 use Composer\Util\ProcessExecutor;
20621 use Psr\Log\LoggerInterface;
20622 use Psr\Log\LogLevel;
20623
20624 abstract class BaseIO implements IOInterface, LoggerInterface
20625 {
20626 protected $authentications = array();
20627
20628
20629
20630
20631 public function getAuthentications()
20632 {
20633 return $this->authentications;
20634 }
20635
20636
20637
20638
20639 public function resetAuthentications()
20640 {
20641 $this->authentications = array();
20642 }
20643
20644
20645
20646
20647 public function hasAuthentication($repositoryName)
20648 {
20649 return isset($this->authentications[$repositoryName]);
20650 }
20651
20652
20653
20654
20655 public function getAuthentication($repositoryName)
20656 {
20657 if (isset($this->authentications[$repositoryName])) {
20658 return $this->authentications[$repositoryName];
20659 }
20660
20661 return array('username' => null, 'password' => null);
20662 }
20663
20664
20665
20666
20667 public function setAuthentication($repositoryName, $username, $password = null)
20668 {
20669 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
20670 }
20671
20672
20673
20674
20675 public function writeRaw($messages, $newline = true, $verbosity = self::NORMAL)
20676 {
20677 $this->write($messages, $newline, $verbosity);
20678 }
20679
20680
20681
20682
20683 public function writeErrorRaw($messages, $newline = true, $verbosity = self::NORMAL)
20684 {
20685 $this->writeError($messages, $newline, $verbosity);
20686 }
20687
20688
20689
20690
20691
20692
20693
20694
20695 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
20696 {
20697 if ($this->hasAuthentication($repositoryName)) {
20698 $auth = $this->getAuthentication($repositoryName);
20699 if ($auth['username'] === $username && $auth['password'] === $password) {
20700 return;
20701 }
20702
20703 $this->writeError(
20704 sprintf(
20705 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
20706 $repositoryName
20707 )
20708 );
20709 }
20710 $this->setAuthentication($repositoryName, $username, $password);
20711 }
20712
20713
20714
20715
20716 public function loadConfiguration(Config $config)
20717 {
20718 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
20719 $githubOauth = $config->get('github-oauth') ?: array();
20720 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
20721 $gitlabToken = $config->get('gitlab-token') ?: array();
20722 $httpBasic = $config->get('http-basic') ?: array();
20723 $bearerToken = $config->get('bearer') ?: array();
20724
20725
20726
20727 foreach ($bitbucketOauth as $domain => $cred) {
20728 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
20729 }
20730
20731 foreach ($githubOauth as $domain => $token) {
20732 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
20733 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
20734 }
20735 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
20736 }
20737
20738 foreach ($gitlabOauth as $domain => $token) {
20739 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
20740 }
20741
20742 foreach ($gitlabToken as $domain => $token) {
20743 $this->checkAndSetAuthentication($domain, $token, 'private-token');
20744 }
20745
20746
20747  foreach ($httpBasic as $domain => $cred) {
20748 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
20749 }
20750
20751 foreach ($bearerToken as $domain => $token) {
20752 $this->checkAndSetAuthentication($domain, $token, 'bearer');
20753 }
20754
20755
20756  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
20757 }
20758
20759
20760
20761
20762
20763
20764
20765
20766 public function emergency($message, array $context = array())
20767 {
20768 return $this->log(LogLevel::EMERGENCY, $message, $context);
20769 }
20770
20771
20772
20773
20774
20775
20776
20777
20778
20779
20780
20781 public function alert($message, array $context = array())
20782 {
20783 return $this->log(LogLevel::ALERT, $message, $context);
20784 }
20785
20786
20787
20788
20789
20790
20791
20792
20793
20794
20795 public function critical($message, array $context = array())
20796 {
20797 return $this->log(LogLevel::CRITICAL, $message, $context);
20798 }
20799
20800
20801
20802
20803
20804
20805
20806
20807
20808 public function error($message, array $context = array())
20809 {
20810 return $this->log(LogLevel::ERROR, $message, $context);
20811 }
20812
20813
20814
20815
20816
20817
20818
20819
20820
20821
20822
20823 public function warning($message, array $context = array())
20824 {
20825 return $this->log(LogLevel::WARNING, $message, $context);
20826 }
20827
20828
20829
20830
20831
20832
20833
20834
20835 public function notice($message, array $context = array())
20836 {
20837 return $this->log(LogLevel::NOTICE, $message, $context);
20838 }
20839
20840
20841
20842
20843
20844
20845
20846
20847
20848
20849 public function info($message, array $context = array())
20850 {
20851 return $this->log(LogLevel::INFO, $message, $context);
20852 }
20853
20854
20855
20856
20857
20858
20859
20860
20861 public function debug($message, array $context = array())
20862 {
20863 return $this->log(LogLevel::DEBUG, $message, $context);
20864 }
20865
20866
20867
20868
20869
20870
20871
20872
20873
20874 public function log($level, $message, array $context = array())
20875 {
20876 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
20877 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
20878 } elseif ($level === LogLevel::WARNING) {
20879 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
20880 } elseif ($level === LogLevel::NOTICE) {
20881 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
20882 } elseif ($level === LogLevel::INFO) {
20883 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
20884 } else {
20885 $this->writeError($message, true, self::DEBUG);
20886 }
20887 }
20888 }
20889 <?php
20890
20891
20892
20893
20894
20895
20896
20897
20898
20899
20900
20901 namespace Composer\IO;
20902
20903 use Symfony\Component\Console\Helper\QuestionHelper;
20904 use Symfony\Component\Console\Output\StreamOutput;
20905 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
20906 use Symfony\Component\Console\Input\StreamableInputInterface;
20907 use Symfony\Component\Console\Input\StringInput;
20908 use Symfony\Component\Console\Helper\HelperSet;
20909
20910
20911
20912
20913 class BufferIO extends ConsoleIO
20914 {
20915
20916
20917
20918
20919
20920 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
20921 {
20922 $input = new StringInput($input);
20923 $input->setInteractive(false);
20924
20925 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
20926
20927 parent::__construct($input, $output, new HelperSet(array(
20928 new QuestionHelper(),
20929 )));
20930 }
20931
20932 public function getOutput()
20933 {
20934 fseek($this->output->getStream(), 0);
20935
20936 $output = stream_get_contents($this->output->getStream());
20937
20938 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
20939 $pre = strip_tags($matches[1]);
20940
20941 if (strlen($pre) === strlen($matches[2])) {
20942 return '';
20943 }
20944
20945
20946  return rtrim($matches[1])."\n";
20947 }, $output);
20948
20949 return $output;
20950 }
20951
20952 public function setUserInputs(array $inputs)
20953 {
20954 if (!$this->input instanceof StreamableInputInterface) {
20955 throw new \RuntimeException('Setting the user inputs requires at least the version 3.2 of the symfony/console component.');
20956 }
20957
20958 $this->input->setStream($this->createStream($inputs));
20959 $this->input->setInteractive(true);
20960 }
20961
20962 private function createStream(array $inputs)
20963 {
20964 $stream = fopen('php://memory', 'r+', false);
20965
20966 foreach ($inputs as $input) {
20967 fwrite($stream, $input.PHP_EOL);
20968 }
20969
20970 rewind($stream);
20971
20972 return $stream;
20973 }
20974 }
20975 <?php
20976
20977
20978
20979
20980
20981
20982
20983
20984
20985
20986
20987 namespace Composer\IO;
20988
20989 use Composer\Question\StrictConfirmationQuestion;
20990 use Symfony\Component\Console\Helper\HelperSet;
20991 use Symfony\Component\Console\Input\InputInterface;
20992 use Symfony\Component\Console\Output\ConsoleOutputInterface;
20993 use Symfony\Component\Console\Output\OutputInterface;
20994 use Symfony\Component\Console\Question\ChoiceQuestion;
20995 use Symfony\Component\Console\Question\Question;
20996
20997
20998
20999
21000
21001
21002
21003 class ConsoleIO extends BaseIO
21004 {
21005
21006 protected $input;
21007
21008 protected $output;
21009
21010 protected $helperSet;
21011
21012 protected $lastMessage;
21013
21014 protected $lastMessageErr;
21015
21016
21017 private $startTime;
21018
21019 private $verbosityMap;
21020
21021
21022
21023
21024
21025
21026
21027
21028 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
21029 {
21030 $this->input = $input;
21031 $this->output = $output;
21032 $this->helperSet = $helperSet;
21033 $this->verbosityMap = array(
21034 self::QUIET => OutputInterface::VERBOSITY_QUIET,
21035 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
21036 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
21037 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
21038 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
21039 );
21040 }
21041
21042
21043
21044
21045 public function enableDebugging($startTime)
21046 {
21047 $this->startTime = $startTime;
21048 }
21049
21050
21051
21052
21053 public function isInteractive()
21054 {
21055 return $this->input->isInteractive();
21056 }
21057
21058
21059
21060
21061 public function isDecorated()
21062 {
21063 return $this->output->isDecorated();
21064 }
21065
21066
21067
21068
21069 public function isVerbose()
21070 {
21071 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
21072 }
21073
21074
21075
21076
21077 public function isVeryVerbose()
21078 {
21079 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
21080 }
21081
21082
21083
21084
21085 public function isDebug()
21086 {
21087 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
21088 }
21089
21090
21091
21092
21093 public function write($messages, $newline = true, $verbosity = self::NORMAL)
21094 {
21095 $this->doWrite($messages, $newline, false, $verbosity);
21096 }
21097
21098
21099
21100
21101 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
21102 {
21103 $this->doWrite($messages, $newline, true, $verbosity);
21104 }
21105
21106
21107
21108
21109 public function writeRaw($messages, $newline = true, $verbosity = self::NORMAL)
21110 {
21111 $this->doWrite($messages, $newline, false, $verbosity, true);
21112 }
21113
21114
21115
21116
21117 public function writeErrorRaw($messages, $newline = true, $verbosity = self::NORMAL)
21118 {
21119 $this->doWrite($messages, $newline, true, $verbosity, true);
21120 }
21121
21122
21123
21124
21125
21126
21127
21128 private function doWrite($messages, $newline, $stderr, $verbosity, $raw = false)
21129 {
21130 $sfVerbosity = $this->verbosityMap[$verbosity];
21131 if ($sfVerbosity > $this->output->getVerbosity()) {
21132 return;
21133 }
21134
21135
21136  
21137  
21138  if (OutputInterface::VERBOSITY_QUIET === 0) {
21139 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
21140 }
21141
21142 if ($raw) {
21143 if ($sfVerbosity === OutputInterface::OUTPUT_NORMAL) {
21144 $sfVerbosity = OutputInterface::OUTPUT_RAW;
21145 } else {
21146 $sfVerbosity |= OutputInterface::OUTPUT_RAW;
21147 }
21148 }
21149
21150 if (null !== $this->startTime) {
21151 $memoryUsage = memory_get_usage() / 1024 / 1024;
21152 $timeSpent = microtime(true) - $this->startTime;
21153 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
21154 return sprintf('[%.1fMiB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
21155 }, (array) $messages);
21156 }
21157
21158 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
21159 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
21160 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
21161
21162 return;
21163 }
21164
21165 $this->output->write($messages, $newline, $sfVerbosity);
21166 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
21167 }
21168
21169
21170
21171
21172 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
21173 {
21174 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
21175 }
21176
21177
21178
21179
21180 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
21181 {
21182 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
21183 }
21184
21185
21186
21187
21188
21189
21190
21191
21192 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
21193 {
21194
21195  $messages = implode($newline ? "\n" : '', (array) $messages);
21196
21197
21198  if (!isset($size)) {
21199
21200  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
21201 }
21202
21203  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
21204
21205
21206  $this->doWrite($messages, false, $stderr, $verbosity);
21207
21208
21209  
21210  
21211  $fill = $size - strlen(strip_tags($messages));
21212 if ($fill > 0) {
21213
21214  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
21215
21216  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
21217 }
21218
21219 if ($newline) {
21220 $this->doWrite('', true, $stderr, $verbosity);
21221 }
21222
21223 if ($stderr) {
21224 $this->lastMessageErr = $messages;
21225 } else {
21226 $this->lastMessage = $messages;
21227 }
21228 }
21229
21230
21231
21232
21233 public function ask($question, $default = null)
21234 {
21235
21236 $helper = $this->helperSet->get('question');
21237 $question = new Question($question, $default);
21238
21239 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21240 }
21241
21242
21243
21244
21245 public function askConfirmation($question, $default = true)
21246 {
21247
21248 $helper = $this->helperSet->get('question');
21249 $question = new StrictConfirmationQuestion($question, $default);
21250
21251 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21252 }
21253
21254
21255
21256
21257 public function askAndValidate($question, $validator, $attempts = null, $default = null)
21258 {
21259
21260 $helper = $this->helperSet->get('question');
21261 $question = new Question($question, $default);
21262 $question->setValidator($validator);
21263 $question->setMaxAttempts($attempts);
21264
21265 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21266 }
21267
21268
21269
21270
21271 public function askAndHideAnswer($question)
21272 {
21273
21274 $helper = $this->helperSet->get('question');
21275 $question = new Question($question);
21276 $question->setHidden(true);
21277
21278 return $helper->ask($this->input, $this->getErrorOutput(), $question);
21279 }
21280
21281
21282
21283
21284 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
21285 {
21286
21287 $helper = $this->helperSet->get('question');
21288 $question = new ChoiceQuestion($question, $choices, $default);
21289 $question->setMaxAttempts($attempts ?: null); 
21290  $question->setErrorMessage($errorMessage);
21291 $question->setMultiselect($multiselect);
21292
21293 $result = $helper->ask($this->input, $this->getErrorOutput(), $question);
21294
21295 if (!is_array($result)) {
21296 return (string) array_search($result, $choices, true);
21297 }
21298
21299 $results = array();
21300 foreach ($choices as $index => $choice) {
21301 if (in_array($choice, $result, true)) {
21302 $results[] = (string) $index;
21303 }
21304 }
21305
21306 return $results;
21307 }
21308
21309
21310
21311
21312 private function getErrorOutput()
21313 {
21314 if ($this->output instanceof ConsoleOutputInterface) {
21315 return $this->output->getErrorOutput();
21316 }
21317
21318 return $this->output;
21319 }
21320 }
21321 <?php
21322
21323
21324
21325
21326
21327
21328
21329
21330
21331
21332
21333 namespace Composer\IO;
21334
21335 use Composer\Config;
21336
21337
21338
21339
21340
21341
21342 interface IOInterface
21343 {
21344 const QUIET = 1;
21345 const NORMAL = 2;
21346 const VERBOSE = 4;
21347 const VERY_VERBOSE = 8;
21348 const DEBUG = 16;
21349
21350
21351
21352
21353
21354
21355 public function isInteractive();
21356
21357
21358
21359
21360
21361
21362 public function isVerbose();
21363
21364
21365
21366
21367
21368
21369 public function isVeryVerbose();
21370
21371
21372
21373
21374
21375
21376 public function isDebug();
21377
21378
21379
21380
21381
21382
21383 public function isDecorated();
21384
21385
21386
21387
21388
21389
21390
21391
21392 public function write($messages, $newline = true, $verbosity = self::NORMAL);
21393
21394
21395
21396
21397
21398
21399
21400
21401 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
21402
21403
21404
21405
21406
21407
21408
21409
21410
21411 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
21412
21413
21414
21415
21416
21417
21418
21419
21420
21421 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
21422
21423
21424
21425
21426
21427
21428
21429
21430
21431
21432 public function ask($question, $default = null);
21433
21434
21435
21436
21437
21438
21439
21440
21441
21442
21443
21444 public function askConfirmation($question, $default = true);
21445
21446
21447
21448
21449
21450
21451
21452
21453
21454
21455
21456
21457
21458
21459
21460
21461 public function askAndValidate($question, $validator, $attempts = null, $default = null);
21462
21463
21464
21465
21466
21467
21468
21469
21470 public function askAndHideAnswer($question);
21471
21472
21473
21474
21475
21476
21477
21478
21479
21480
21481
21482
21483
21484
21485 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
21486
21487
21488
21489
21490
21491
21492 public function getAuthentications();
21493
21494
21495
21496
21497
21498
21499
21500
21501 public function hasAuthentication($repositoryName);
21502
21503
21504
21505
21506
21507
21508
21509
21510 public function getAuthentication($repositoryName);
21511
21512
21513
21514
21515
21516
21517
21518
21519 public function setAuthentication($repositoryName, $username, $password = null);
21520
21521
21522
21523
21524
21525
21526 public function loadConfiguration(Config $config);
21527 }
21528 <?php
21529
21530
21531
21532
21533
21534
21535
21536
21537
21538
21539
21540 namespace Composer\IO;
21541
21542
21543
21544
21545
21546
21547 class NullIO extends BaseIO
21548 {
21549
21550
21551
21552 public function isInteractive()
21553 {
21554 return false;
21555 }
21556
21557
21558
21559
21560 public function isVerbose()
21561 {
21562 return false;
21563 }
21564
21565
21566
21567
21568 public function isVeryVerbose()
21569 {
21570 return false;
21571 }
21572
21573
21574
21575
21576 public function isDebug()
21577 {
21578 return false;
21579 }
21580
21581
21582
21583
21584 public function isDecorated()
21585 {
21586 return false;
21587 }
21588
21589
21590
21591
21592 public function write($messages, $newline = true, $verbosity = self::NORMAL)
21593 {
21594 }
21595
21596
21597
21598
21599 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
21600 {
21601 }
21602
21603
21604
21605
21606 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
21607 {
21608 }
21609
21610
21611
21612
21613 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
21614 {
21615 }
21616
21617
21618
21619
21620 public function ask($question, $default = null)
21621 {
21622 return $default;
21623 }
21624
21625
21626
21627
21628 public function askConfirmation($question, $default = true)
21629 {
21630 return $default;
21631 }
21632
21633
21634
21635
21636 public function askAndValidate($question, $validator, $attempts = false, $default = null)
21637 {
21638 return $default;
21639 }
21640
21641
21642
21643
21644 public function askAndHideAnswer($question)
21645 {
21646 return null;
21647 }
21648
21649
21650
21651
21652 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
21653 {
21654 return $default;
21655 }
21656 }
21657 <?php
21658
21659
21660
21661
21662
21663
21664
21665
21666
21667
21668
21669 namespace Composer;
21670
21671 use Composer\Autoload\AutoloadGenerator;
21672 use Composer\DependencyResolver\DefaultPolicy;
21673 use Composer\DependencyResolver\Operation\UpdateOperation;
21674 use Composer\DependencyResolver\Operation\InstallOperation;
21675 use Composer\DependencyResolver\Operation\UninstallOperation;
21676 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
21677 use Composer\DependencyResolver\Operation\OperationInterface;
21678 use Composer\DependencyResolver\PolicyInterface;
21679 use Composer\DependencyResolver\Pool;
21680 use Composer\DependencyResolver\Request;
21681 use Composer\DependencyResolver\Rule;
21682 use Composer\DependencyResolver\Solver;
21683 use Composer\DependencyResolver\SolverProblemsException;
21684 use Composer\Downloader\DownloadManager;
21685 use Composer\EventDispatcher\EventDispatcher;
21686 use Composer\Installer\InstallationManager;
21687 use Composer\Installer\InstallerEvents;
21688 use Composer\Installer\NoopInstaller;
21689 use Composer\Installer\SuggestedPackagesReporter;
21690 use Composer\IO\IOInterface;
21691 use Composer\Package\AliasPackage;
21692 use Composer\Package\BasePackage;
21693 use Composer\Package\CompletePackage;
21694 use Composer\Package\CompletePackageInterface;
21695 use Composer\Package\Link;
21696 use Composer\Package\Loader\ArrayLoader;
21697 use Composer\Package\Dumper\ArrayDumper;
21698 use Composer\Semver\Constraint\Constraint;
21699 use Composer\Package\Locker;
21700 use Composer\Package\PackageInterface;
21701 use Composer\Package\RootPackageInterface;
21702 use Composer\Repository\CompositeRepository;
21703 use Composer\Repository\InstalledArrayRepository;
21704 use Composer\Repository\PlatformRepository;
21705 use Composer\Repository\RepositoryInterface;
21706 use Composer\Repository\RepositoryManager;
21707 use Composer\Repository\WritableRepositoryInterface;
21708 use Composer\Script\ScriptEvents;
21709
21710
21711
21712
21713
21714
21715
21716 class Installer
21717 {
21718
21719
21720
21721 protected $io;
21722
21723
21724
21725
21726 protected $config;
21727
21728
21729
21730
21731 protected $package;
21732
21733
21734
21735
21736 protected $downloadManager;
21737
21738
21739
21740
21741 protected $repositoryManager;
21742
21743
21744
21745
21746 protected $locker;
21747
21748
21749
21750
21751 protected $installationManager;
21752
21753
21754
21755
21756 protected $eventDispatcher;
21757
21758
21759
21760
21761 protected $autoloadGenerator;
21762
21763 protected $preferSource = false;
21764 protected $preferDist = false;
21765 protected $optimizeAutoloader = false;
21766 protected $classMapAuthoritative = false;
21767 protected $apcuAutoloader = false;
21768 protected $devMode = false;
21769 protected $dryRun = false;
21770 protected $verbose = false;
21771 protected $update = false;
21772 protected $dumpAutoloader = true;
21773 protected $runScripts = true;
21774 protected $ignorePlatformReqs = false;
21775 protected $preferStable = false;
21776 protected $preferLowest = false;
21777 protected $skipSuggest = false;
21778 protected $writeLock;
21779 protected $executeOperations = true;
21780
21781
21782
21783
21784
21785
21786 protected $updateWhitelist = null;
21787 protected $whitelistDependencies = false; 
21788  protected $whitelistAllDependencies = false;
21789
21790
21791
21792
21793 protected $suggestedPackagesReporter;
21794
21795
21796
21797
21798 protected $additionalInstalledRepository;
21799
21800
21801
21802
21803
21804
21805
21806
21807
21808
21809
21810
21811
21812
21813 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
21814 {
21815 $this->io = $io;
21816 $this->config = $config;
21817 $this->package = $package;
21818 $this->downloadManager = $downloadManager;
21819 $this->repositoryManager = $repositoryManager;
21820 $this->locker = $locker;
21821 $this->installationManager = $installationManager;
21822 $this->eventDispatcher = $eventDispatcher;
21823 $this->autoloadGenerator = $autoloadGenerator;
21824
21825 $this->writeLock = $config->get('lock');
21826 }
21827
21828
21829
21830
21831
21832
21833
21834 public function run()
21835 {
21836
21837  
21838  
21839  
21840  gc_collect_cycles();
21841 gc_disable();
21842
21843
21844  if (!$this->update && !$this->locker->isLocked()) {
21845 $this->update = true;
21846 }
21847
21848 if ($this->dryRun) {
21849 $this->verbose = true;
21850 $this->runScripts = false;
21851 $this->executeOperations = false;
21852 $this->writeLock = false;
21853 $this->dumpAutoloader = false;
21854 $this->installationManager->addInstaller(new NoopInstaller);
21855 $this->mockLocalRepositories($this->repositoryManager);
21856 }
21857
21858 if ($this->runScripts) {
21859 $_SERVER['COMPOSER_DEV_MODE'] = (int) $this->devMode;
21860 putenv('COMPOSER_DEV_MODE='.$_SERVER['COMPOSER_DEV_MODE']);
21861
21862
21863  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
21864 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
21865 }
21866
21867 $this->downloadManager->setPreferSource($this->preferSource);
21868 $this->downloadManager->setPreferDist($this->preferDist);
21869
21870
21871  $localRepo = $this->repositoryManager->getLocalRepository();
21872 if ($this->update) {
21873 $platformOverrides = $this->config->get('platform') ?: array();
21874 } else {
21875 $platformOverrides = $this->locker->getPlatformOverrides();
21876 }
21877 $platformRepo = new PlatformRepository(array(), $platformOverrides);
21878 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
21879
21880 $aliases = $this->getRootAliases();
21881 $this->aliasPlatformPackages($platformRepo, $aliases);
21882
21883 if (!$this->suggestedPackagesReporter) {
21884 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
21885 }
21886
21887 try {
21888 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
21889 if ($res !== 0) {
21890 return $res;
21891 }
21892 } catch (\Exception $e) {
21893 if ($this->executeOperations && $this->config->get('notify-on-install')) {
21894 $this->installationManager->notifyInstalls($this->io);
21895 }
21896
21897 throw $e;
21898 }
21899 if ($this->executeOperations && $this->config->get('notify-on-install')) {
21900 $this->installationManager->notifyInstalls($this->io);
21901 }
21902
21903
21904  if ($this->devMode && !$this->skipSuggest) {
21905 $this->suggestedPackagesReporter->output($installedRepo);
21906 }
21907
21908
21909  foreach ($localRepo->getPackages() as $package) {
21910 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
21911 continue;
21912 }
21913
21914 $replacement = is_string($package->getReplacementPackage())
21915 ? 'Use ' . $package->getReplacementPackage() . ' instead'
21916 : 'No replacement was suggested';
21917
21918 $this->io->writeError(
21919 sprintf(
21920 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
21921 $package->getPrettyName(),
21922 $replacement
21923 )
21924 );
21925 }
21926
21927
21928  if ($this->update && $this->writeLock) {
21929 $localRepo->reload();
21930
21931 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
21932 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
21933
21934 $updatedLock = $this->locker->setLockData(
21935 array_diff($localRepo->getCanonicalPackages(), $devPackages),
21936 $devPackages,
21937 $platformReqs,
21938 $platformDevReqs,
21939 $aliases,
21940 $this->package->getMinimumStability(),
21941 $this->package->getStabilityFlags(),
21942 $this->preferStable || $this->package->getPreferStable(),
21943 $this->preferLowest,
21944 $this->config->get('platform') ?: array()
21945 );
21946 if ($updatedLock) {
21947 $this->io->writeError('<info>Writing lock file</info>');
21948 }
21949 }
21950
21951 if ($this->dumpAutoloader) {
21952
21953  if ($this->optimizeAutoloader) {
21954 $this->io->writeError('<info>Generating optimized autoload files</info>');
21955 } else {
21956 $this->io->writeError('<info>Generating autoload files</info>');
21957 }
21958
21959 $this->autoloadGenerator->setDevMode($this->devMode);
21960 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
21961 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
21962 $this->autoloadGenerator->setRunScripts($this->runScripts);
21963 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
21964 }
21965
21966 if ($this->executeOperations) {
21967
21968  foreach ($localRepo->getPackages() as $package) {
21969 $this->installationManager->ensureBinariesPresence($package);
21970 }
21971 }
21972
21973 $fundingCount = 0;
21974 foreach ($localRepo->getPackages() as $package) {
21975 if ($package instanceof CompletePackageInterface && !$package instanceof AliasPackage && $package->getFunding()) {
21976 $fundingCount++;
21977 }
21978 }
21979 if ($fundingCount) {
21980 $this->io->writeError(array(
21981 sprintf(
21982 "<info>%d package%s you are using %s looking for funding.</info>",
21983 $fundingCount,
21984 1 === $fundingCount ? '' : 's',
21985 1 === $fundingCount ? 'is' : 'are'
21986 ),
21987 '<info>Use the `composer fund` command to find out more!</info>',
21988 ));
21989 }
21990
21991 if ($this->runScripts) {
21992
21993  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
21994 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
21995 }
21996
21997
21998  if (!defined('HHVM_VERSION')) {
21999 gc_enable();
22000 }
22001
22002 return 0;
22003 }
22004
22005
22006
22007
22008
22009
22010
22011
22012 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
22013 {
22014
22015  $lockedRepository = null;
22016 $repositories = null;
22017
22018
22019  
22020  
22021  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
22022 try {
22023 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
22024 } catch (\RuntimeException $e) {
22025
22026  if ($this->package->getDevRequires()) {
22027 throw $e;
22028 }
22029
22030  $lockedRepository = $this->locker->getLockedRepository();
22031 }
22032 }
22033
22034 $this->whitelistUpdateDependencies(
22035 $lockedRepository ?: $localRepo,
22036 $this->package->getRequires(),
22037 $this->package->getDevRequires()
22038 );
22039
22040 $this->io->writeError('<info>Loading composer repositories with package information</info>');
22041
22042
22043  $policy = $this->createPolicy();
22044 $pool = $this->createPool($this->update ? null : $lockedRepository);
22045 $pool->addRepository($installedRepo, $aliases);
22046 if ($this->update) {
22047 $repositories = $this->repositoryManager->getRepositories();
22048 foreach ($repositories as $repository) {
22049 $pool->addRepository($repository, $aliases);
22050 }
22051 }
22052
22053  
22054  
22055  if ($lockedRepository) {
22056 $pool->addRepository($lockedRepository, $aliases);
22057 }
22058
22059
22060  $request = $this->createRequest($this->package, $platformRepo);
22061
22062 if ($this->update) {
22063
22064  $removedUnstablePackages = array();
22065 foreach ($localRepo->getPackages() as $package) {
22066 if (
22067 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
22068 && $this->installationManager->isPackageInstalled($localRepo, $package)
22069 ) {
22070 $removedUnstablePackages[$package->getName()] = true;
22071 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
22072 }
22073 }
22074
22075 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
22076
22077 $request->updateAll();
22078
22079 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
22080
22081 foreach ($links as $link) {
22082 $request->install($link->getTarget(), $link->getConstraint());
22083 }
22084
22085
22086  
22087  if ($this->updateWhitelist) {
22088 $currentPackages = $this->getCurrentPackages($installedRepo);
22089
22090
22091  $candidates = array();
22092 foreach ($links as $link) {
22093 $candidates[$link->getTarget()] = true;
22094 $rootRequires[$link->getTarget()] = $link;
22095 }
22096 foreach ($currentPackages as $package) {
22097 $candidates[$package->getName()] = true;
22098 }
22099
22100
22101  foreach ($candidates as $candidate => $dummy) {
22102 foreach ($currentPackages as $curPackage) {
22103 if ($curPackage->getName() === $candidate) {
22104 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
22105 $constraint = new Constraint('=', $curPackage->getVersion());
22106 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
22107 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
22108 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
22109 $request->install($curPackage->getName(), $constraint);
22110 }
22111 break;
22112 }
22113 }
22114 }
22115 }
22116 } else {
22117 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
22118
22119 if (!$this->locker->isFresh()) {
22120 $this->io->writeError('<warning>Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. It is recommended that you run `composer update` or `composer update <package name>`.</warning>', true, IOInterface::QUIET);
22121 }
22122
22123 foreach ($lockedRepository->getPackages() as $package) {
22124 $version = $package->getVersion();
22125 if (isset($aliases[$package->getName()][$version])) {
22126 $version = $aliases[$package->getName()][$version]['alias_normalized'];
22127 }
22128 $constraint = new Constraint('=', $version);
22129 $constraint->setPrettyString($package->getPrettyVersion());
22130 $request->install($package->getName(), $constraint);
22131 }
22132
22133 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
22134 $request->install($link->getTarget(), $link->getConstraint());
22135 }
22136 }
22137
22138
22139  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
22140
22141
22142  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
22143 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
22144 try {
22145 $operations = $solver->solve($request, $this->ignorePlatformReqs);
22146 $ruleSetSize = $solver->getRuleSetSize();
22147 $solver = null;
22148 } catch (SolverProblemsException $e) {
22149 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
22150 $this->io->writeError($e->getMessage());
22151 if ($this->update && !$this->devMode) {
22152 $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);
22153 }
22154
22155 return array(max(1, $e->getCode()), array());
22156 }
22157
22158
22159  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
22160
22161 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
22162
22163 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
22164 $this->io->writeError("Analyzed ".$ruleSetSize." rules to resolve dependencies", true, IOInterface::VERBOSE);
22165
22166
22167  if (!$operations) {
22168 $this->io->writeError('Nothing to install or update');
22169 }
22170
22171 $operations = $this->movePluginsToFront($operations);
22172 $operations = $this->moveUninstallsToFront($operations);
22173
22174
22175  
22176  if ($this->update) {
22177 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
22178 if (!$this->devMode) {
22179 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
22180 }
22181 } else {
22182 $devPackages = null;
22183 }
22184
22185 if ($operations) {
22186 $installs = $updates = $uninstalls = array();
22187 foreach ($operations as $operation) {
22188 if ($operation instanceof InstallOperation) {
22189 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
22190 } elseif ($operation instanceof UpdateOperation) {
22191 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
22192 } elseif ($operation instanceof UninstallOperation) {
22193 $uninstalls[] = $operation->getPackage()->getPrettyName();
22194 }
22195 }
22196
22197 $this->io->writeError(sprintf(
22198 "<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
22199 count($installs),
22200 1 === count($installs) ? '' : 's',
22201 count($updates),
22202 1 === count($updates) ? '' : 's',
22203 count($uninstalls),
22204 1 === count($uninstalls) ? '' : 's'
22205 ));
22206 if ($installs) {
22207 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
22208 }
22209 if ($updates) {
22210 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
22211 }
22212 if ($uninstalls) {
22213 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
22214 }
22215 }
22216
22217 foreach ($operations as $operation) {
22218
22219  $jobType = $operation->getJobType();
22220 if ('install' === $jobType) {
22221 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
22222 }
22223
22224
22225  if ($this->update) {
22226 $package = null;
22227 if ('update' === $jobType) {
22228 $package = $operation->getTargetPackage();
22229 } elseif ('install' === $jobType) {
22230 $package = $operation->getPackage();
22231 }
22232 if ($package && $package->isDev()) {
22233 $references = $this->package->getReferences();
22234 if (isset($references[$package->getName()])) {
22235 $this->updateInstallReferences($package, $references[$package->getName()]);
22236 }
22237 }
22238 if ('update' === $jobType) {
22239 $targetPackage = $operation->getTargetPackage();
22240 if ($targetPackage->isDev()) {
22241 $initialPackage = $operation->getInitialPackage();
22242 if ($targetPackage->getVersion() === $initialPackage->getVersion()
22243 && (!$targetPackage->getSourceReference() || $targetPackage->getSourceReference() === $initialPackage->getSourceReference())
22244 && (!$targetPackage->getDistReference() || $targetPackage->getDistReference() === $initialPackage->getDistReference())
22245 ) {
22246 $this->io->writeError('  - Skipping update of ' . $targetPackage->getPrettyName() . ' to the same reference-locked version', true, IOInterface::DEBUG);
22247 $this->io->writeError('', true, IOInterface::DEBUG);
22248
22249 continue;
22250 }
22251 }
22252 }
22253 }
22254
22255 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($jobType);
22256 if (defined($event) && $this->runScripts) {
22257 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
22258 }
22259
22260
22261  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
22262 $this->io->writeError('  - ' . $operation);
22263 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
22264 $this->io->writeError('  - ' . $operation);
22265 }
22266
22267 $this->installationManager->execute($localRepo, $operation);
22268
22269
22270  if ($this->verbose && $this->io->isVeryVerbose() && in_array($jobType, array('install', 'update'))) {
22271 $reason = $operation->getReason();
22272 if ($reason instanceof Rule) {
22273 switch ($reason->getReason()) {
22274 case Rule::RULE_JOB_INSTALL:
22275 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
22276 $this->io->writeError('');
22277 break;
22278 case Rule::RULE_PACKAGE_REQUIRES:
22279 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
22280 $this->io->writeError('');
22281 break;
22282 }
22283 }
22284 }
22285
22286 if ($this->executeOperations || $this->writeLock) {
22287 $localRepo->write();
22288 }
22289
22290 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($jobType);
22291 if (defined($event) && $this->runScripts) {
22292 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
22293 }
22294 }
22295
22296 if ($this->executeOperations) {
22297
22298  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
22299 $localRepo->write();
22300 }
22301
22302
22303  if ($operations) {
22304 $vendorDir = $this->config->get('vendor-dir');
22305 if (is_dir($vendorDir)) {
22306
22307  
22308  @touch($vendorDir);
22309 }
22310 }
22311
22312 return array(0, $devPackages);
22313 }
22314
22315
22316
22317
22318
22319
22320
22321
22322
22323
22324
22325 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
22326 {
22327 if (!$this->package->getDevRequires()) {
22328 return array();
22329 }
22330
22331
22332  $tempLocalRepo = clone $localRepo;
22333 foreach ($operations as $operation) {
22334 switch ($operation->getJobType()) {
22335 case 'install':
22336 case 'markAliasInstalled':
22337 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
22338 $tempLocalRepo->addPackage(clone $operation->getPackage());
22339 }
22340 break;
22341
22342 case 'uninstall':
22343 case 'markAliasUninstalled':
22344 $tempLocalRepo->removePackage($operation->getPackage());
22345 break;
22346
22347 case 'update':
22348 $tempLocalRepo->removePackage($operation->getInitialPackage());
22349 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
22350 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
22351 }
22352 break;
22353
22354 default:
22355 throw new \LogicException('Unknown type: '.$operation->getJobType());
22356 }
22357 }
22358
22359
22360  
22361  
22362  $localRepo = new InstalledArrayRepository(array());
22363 $loader = new ArrayLoader(null, true);
22364 $dumper = new ArrayDumper();
22365 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
22366 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
22367 }
22368 unset($tempLocalRepo, $loader, $dumper);
22369
22370 $policy = $this->createPolicy();
22371 $pool = $this->createPool();
22372 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
22373 $pool->addRepository($installedRepo, $aliases);
22374
22375
22376  $request = $this->createRequest($this->package, $platformRepo);
22377 $request->updateAll();
22378 foreach ($this->package->getRequires() as $link) {
22379 $request->install($link->getTarget(), $link->getConstraint());
22380 }
22381
22382
22383  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
22384 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
22385 $ops = $solver->solve($request, $this->ignorePlatformReqs);
22386 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
22387
22388 $devPackages = array();
22389 foreach ($ops as $op) {
22390 if ($op->getJobType() === 'uninstall') {
22391 $devPackages[] = $op->getPackage();
22392 }
22393 }
22394
22395 return $devPackages;
22396 }
22397
22398
22399
22400
22401 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
22402 {
22403 $finalOps = array();
22404 $packagesToSkip = array();
22405 foreach ($devPackages as $pkg) {
22406 $packagesToSkip[$pkg->getName()] = true;
22407 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
22408 if ($installedDevPkg instanceof AliasPackage) {
22409 $finalOps[] = new MarkAliasUninstalledOperation($installedDevPkg, 'non-dev install removing it');
22410 $installedDevPkg = $installedDevPkg->getAliasOf();
22411 }
22412 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
22413 }
22414 }
22415
22416
22417  foreach ($operations as $op) {
22418 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
22419 if (isset($packagesToSkip[$package->getName()])) {
22420 continue;
22421 }
22422
22423 $finalOps[] = $op;
22424 }
22425
22426 return $finalOps;
22427 }
22428
22429
22430
22431
22432
22433
22434
22435
22436
22437
22438
22439
22440
22441
22442 private function movePluginsToFront(array $operations)
22443 {
22444 $pluginsNoDeps = array();
22445 $pluginsWithDeps = array();
22446 $pluginRequires = array();
22447
22448 foreach (array_reverse($operations, true) as $idx => $op) {
22449 if ($op instanceof InstallOperation) {
22450 $package = $op->getPackage();
22451 } elseif ($op instanceof UpdateOperation) {
22452 $package = $op->getTargetPackage();
22453 } else {
22454 continue;
22455 }
22456
22457
22458  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
22459
22460
22461  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
22462
22463  $requires = array_filter(array_keys($package->getRequires()), function ($req) {
22464 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
22465 });
22466
22467
22468  if ($isPlugin && !count($requires)) {
22469
22470  array_unshift($pluginsNoDeps, $op);
22471 } else {
22472
22473  $pluginRequires = array_merge($pluginRequires, $requires);
22474
22475  array_unshift($pluginsWithDeps, $op);
22476 }
22477
22478 unset($operations[$idx]);
22479 }
22480 }
22481
22482 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
22483 }
22484
22485
22486
22487
22488
22489
22490
22491
22492 private function moveUninstallsToFront(array $operations)
22493 {
22494 $uninstOps = array();
22495 foreach ($operations as $idx => $op) {
22496 if ($op instanceof UninstallOperation) {
22497 $uninstOps[] = $op;
22498 unset($operations[$idx]);
22499 }
22500 }
22501
22502 return array_merge($uninstOps, $operations);
22503 }
22504
22505
22506
22507
22508 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
22509 {
22510
22511  
22512  
22513  $installedRootPackage = clone $this->package;
22514 $installedRootPackage->setRequires(array());
22515 $installedRootPackage->setDevRequires(array());
22516
22517 $repos = array(
22518 $localRepo,
22519 new InstalledArrayRepository(array($installedRootPackage)),
22520 $platformRepo,
22521 );
22522 $installedRepo = new CompositeRepository($repos);
22523 if ($this->additionalInstalledRepository) {
22524 $installedRepo->addRepository($this->additionalInstalledRepository);
22525 }
22526
22527 return $installedRepo;
22528 }
22529
22530
22531
22532
22533
22534 private function createPool(RepositoryInterface $lockedRepository = null)
22535 {
22536 if ($this->update) {
22537 $minimumStability = $this->package->getMinimumStability();
22538 $stabilityFlags = $this->package->getStabilityFlags();
22539
22540 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
22541 } else {
22542 $minimumStability = $this->locker->getMinimumStability();
22543 $stabilityFlags = $this->locker->getStabilityFlags();
22544
22545 $requires = array();
22546 foreach ($lockedRepository->getPackages() as $package) {
22547 $constraint = new Constraint('=', $package->getVersion());
22548 $constraint->setPrettyString($package->getPrettyVersion());
22549 $requires[$package->getName()] = $constraint;
22550 }
22551 }
22552
22553 $rootConstraints = array();
22554 foreach ($requires as $req => $constraint) {
22555
22556  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
22557 continue;
22558 }
22559 if ($constraint instanceof Link) {
22560 $rootConstraints[$req] = $constraint->getConstraint();
22561 } else {
22562 $rootConstraints[$req] = $constraint;
22563 }
22564 }
22565
22566 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
22567 }
22568
22569
22570
22571
22572 private function createPolicy()
22573 {
22574 $preferStable = null;
22575 $preferLowest = null;
22576 if (!$this->update) {
22577 $preferStable = $this->locker->getPreferStable();
22578 $preferLowest = $this->locker->getPreferLowest();
22579 }
22580
22581  
22582  if (null === $preferStable) {
22583 $preferStable = $this->preferStable || $this->package->getPreferStable();
22584 }
22585 if (null === $preferLowest) {
22586 $preferLowest = $this->preferLowest;
22587 }
22588
22589 return new DefaultPolicy($preferStable, $preferLowest);
22590 }
22591
22592
22593
22594
22595
22596
22597 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
22598 {
22599 $request = new Request();
22600
22601 $constraint = new Constraint('=', $rootPackage->getVersion());
22602 $constraint->setPrettyString($rootPackage->getPrettyVersion());
22603 $request->install($rootPackage->getName(), $constraint);
22604
22605 $fixedPackages = $platformRepo->getPackages();
22606 if ($this->additionalInstalledRepository) {
22607 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
22608 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
22609 }
22610
22611
22612  
22613  $provided = $rootPackage->getProvides();
22614 foreach ($fixedPackages as $package) {
22615 $constraint = new Constraint('=', $package->getVersion());
22616 $constraint->setPrettyString($package->getPrettyVersion());
22617
22618
22619  if ($package->getRepository() !== $platformRepo
22620 || !isset($provided[$package->getName()])
22621 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
22622 ) {
22623 $request->fix($package->getName(), $constraint);
22624 }
22625 }
22626
22627 return $request;
22628 }
22629
22630
22631
22632
22633
22634
22635
22636
22637
22638
22639
22640
22641 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
22642 {
22643 if ($task === 'force-updates' && null === $operations) {
22644 throw new \InvalidArgumentException('Missing operations argument');
22645 }
22646 if ($task === 'force-links') {
22647 $operations = array();
22648 }
22649
22650 if ($this->update && $this->updateWhitelist) {
22651 $currentPackages = $this->getCurrentPackages($installedRepo);
22652 }
22653
22654 foreach ($localRepo->getCanonicalPackages() as $package) {
22655
22656  if (!$package->isDev()) {
22657 continue;
22658 }
22659
22660
22661  foreach ($operations as $operation) {
22662 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
22663 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
22664 ) {
22665 continue 2;
22666 }
22667 }
22668
22669 if ($this->update) {
22670
22671  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
22672
22673  foreach ($currentPackages as $curPackage) {
22674 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
22675 if ($task === 'force-links') {
22676 $package->setRequires($curPackage->getRequires());
22677 $package->setConflicts($curPackage->getConflicts());
22678 $package->setProvides($curPackage->getProvides());
22679 $package->setReplaces($curPackage->getReplaces());
22680 } elseif ($task === 'force-updates') {
22681 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
22682 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
22683 ) {
22684 $operations[] = new UpdateOperation($package, $curPackage);
22685 }
22686 }
22687
22688 break;
22689 }
22690 }
22691
22692 continue;
22693 }
22694
22695
22696  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
22697 foreach ($matches as $index => $match) {
22698
22699  if (!in_array($match->getRepository(), $repositories, true)) {
22700 unset($matches[$index]);
22701 continue;
22702 }
22703
22704
22705  if ($match->getName() !== $package->getName()) {
22706 unset($matches[$index]);
22707 continue;
22708 }
22709
22710 $matches[$index] = $match->getId();
22711 }
22712
22713
22714  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
22715 $newPackage = $pool->literalToPackage($matches[0]);
22716
22717 if ($task === 'force-links' && $newPackage) {
22718 $package->setRequires($newPackage->getRequires());
22719 $package->setConflicts($newPackage->getConflicts());
22720 $package->setProvides($newPackage->getProvides());
22721 $package->setReplaces($newPackage->getReplaces());
22722 }
22723
22724 if (
22725 $task === 'force-updates'
22726 && $newPackage
22727 && (
22728 ($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
22729 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
22730 )
22731 ) {
22732 $operations[] = new UpdateOperation($package, $newPackage);
22733
22734 continue;
22735 }
22736 }
22737
22738 if ($task === 'force-updates') {
22739
22740  $references = $this->package->getReferences();
22741
22742 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
22743
22744  $operations[] = new UpdateOperation($package, clone $package);
22745 }
22746 }
22747 } else {
22748
22749  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
22750 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
22751 if ($task === 'force-links') {
22752 $package->setRequires($lockedPackage->getRequires());
22753 $package->setConflicts($lockedPackage->getConflicts());
22754 $package->setProvides($lockedPackage->getProvides());
22755 $package->setReplaces($lockedPackage->getReplaces());
22756 } elseif ($task === 'force-updates') {
22757 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
22758 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
22759 ) {
22760 $operations[] = new UpdateOperation($package, $lockedPackage);
22761 }
22762 }
22763
22764 break;
22765 }
22766 }
22767 }
22768 }
22769
22770 return $operations;
22771 }
22772
22773
22774
22775
22776
22777
22778 private function getCurrentPackages($installedRepo)
22779 {
22780 if ($this->locker->isLocked()) {
22781 try {
22782 return $this->locker->getLockedRepository(true)->getPackages();
22783 } catch (\RuntimeException $e) {
22784
22785  return $this->locker->getLockedRepository()->getPackages();
22786 }
22787 }
22788
22789 return $installedRepo->getPackages();
22790 }
22791
22792
22793
22794
22795 private function getRootAliases()
22796 {
22797 if ($this->update) {
22798 $aliases = $this->package->getAliases();
22799 } else {
22800 $aliases = $this->locker->getAliases();
22801 }
22802
22803 $normalizedAliases = array();
22804
22805 foreach ($aliases as $alias) {
22806 $normalizedAliases[$alias['package']][$alias['version']] = array(
22807 'alias' => $alias['alias'],
22808 'alias_normalized' => $alias['alias_normalized'],
22809 );
22810 }
22811
22812 return $normalizedAliases;
22813 }
22814
22815
22816
22817
22818
22819
22820
22821 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
22822 {
22823 if (!$this->update) {
22824 return;
22825 }
22826
22827 $rootRefs = $this->package->getReferences();
22828
22829 foreach ($localRepo->getCanonicalPackages() as $package) {
22830
22831  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
22832 foreach ($matches as $index => $match) {
22833
22834  if (!in_array($match->getRepository(), $repositories, true)) {
22835 unset($matches[$index]);
22836 continue;
22837 }
22838
22839
22840  if ($match->getName() !== $package->getName()) {
22841 unset($matches[$index]);
22842 continue;
22843 }
22844
22845 $matches[$index] = $match->getId();
22846 }
22847
22848
22849  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
22850 $newPackage = $pool->literalToPackage($matches[0]);
22851
22852
22853  $sourceUrl = $package->getSourceUrl();
22854 $newSourceUrl = $newPackage->getSourceUrl();
22855 $newReference = $newPackage->getSourceReference();
22856
22857 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
22858 $newReference = $rootRefs[$package->getName()];
22859 }
22860
22861 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl(), $newPackage->getDistType(), $newPackage->getDistSha1Checksum());
22862
22863 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
22864 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
22865 }
22866
22867 $package->setDistMirrors($newPackage->getDistMirrors());
22868 $package->setSourceMirrors($newPackage->getSourceMirrors());
22869 $package->setTransportOptions($newPackage->getTransportOptions());
22870 }
22871 }
22872 }
22873
22874 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl, $distType, $distShaSum)
22875 {
22876 $oldSourceRef = $package->getSourceReference();
22877
22878 if ($package->getSourceUrl() !== $sourceUrl) {
22879 $package->setSourceType($sourceType);
22880 $package->setSourceUrl($sourceUrl);
22881 $package->setSourceReference($sourceReference);
22882 }
22883
22884
22885  
22886  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $distUrl)) {
22887 $package->setDistUrl($distUrl);
22888 $package->setDistType($distType);
22889 $package->setDistSha1Checksum($distShaSum);
22890 $this->updateInstallReferences($package, $sourceReference);
22891 }
22892
22893 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
22894 $this->updateInstallReferences($package, $oldSourceRef);
22895 }
22896 }
22897
22898 private function updateInstallReferences(PackageInterface $package, $reference)
22899 {
22900 if (!$reference) {
22901 return;
22902 }
22903
22904 $package->setSourceReference($reference);
22905
22906 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $package->getDistUrl())) {
22907 $package->setDistReference($reference);
22908 $package->setDistUrl(preg_replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
22909 } elseif ($package->getDistReference()) { 
22910  $package->setDistReference($reference);
22911 }
22912 }
22913
22914
22915
22916
22917
22918 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
22919 {
22920 foreach ($aliases as $package => $versions) {
22921 foreach ($versions as $version => $alias) {
22922 $packages = $platformRepo->findPackages($package, $version);
22923 foreach ($packages as $package) {
22924 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
22925 $aliasPackage->setRootPackageAlias(true);
22926 $platformRepo->addPackage($aliasPackage);
22927 }
22928 }
22929 }
22930 }
22931
22932
22933
22934
22935
22936 private function isUpdateable(PackageInterface $package)
22937 {
22938 if (!$this->updateWhitelist) {
22939 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
22940 }
22941
22942 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
22943 $patternRegexp = BasePackage::packageNameToRegexp($whiteListedPattern);
22944 if (preg_match($patternRegexp, $package->getName())) {
22945 return true;
22946 }
22947 }
22948
22949 return false;
22950 }
22951
22952
22953
22954
22955
22956 private function extractPlatformRequirements($links)
22957 {
22958 $platformReqs = array();
22959 foreach ($links as $link) {
22960 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
22961 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
22962 }
22963 }
22964
22965 return $platformReqs;
22966 }
22967
22968
22969
22970
22971
22972
22973
22974
22975
22976
22977
22978
22979
22980
22981 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
22982 {
22983 if (!$this->updateWhitelist) {
22984 return;
22985 }
22986
22987 $rootRequires = array_merge($rootRequires, $rootDevRequires);
22988
22989 $skipPackages = array();
22990 if (!$this->whitelistAllDependencies) {
22991 foreach ($rootRequires as $require) {
22992 $skipPackages[$require->getTarget()] = true;
22993 }
22994 }
22995
22996 $pool = new Pool('dev');
22997 $pool->addRepository($localOrLockRepo);
22998
22999 $seen = array();
23000
23001 $rootRequiredPackageNames = array_keys($rootRequires);
23002
23003 foreach ($this->updateWhitelist as $packageName => $void) {
23004 $packageQueue = new \SplQueue;
23005 $nameMatchesRequiredPackage = false;
23006
23007 $depPackages = $pool->whatProvides($packageName);
23008 $matchesByPattern = array();
23009
23010  if (empty($depPackages)) {
23011
23012  $whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$');
23013 foreach ($localOrLockRepo->search($whitelistPatternSearchRegexp) as $installedPackage) {
23014 $matchesByPattern[] = $pool->whatProvides($installedPackage['name']);
23015 }
23016
23017
23018  $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName);
23019 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
23020 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
23021 $nameMatchesRequiredPackage = true;
23022 break;
23023 }
23024 }
23025 }
23026
23027 if (!empty($matchesByPattern)) {
23028 $depPackages = array_merge($depPackages, call_user_func_array('array_merge', $matchesByPattern));
23029 }
23030
23031 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
23032 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
23033 }
23034
23035 foreach ($depPackages as $depPackage) {
23036 $packageQueue->enqueue($depPackage);
23037 }
23038
23039 while (!$packageQueue->isEmpty()) {
23040 $package = $packageQueue->dequeue();
23041 if (isset($seen[$package->getId()])) {
23042 continue;
23043 }
23044
23045 $seen[$package->getId()] = true;
23046 $this->updateWhitelist[$package->getName()] = true;
23047
23048 if (!$this->whitelistDependencies && !$this->whitelistAllDependencies) {
23049 continue;
23050 }
23051
23052 $requires = $package->getRequires();
23053
23054 foreach ($requires as $require) {
23055 $requirePackages = $pool->whatProvides($require->getTarget());
23056
23057 foreach ($requirePackages as $requirePackage) {
23058 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
23059 continue;
23060 }
23061
23062 if (isset($skipPackages[$requirePackage->getName()]) && !preg_match(BasePackage::packageNameToRegexp($packageName), $requirePackage->getName())) {
23063 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
23064 continue;
23065 }
23066
23067 $packageQueue->enqueue($requirePackage);
23068 }
23069 }
23070 }
23071 }
23072 }
23073
23074
23075
23076
23077
23078
23079
23080
23081 private function mockLocalRepositories(RepositoryManager $rm)
23082 {
23083 $packages = array();
23084 foreach ($rm->getLocalRepository()->getPackages() as $package) {
23085 $packages[(string) $package] = clone $package;
23086 }
23087 foreach ($packages as $key => $package) {
23088 if ($package instanceof AliasPackage) {
23089 $alias = (string) $package->getAliasOf();
23090 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
23091 }
23092 }
23093 $rm->setLocalRepository(
23094 new InstalledArrayRepository($packages)
23095 );
23096 }
23097
23098
23099
23100
23101
23102
23103
23104
23105 public static function create(IOInterface $io, Composer $composer)
23106 {
23107 return new static(
23108 $io,
23109 $composer->getConfig(),
23110 $composer->getPackage(),
23111 $composer->getDownloadManager(),
23112 $composer->getRepositoryManager(),
23113 $composer->getLocker(),
23114 $composer->getInstallationManager(),
23115 $composer->getEventDispatcher(),
23116 $composer->getAutoloadGenerator()
23117 );
23118 }
23119
23120
23121
23122
23123
23124 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
23125 {
23126 $this->additionalInstalledRepository = $additionalInstalledRepository;
23127
23128 return $this;
23129 }
23130
23131
23132
23133
23134
23135
23136
23137 public function setDryRun($dryRun = true)
23138 {
23139 $this->dryRun = (bool) $dryRun;
23140
23141 return $this;
23142 }
23143
23144
23145
23146
23147
23148
23149 public function isDryRun()
23150 {
23151 return $this->dryRun;
23152 }
23153
23154
23155
23156
23157
23158
23159
23160 public function setPreferSource($preferSource = true)
23161 {
23162 $this->preferSource = (bool) $preferSource;
23163
23164 return $this;
23165 }
23166
23167
23168
23169
23170
23171
23172
23173 public function setPreferDist($preferDist = true)
23174 {
23175 $this->preferDist = (bool) $preferDist;
23176
23177 return $this;
23178 }
23179
23180
23181
23182
23183
23184
23185
23186 public function setOptimizeAutoloader($optimizeAutoloader = false)
23187 {
23188 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
23189 if (!$this->optimizeAutoloader) {
23190
23191  
23192  $this->setClassMapAuthoritative(false);
23193 }
23194
23195 return $this;
23196 }
23197
23198
23199
23200
23201
23202
23203
23204
23205 public function setClassMapAuthoritative($classMapAuthoritative = false)
23206 {
23207 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
23208 if ($this->classMapAuthoritative) {
23209
23210  $this->setOptimizeAutoloader(true);
23211 }
23212
23213 return $this;
23214 }
23215
23216
23217
23218
23219
23220
23221
23222 public function setApcuAutoloader($apcuAutoloader = false)
23223 {
23224 $this->apcuAutoloader = (bool) $apcuAutoloader;
23225
23226 return $this;
23227 }
23228
23229
23230
23231
23232
23233
23234
23235 public function setUpdate($update = true)
23236 {
23237 $this->update = (bool) $update;
23238
23239 return $this;
23240 }
23241
23242
23243
23244
23245
23246
23247
23248 public function setDevMode($devMode = true)
23249 {
23250 $this->devMode = (bool) $devMode;
23251
23252 return $this;
23253 }
23254
23255
23256
23257
23258
23259
23260
23261
23262
23263 public function setDumpAutoloader($dumpAutoloader = true)
23264 {
23265 $this->dumpAutoloader = (bool) $dumpAutoloader;
23266
23267 return $this;
23268 }
23269
23270
23271
23272
23273
23274
23275
23276
23277
23278 public function setRunScripts($runScripts = true)
23279 {
23280 $this->runScripts = (bool) $runScripts;
23281
23282 return $this;
23283 }
23284
23285
23286
23287
23288
23289
23290
23291 public function setConfig(Config $config)
23292 {
23293 $this->config = $config;
23294
23295 return $this;
23296 }
23297
23298
23299
23300
23301
23302
23303
23304 public function setVerbose($verbose = true)
23305 {
23306 $this->verbose = (bool) $verbose;
23307
23308 return $this;
23309 }
23310
23311
23312
23313
23314
23315
23316 public function isVerbose()
23317 {
23318 return $this->verbose;
23319 }
23320
23321
23322
23323
23324
23325
23326
23327 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
23328 {
23329 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
23330
23331 return $this;
23332 }
23333
23334
23335
23336
23337
23338
23339
23340
23341 public function setUpdateWhitelist(array $packages)
23342 {
23343 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
23344
23345 return $this;
23346 }
23347
23348
23349
23350
23351 public function setWhitelistDependencies($updateDependencies = true)
23352 {
23353 return $this->setWhitelistTransitiveDependencies($updateDependencies);
23354 }
23355
23356
23357
23358
23359
23360
23361
23362
23363
23364
23365 public function setWhitelistTransitiveDependencies($updateTransitiveDependencies = true)
23366 {
23367 $this->whitelistDependencies = (bool) $updateTransitiveDependencies;
23368
23369 return $this;
23370 }
23371
23372
23373
23374
23375
23376
23377
23378
23379
23380
23381 public function setWhitelistAllDependencies($updateAllDependencies = true)
23382 {
23383 $this->whitelistAllDependencies = (bool) $updateAllDependencies;
23384
23385 return $this;
23386 }
23387
23388
23389
23390
23391
23392
23393
23394 public function setPreferStable($preferStable = true)
23395 {
23396 $this->preferStable = (bool) $preferStable;
23397
23398 return $this;
23399 }
23400
23401
23402
23403
23404
23405
23406
23407 public function setPreferLowest($preferLowest = true)
23408 {
23409 $this->preferLowest = (bool) $preferLowest;
23410
23411 return $this;
23412 }
23413
23414
23415
23416
23417
23418
23419
23420
23421
23422 public function setWriteLock($writeLock = true)
23423 {
23424 $this->writeLock = (bool) $writeLock;
23425
23426 return $this;
23427 }
23428
23429
23430
23431
23432
23433
23434
23435
23436
23437 public function setExecuteOperations($executeOperations = true)
23438 {
23439 $this->executeOperations = (bool) $executeOperations;
23440
23441 return $this;
23442 }
23443
23444
23445
23446
23447
23448
23449
23450 public function setSkipSuggest($skipSuggest = true)
23451 {
23452 $this->skipSuggest = (bool) $skipSuggest;
23453
23454 return $this;
23455 }
23456
23457
23458
23459
23460
23461
23462
23463
23464
23465
23466 public function disablePlugins()
23467 {
23468 $this->installationManager->disablePlugins();
23469
23470 return $this;
23471 }
23472
23473
23474
23475
23476
23477 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
23478 {
23479 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
23480
23481 return $this;
23482 }
23483 }
23484 <?php
23485
23486
23487
23488
23489
23490
23491
23492
23493
23494
23495
23496 namespace Composer\Installer;
23497
23498 use Composer\IO\IOInterface;
23499 use Composer\Package\PackageInterface;
23500 use Composer\Util\Filesystem;
23501 use Composer\Util\Platform;
23502 use Composer\Util\ProcessExecutor;
23503 use Composer\Util\Silencer;
23504
23505
23506
23507
23508
23509
23510
23511
23512 class BinaryInstaller
23513 {
23514 protected $binDir;
23515 protected $binCompat;
23516 protected $io;
23517 protected $filesystem;
23518
23519
23520
23521
23522
23523
23524
23525 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
23526 {
23527 $this->binDir = $binDir;
23528 $this->binCompat = $binCompat;
23529 $this->io = $io;
23530 $this->filesystem = $filesystem ?: new Filesystem();
23531 }
23532
23533 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
23534 {
23535 $binaries = $this->getBinaries($package);
23536 if (!$binaries) {
23537 return;
23538 }
23539 foreach ($binaries as $bin) {
23540 $binPath = $installPath.'/'.$bin;
23541 if (!file_exists($binPath)) {
23542 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
23543 continue;
23544 }
23545
23546
23547  
23548  
23549  
23550  $binPath = realpath($binPath);
23551
23552 $this->initializeBinDir();
23553 $link = $this->binDir.'/'.basename($bin);
23554 if (file_exists($link)) {
23555 if (is_link($link)) {
23556
23557  
23558  
23559  Silencer::call('chmod', $link, 0777 & ~umask());
23560 }
23561 if ($warnOnOverwrite) {
23562 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
23563 }
23564 continue;
23565 }
23566
23567 if ($this->binCompat === "auto") {
23568 if (Platform::isWindows()) {
23569 $this->installFullBinaries($binPath, $link, $bin, $package);
23570 } else {
23571 $this->installSymlinkBinaries($binPath, $link);
23572 }
23573 } elseif ($this->binCompat === "full") {
23574 $this->installFullBinaries($binPath, $link, $bin, $package);
23575 }
23576 Silencer::call('chmod', $link, 0777 & ~umask());
23577 }
23578 }
23579
23580 public function removeBinaries(PackageInterface $package)
23581 {
23582 $this->initializeBinDir();
23583
23584 $binaries = $this->getBinaries($package);
23585 if (!$binaries) {
23586 return;
23587 }
23588 foreach ($binaries as $bin) {
23589 $link = $this->binDir.'/'.basename($bin);
23590 if (is_link($link) || file_exists($link)) {
23591 $this->filesystem->unlink($link);
23592 }
23593 if (file_exists($link.'.bat')) {
23594 $this->filesystem->unlink($link.'.bat');
23595 }
23596 }
23597
23598
23599  if (is_dir($this->binDir) && $this->filesystem->isDirEmpty($this->binDir)) {
23600 Silencer::call('rmdir', $this->binDir);
23601 }
23602 }
23603
23604 public static function determineBinaryCaller($bin)
23605 {
23606 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
23607 return 'call';
23608 }
23609
23610 $handle = fopen($bin, 'r');
23611 $line = fgets($handle);
23612 fclose($handle);
23613 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
23614 return trim($match[1]);
23615 }
23616
23617 return 'php';
23618 }
23619
23620 protected function getBinaries(PackageInterface $package)
23621 {
23622 return $package->getBinaries();
23623 }
23624
23625 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
23626 {
23627
23628  if ('.bat' !== substr($binPath, -4)) {
23629 $this->installUnixyProxyBinaries($binPath, $link);
23630 @chmod($link, 0777 & ~umask());
23631 $link .= '.bat';
23632 if (file_exists($link)) {
23633 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
23634 }
23635 }
23636 if (!file_exists($link)) {
23637 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
23638 }
23639 }
23640
23641 protected function installSymlinkBinaries($binPath, $link)
23642 {
23643 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
23644 $this->installUnixyProxyBinaries($binPath, $link);
23645 }
23646 }
23647
23648 protected function installUnixyProxyBinaries($binPath, $link)
23649 {
23650 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
23651 }
23652
23653 protected function initializeBinDir()
23654 {
23655 $this->filesystem->ensureDirectoryExists($this->binDir);
23656 $this->binDir = realpath($this->binDir);
23657 }
23658
23659 protected function generateWindowsProxyCode($bin, $link)
23660 {
23661 $binPath = $this->filesystem->findShortestPath($link, $bin);
23662 $caller = self::determineBinaryCaller($bin);
23663
23664 return "@ECHO OFF\r\n".
23665 "setlocal DISABLEDELAYEDEXPANSION\r\n".
23666 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
23667 "{$caller} \"%BIN_TARGET%\" %*\r\n";
23668 }
23669
23670 protected function generateUnixyProxyCode($bin, $link)
23671 {
23672 $binPath = $this->filesystem->findShortestPath($link, $bin);
23673
23674 $binDir = ProcessExecutor::escape(dirname($binPath));
23675 $binFile = basename($binPath);
23676
23677 $proxyCode = <<<PROXY
23678 #!/usr/bin/env sh
23679
23680 dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
23681
23682 if [ -d /proc/cygdrive ]; then
23683     case \$(which php) in
23684         \$(readlink -n /proc/cygdrive)/*)
23685             # We are in Cygwin using Windows php, so the path must be translated
23686             dir=\$(cygpath -m "\$dir");
23687             ;;
23688     esac
23689 fi
23690
23691 "\${dir}/$binFile" "\$@"
23692
23693 PROXY;
23694
23695 return $proxyCode;
23696 }
23697 }
23698 <?php
23699
23700
23701
23702
23703
23704
23705
23706
23707
23708
23709
23710 namespace Composer\Installer;
23711
23712 use Composer\Package\PackageInterface;
23713
23714
23715
23716
23717
23718
23719 interface BinaryPresenceInterface
23720 {
23721
23722
23723
23724
23725
23726 public function ensureBinariesPresence(PackageInterface $package);
23727 }
23728 <?php
23729
23730
23731
23732
23733
23734
23735
23736
23737
23738
23739
23740 namespace Composer\Installer;
23741
23742 use Composer\IO\IOInterface;
23743 use Composer\Package\PackageInterface;
23744 use Composer\Package\AliasPackage;
23745 use Composer\Repository\RepositoryInterface;
23746 use Composer\Repository\InstalledRepositoryInterface;
23747 use Composer\DependencyResolver\Operation\OperationInterface;
23748 use Composer\DependencyResolver\Operation\InstallOperation;
23749 use Composer\DependencyResolver\Operation\UpdateOperation;
23750 use Composer\DependencyResolver\Operation\UninstallOperation;
23751 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
23752 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
23753 use Composer\Util\StreamContextFactory;
23754
23755
23756
23757
23758
23759
23760
23761
23762 class InstallationManager
23763 {
23764 private $installers = array();
23765 private $cache = array();
23766 private $notifiablePackages = array();
23767
23768 public function reset()
23769 {
23770 $this->notifiablePackages = array();
23771 }
23772
23773
23774
23775
23776
23777
23778 public function addInstaller(InstallerInterface $installer)
23779 {
23780 array_unshift($this->installers, $installer);
23781 $this->cache = array();
23782 }
23783
23784
23785
23786
23787
23788
23789 public function removeInstaller(InstallerInterface $installer)
23790 {
23791 if (false !== ($key = array_search($installer, $this->installers, true))) {
23792 array_splice($this->installers, $key, 1);
23793 $this->cache = array();
23794 }
23795 }
23796
23797
23798
23799
23800
23801
23802
23803
23804 public function disablePlugins()
23805 {
23806 foreach ($this->installers as $i => $installer) {
23807 if (!$installer instanceof PluginInstaller) {
23808 continue;
23809 }
23810
23811 unset($this->installers[$i]);
23812 }
23813 }
23814
23815
23816
23817
23818
23819
23820
23821
23822
23823 public function getInstaller($type)
23824 {
23825 $type = strtolower($type);
23826
23827 if (isset($this->cache[$type])) {
23828 return $this->cache[$type];
23829 }
23830
23831 foreach ($this->installers as $installer) {
23832 if ($installer->supports($type)) {
23833 return $this->cache[$type] = $installer;
23834 }
23835 }
23836
23837 throw new \InvalidArgumentException('Unknown installer type: '.$type);
23838 }
23839
23840
23841
23842
23843
23844
23845
23846
23847
23848 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23849 {
23850 if ($package instanceof AliasPackage) {
23851 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
23852 }
23853
23854 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
23855 }
23856
23857
23858
23859
23860
23861
23862
23863 public function ensureBinariesPresence(PackageInterface $package)
23864 {
23865 try {
23866 $installer = $this->getInstaller($package->getType());
23867 } catch (\InvalidArgumentException $e) {
23868
23869  return;
23870 }
23871
23872
23873  if ($installer instanceof BinaryPresenceInterface) {
23874 $installer->ensureBinariesPresence($package);
23875 }
23876 }
23877
23878
23879
23880
23881
23882
23883
23884 public function execute(RepositoryInterface $repo, OperationInterface $operation)
23885 {
23886 $method = $operation->getJobType();
23887 $this->$method($repo, $operation);
23888 }
23889
23890
23891
23892
23893
23894
23895
23896 public function install(RepositoryInterface $repo, InstallOperation $operation)
23897 {
23898 $package = $operation->getPackage();
23899 $installer = $this->getInstaller($package->getType());
23900 $installer->install($repo, $package);
23901 $this->markForNotification($package);
23902 }
23903
23904
23905
23906
23907
23908
23909
23910 public function update(RepositoryInterface $repo, UpdateOperation $operation)
23911 {
23912 $initial = $operation->getInitialPackage();
23913 $target = $operation->getTargetPackage();
23914
23915 $initialType = $initial->getType();
23916 $targetType = $target->getType();
23917
23918 if ($initialType === $targetType) {
23919 $installer = $this->getInstaller($initialType);
23920 $installer->update($repo, $initial, $target);
23921 $this->markForNotification($target);
23922 } else {
23923 $this->getInstaller($initialType)->uninstall($repo, $initial);
23924 $this->getInstaller($targetType)->install($repo, $target);
23925 }
23926 }
23927
23928
23929
23930
23931
23932
23933
23934 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
23935 {
23936 $package = $operation->getPackage();
23937 $installer = $this->getInstaller($package->getType());
23938 $installer->uninstall($repo, $package);
23939 }
23940
23941
23942
23943
23944
23945
23946
23947 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
23948 {
23949 $package = $operation->getPackage();
23950
23951 if (!$repo->hasPackage($package)) {
23952 $repo->addPackage(clone $package);
23953 }
23954 }
23955
23956
23957
23958
23959
23960
23961
23962 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
23963 {
23964 $package = $operation->getPackage();
23965
23966 $repo->removePackage($package);
23967 }
23968
23969
23970
23971
23972
23973
23974
23975 public function getInstallPath(PackageInterface $package)
23976 {
23977 $installer = $this->getInstaller($package->getType());
23978
23979 return $installer->getInstallPath($package);
23980 }
23981
23982 public function notifyInstalls(IOInterface $io)
23983 {
23984 foreach ($this->notifiablePackages as $repoUrl => $packages) {
23985 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
23986 if ($io->hasAuthentication($repositoryName)) {
23987 $auth = $io->getAuthentication($repositoryName);
23988 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
23989 $authHeader = 'Authorization: Basic '.$authStr;
23990 }
23991
23992
23993  if (strpos($repoUrl, '%package%')) {
23994 foreach ($packages as $package) {
23995 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
23996
23997 $params = array(
23998 'version' => $package->getPrettyVersion(),
23999 'version_normalized' => $package->getVersion(),
24000 );
24001 $opts = array('http' =>
24002 array(
24003 'method' => 'POST',
24004 'header' => array('Content-type: application/x-www-form-urlencoded'),
24005 'content' => http_build_query($params, '', '&'),
24006 'timeout' => 3,
24007 ),
24008 );
24009 if (isset($authHeader)) {
24010 $opts['http']['header'][] = $authHeader;
24011 }
24012
24013 $context = StreamContextFactory::getContext($url, $opts);
24014 @file_get_contents($url, false, $context);
24015 }
24016
24017 continue;
24018 }
24019
24020 $postData = array('downloads' => array());
24021 foreach ($packages as $package) {
24022 $postData['downloads'][] = array(
24023 'name' => $package->getPrettyName(),
24024 'version' => $package->getVersion(),
24025 );
24026 }
24027
24028 $opts = array('http' =>
24029 array(
24030 'method' => 'POST',
24031 'header' => array('Content-Type: application/json'),
24032 'content' => json_encode($postData),
24033 'timeout' => 6,
24034 ),
24035 );
24036 if (isset($authHeader)) {
24037 $opts['http']['header'][] = $authHeader;
24038 }
24039
24040 $context = StreamContextFactory::getContext($repoUrl, $opts);
24041 @file_get_contents($repoUrl, false, $context);
24042 }
24043
24044 $this->reset();
24045 }
24046
24047 private function markForNotification(PackageInterface $package)
24048 {
24049 if ($package->getNotificationUrl()) {
24050 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
24051 }
24052 }
24053 }
24054 <?php
24055
24056
24057
24058
24059
24060
24061
24062
24063
24064
24065
24066 namespace Composer\Installer;
24067
24068 use Composer\Composer;
24069 use Composer\DependencyResolver\PolicyInterface;
24070 use Composer\DependencyResolver\Operation\OperationInterface;
24071 use Composer\DependencyResolver\Pool;
24072 use Composer\DependencyResolver\Request;
24073 use Composer\EventDispatcher\Event;
24074 use Composer\IO\IOInterface;
24075 use Composer\Repository\CompositeRepository;
24076
24077
24078
24079
24080
24081
24082 class InstallerEvent extends Event
24083 {
24084
24085
24086
24087 private $composer;
24088
24089
24090
24091
24092 private $io;
24093
24094
24095
24096
24097 private $devMode;
24098
24099
24100
24101
24102 private $policy;
24103
24104
24105
24106
24107 private $pool;
24108
24109
24110
24111
24112 private $installedRepo;
24113
24114
24115
24116
24117 private $request;
24118
24119
24120
24121
24122 private $operations;
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
24138 {
24139 parent::__construct($eventName);
24140
24141 $this->composer = $composer;
24142 $this->io = $io;
24143 $this->devMode = $devMode;
24144 $this->policy = $policy;
24145 $this->pool = $pool;
24146 $this->installedRepo = $installedRepo;
24147 $this->request = $request;
24148 $this->operations = $operations;
24149 }
24150
24151
24152
24153
24154 public function getComposer()
24155 {
24156 return $this->composer;
24157 }
24158
24159
24160
24161
24162 public function getIO()
24163 {
24164 return $this->io;
24165 }
24166
24167
24168
24169
24170 public function isDevMode()
24171 {
24172 return $this->devMode;
24173 }
24174
24175
24176
24177
24178 public function getPolicy()
24179 {
24180 return $this->policy;
24181 }
24182
24183
24184
24185
24186 public function getPool()
24187 {
24188 return $this->pool;
24189 }
24190
24191
24192
24193
24194 public function getInstalledRepo()
24195 {
24196 return $this->installedRepo;
24197 }
24198
24199
24200
24201
24202 public function getRequest()
24203 {
24204 return $this->request;
24205 }
24206
24207
24208
24209
24210 public function getOperations()
24211 {
24212 return $this->operations;
24213 }
24214 }
24215 <?php
24216
24217
24218
24219
24220
24221
24222
24223
24224
24225
24226
24227 namespace Composer\Installer;
24228
24229
24230
24231
24232
24233
24234 class InstallerEvents
24235 {
24236
24237
24238
24239
24240
24241
24242
24243
24244
24245 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
24246
24247
24248
24249
24250
24251
24252
24253
24254
24255
24256 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
24257 }
24258 <?php
24259
24260
24261
24262
24263
24264
24265
24266
24267
24268
24269
24270 namespace Composer\Installer;
24271
24272 use Composer\Package\PackageInterface;
24273 use Composer\Repository\InstalledRepositoryInterface;
24274 use InvalidArgumentException;
24275
24276
24277
24278
24279
24280
24281
24282 interface InstallerInterface
24283 {
24284
24285
24286
24287
24288
24289
24290 public function supports($packageType);
24291
24292
24293
24294
24295
24296
24297
24298
24299
24300 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
24301
24302
24303
24304
24305
24306
24307
24308 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
24309
24310
24311
24312
24313
24314
24315
24316
24317
24318
24319 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
24320
24321
24322
24323
24324
24325
24326
24327 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
24328
24329
24330
24331
24332
24333
24334
24335 public function getInstallPath(PackageInterface $package);
24336 }
24337 <?php
24338
24339
24340
24341
24342
24343
24344
24345
24346
24347
24348
24349 namespace Composer\Installer;
24350
24351 use Composer\Composer;
24352 use Composer\IO\IOInterface;
24353 use Composer\Repository\InstalledRepositoryInterface;
24354 use Composer\Package\PackageInterface;
24355 use Composer\Util\Filesystem;
24356 use Composer\Util\Silencer;
24357 use Composer\Util\Platform;
24358
24359
24360
24361
24362
24363
24364
24365 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
24366 {
24367 protected $composer;
24368 protected $vendorDir;
24369 protected $binDir;
24370 protected $downloadManager;
24371 protected $io;
24372 protected $type;
24373 protected $filesystem;
24374 protected $binCompat;
24375 protected $binaryInstaller;
24376
24377
24378
24379
24380
24381
24382
24383
24384
24385
24386 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
24387 {
24388 $this->composer = $composer;
24389 $this->downloadManager = $composer->getDownloadManager();
24390 $this->io = $io;
24391 $this->type = $type;
24392
24393 $this->filesystem = $filesystem ?: new Filesystem();
24394 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
24395 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
24396 }
24397
24398
24399
24400
24401 public function supports($packageType)
24402 {
24403 return $packageType === $this->type || null === $this->type;
24404 }
24405
24406
24407
24408
24409 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24410 {
24411 if (!$repo->hasPackage($package)) {
24412 return false;
24413 }
24414
24415 $installPath = $this->getInstallPath($package);
24416
24417 if (is_readable($installPath)) {
24418 return true;
24419 }
24420
24421 return (Platform::isWindows() && $this->filesystem->isJunction($installPath)) || is_link($installPath);
24422 }
24423
24424
24425
24426
24427 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24428 {
24429 $this->initializeVendorDir();
24430 $downloadPath = $this->getInstallPath($package);
24431
24432
24433  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
24434 $this->binaryInstaller->removeBinaries($package);
24435 }
24436
24437 $this->installCode($package);
24438 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
24439 if (!$repo->hasPackage($package)) {
24440 $repo->addPackage(clone $package);
24441 }
24442 }
24443
24444
24445
24446
24447 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24448 {
24449 if (!$repo->hasPackage($initial)) {
24450 throw new \InvalidArgumentException('Package is not installed: '.$initial);
24451 }
24452
24453 $this->initializeVendorDir();
24454
24455 $this->binaryInstaller->removeBinaries($initial);
24456 $this->updateCode($initial, $target);
24457 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
24458 $repo->removePackage($initial);
24459 if (!$repo->hasPackage($target)) {
24460 $repo->addPackage(clone $target);
24461 }
24462 }
24463
24464
24465
24466
24467 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
24468 {
24469 if (!$repo->hasPackage($package)) {
24470 throw new \InvalidArgumentException('Package is not installed: '.$package);
24471 }
24472
24473 $this->removeCode($package);
24474 $this->binaryInstaller->removeBinaries($package);
24475 $repo->removePackage($package);
24476
24477 $downloadPath = $this->getPackageBasePath($package);
24478 if (strpos($package->getName(), '/')) {
24479 $packageVendorDir = dirname($downloadPath);
24480 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
24481 Silencer::call('rmdir', $packageVendorDir);
24482 }
24483 }
24484 }
24485
24486
24487
24488
24489 public function getInstallPath(PackageInterface $package)
24490 {
24491 $this->initializeVendorDir();
24492
24493 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
24494 $targetDir = $package->getTargetDir();
24495
24496 return $basePath . ($targetDir ? '/'.$targetDir : '');
24497 }
24498
24499
24500
24501
24502
24503
24504 public function ensureBinariesPresence(PackageInterface $package)
24505 {
24506 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
24507 }
24508
24509
24510
24511
24512
24513
24514
24515
24516
24517
24518 protected function getPackageBasePath(PackageInterface $package)
24519 {
24520 $installPath = $this->getInstallPath($package);
24521 $targetDir = $package->getTargetDir();
24522
24523 if ($targetDir) {
24524 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
24525 }
24526
24527 return $installPath;
24528 }
24529
24530 protected function installCode(PackageInterface $package)
24531 {
24532 $downloadPath = $this->getInstallPath($package);
24533 $this->downloadManager->download($package, $downloadPath);
24534 }
24535
24536 protected function updateCode(PackageInterface $initial, PackageInterface $target)
24537 {
24538 $initialDownloadPath = $this->getInstallPath($initial);
24539 $targetDownloadPath = $this->getInstallPath($target);
24540 if ($targetDownloadPath !== $initialDownloadPath) {
24541
24542  
24543  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
24544 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
24545 ) {
24546 $this->removeCode($initial);
24547 $this->installCode($target);
24548
24549 return;
24550 }
24551
24552 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
24553 }
24554 $this->downloadManager->update($initial, $target, $targetDownloadPath);
24555 }
24556
24557 protected function removeCode(PackageInterface $package)
24558 {
24559 $downloadPath = $this->getPackageBasePath($package);
24560 $this->downloadManager->remove($package, $downloadPath);
24561 }
24562
24563 protected function initializeVendorDir()
24564 {
24565 $this->filesystem->ensureDirectoryExists($this->vendorDir);
24566 $this->vendorDir = realpath($this->vendorDir);
24567 }
24568 }
24569 <?php
24570
24571
24572
24573
24574
24575
24576
24577
24578
24579
24580
24581 namespace Composer\Installer;
24582
24583 use Composer\Repository\InstalledRepositoryInterface;
24584 use Composer\Package\PackageInterface;
24585 use Composer\Package\Version\VersionParser;
24586 use Composer\IO\IOInterface;
24587
24588
24589
24590
24591
24592
24593 class MetapackageInstaller implements InstallerInterface
24594 {
24595 private $io;
24596
24597 public function __construct(IOInterface $io)
24598 {
24599 $this->io = $io;
24600 }
24601
24602
24603
24604
24605 public function supports($packageType)
24606 {
24607 return $packageType === 'metapackage';
24608 }
24609
24610
24611
24612
24613 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24614 {
24615 return $repo->hasPackage($package);
24616 }
24617
24618
24619
24620
24621 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24622 {
24623 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
24624
24625 $repo->addPackage(clone $package);
24626 }
24627
24628
24629
24630
24631 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24632 {
24633 if (!$repo->hasPackage($initial)) {
24634 throw new \InvalidArgumentException('Package is not installed: '.$initial);
24635 }
24636
24637 $name = $target->getName();
24638 $from = $initial->getFullPrettyVersion();
24639 $to = $target->getFullPrettyVersion();
24640 $actionName = VersionParser::isUpgrade($initial->getVersion(), $target->getVersion()) ? 'Updating' : 'Downgrading';
24641 $this->io->writeError("  - " . $actionName . " <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>)");
24642
24643 $repo->removePackage($initial);
24644 $repo->addPackage(clone $target);
24645 }
24646
24647
24648
24649
24650 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
24651 {
24652 if (!$repo->hasPackage($package)) {
24653 throw new \InvalidArgumentException('Package is not installed: '.$package);
24654 }
24655
24656 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
24657
24658 $repo->removePackage($package);
24659 }
24660
24661
24662
24663
24664 public function getInstallPath(PackageInterface $package)
24665 {
24666 return '';
24667 }
24668 }
24669 <?php
24670
24671
24672
24673
24674
24675
24676
24677
24678
24679
24680
24681 namespace Composer\Installer;
24682
24683 use Composer\Repository\InstalledRepositoryInterface;
24684 use Composer\Package\PackageInterface;
24685
24686
24687
24688
24689
24690
24691
24692
24693 class NoopInstaller implements InstallerInterface
24694 {
24695
24696
24697
24698 public function supports($packageType)
24699 {
24700 return true;
24701 }
24702
24703
24704
24705
24706 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
24707 {
24708 return $repo->hasPackage($package);
24709 }
24710
24711
24712
24713
24714 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
24715 {
24716 if (!$repo->hasPackage($package)) {
24717 $repo->addPackage(clone $package);
24718 }
24719 }
24720
24721
24722
24723
24724 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
24725 {
24726 if (!$repo->hasPackage($initial)) {
24727 throw new \InvalidArgumentException('Package is not installed: '.$initial);
24728 }
24729
24730 $repo->removePackage($initial);
24731 if (!$repo->hasPackage($target)) {
24732 $repo->addPackage(clone $target);
24733 }
24734 }
24735
24736
24737
24738
24739 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
24740 {
24741 if (!$repo->hasPackage($package)) {
24742 throw new \InvalidArgumentException('Package is not installed: '.$package);
24743 }
24744 $repo->removePackage($package);
24745 }
24746
24747
24748
24749
24750 public function getInstallPath(PackageInterface $package)
24751 {
24752 $targetDir = $package->getTargetDir();
24753
24754 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
24755 }
24756 }
24757 <?php
24758
24759
24760
24761
24762
24763
24764
24765
24766
24767
24768
24769 namespace Composer\Installer;
24770
24771 use Composer\Composer;
24772 use Composer\IO\IOInterface;
24773 use Composer\DependencyResolver\Operation\OperationInterface;
24774 use Composer\DependencyResolver\PolicyInterface;
24775 use Composer\DependencyResolver\Pool;
24776 use Composer\DependencyResolver\Request;
24777 use Composer\Repository\CompositeRepository;
24778
24779
24780
24781
24782
24783
24784 class PackageEvent extends InstallerEvent
24785 {
24786
24787
24788
24789 private $operation;
24790
24791
24792
24793
24794
24795
24796
24797
24798
24799
24800
24801
24802
24803
24804
24805 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
24806 {
24807 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
24808
24809 $this->operation = $operation;
24810 }
24811
24812
24813
24814
24815
24816
24817 public function getOperation()
24818 {
24819 return $this->operation;
24820 }
24821 }
24822 <?php
24823
24824
24825
24826
24827
24828
24829
24830
24831
24832
24833
24834 namespace Composer\Installer;
24835
24836
24837
24838
24839
24840
24841 class PackageEvents
24842 {
24843
24844
24845
24846
24847
24848
24849
24850 const PRE_PACKAGE_INSTALL = 'pre-package-install';
24851
24852
24853
24854
24855
24856
24857
24858
24859 const POST_PACKAGE_INSTALL = 'post-package-install';
24860
24861
24862
24863
24864
24865
24866
24867
24868 const PRE_PACKAGE_UPDATE = 'pre-package-update';
24869
24870
24871
24872
24873
24874
24875
24876
24877 const POST_PACKAGE_UPDATE = 'post-package-update';
24878
24879
24880
24881
24882
24883
24884
24885
24886 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
24887
24888
24889
24890
24891
24892
24893
24894
24895 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
24896 }
24897 <?php
24898
24899
24900
24901
24902
24903
24904
24905
24906
24907
24908
24909 namespace Composer\Installer;
24910
24911 use Composer\IO\IOInterface;
24912 use Composer\Package\PackageInterface;
24913 use Composer\Util\Filesystem;
24914 use Composer\Util\ProcessExecutor;
24915
24916
24917
24918
24919
24920
24921 class PearBinaryInstaller extends BinaryInstaller
24922 {
24923 private $installer;
24924 private $vendorDir;
24925
24926
24927
24928
24929
24930
24931
24932
24933
24934 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
24935 {
24936 parent::__construct($io, $binDir, $binCompat, $filesystem);
24937 $this->installer = $installer;
24938 $this->vendorDir = $vendorDir;
24939 }
24940
24941 protected function getBinaries(PackageInterface $package)
24942 {
24943 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
24944 $binaries = array();
24945 if (file_exists($binariesPath)) {
24946 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
24947 if (!$value->isDir()) {
24948 $binaries[] = 'bin/'.$fileName;
24949 }
24950 }
24951 }
24952
24953 return $binaries;
24954 }
24955
24956 protected function initializeBinDir()
24957 {
24958 parent::initializeBinDir();
24959 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
24960 @chmod($this->binDir.'/composer-php', 0777 & ~umask());
24961 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
24962 @chmod($this->binDir.'/composer-php.bat', 0777 & ~umask());
24963 }
24964
24965 protected function generateWindowsProxyCode($bin, $link)
24966 {
24967 $binPath = $this->filesystem->findShortestPath($link, $bin);
24968 if ('.bat' === substr($bin, -4)) {
24969 $caller = 'call';
24970 } else {
24971 $handle = fopen($bin, 'r');
24972 $line = fgets($handle);
24973 fclose($handle);
24974 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
24975 $caller = trim($match[1]);
24976 } else {
24977 $caller = 'php';
24978 }
24979
24980 if ($caller === 'php') {
24981 return "@echo off\r\n".
24982 "pushd .\r\n".
24983 "cd %~dp0\r\n".
24984 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
24985 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
24986 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
24987 "popd\r\n".
24988 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
24989 }
24990 }
24991
24992 return "@echo off\r\n".
24993 "pushd .\r\n".
24994 "cd %~dp0\r\n".
24995 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
24996 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
24997 "popd\r\n".
24998 $caller." \"%BIN_TARGET%\" %*\r\n";
24999 }
25000
25001 private function generateWindowsPhpProxyCode()
25002 {
25003 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
25004
25005 return
25006 "@echo off\r\n" .
25007 "setlocal enabledelayedexpansion\r\n" .
25008 "set BIN_DIR=%~dp0\r\n" .
25009 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
25010 "set DIRS=.\r\n" .
25011 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
25012 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
25013 "        set DIRS=!DIRS!;%%~fP\r\n" .
25014 "    )\r\n" .
25015 ")\r\n" .
25016 "php.exe -d include_path=!DIRS! %*\r\n";
25017 }
25018
25019 private function generateUnixyPhpProxyCode()
25020 {
25021 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
25022
25023 return
25024 "#!/usr/bin/env sh\n".
25025 "SRC_DIR=`pwd`\n".
25026 "BIN_DIR=`dirname $0`\n".
25027 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
25028 "DIRS=\"\"\n".
25029 "for vendor in \$VENDOR_DIR/*; do\n".
25030 "    if [ -d \"\$vendor\" ]; then\n".
25031 "        for package in \$vendor/*; do\n".
25032 "            if [ -d \"\$package\" ]; then\n".
25033 "                DIRS=\"\${DIRS}:\${package}\"\n".
25034 "            fi\n".
25035 "        done\n".
25036 "    fi\n".
25037 "done\n".
25038 "php -d include_path=\".\$DIRS\" $@\n";
25039 }
25040 }
25041 <?php
25042
25043
25044
25045
25046
25047
25048
25049
25050
25051
25052
25053 namespace Composer\Installer;
25054
25055 use Composer\IO\IOInterface;
25056 use Composer\Composer;
25057 use Composer\Downloader\PearPackageExtractor;
25058 use Composer\Repository\InstalledRepositoryInterface;
25059 use Composer\Package\PackageInterface;
25060 use Composer\Util\Platform;
25061 use Composer\Util\Filesystem;
25062
25063
25064
25065
25066
25067
25068
25069 class PearInstaller extends LibraryInstaller
25070 {
25071
25072
25073
25074
25075
25076
25077
25078 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
25079 {
25080 $filesystem = new Filesystem();
25081 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
25082
25083 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
25084 }
25085
25086
25087
25088
25089 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
25090 {
25091 $this->uninstall($repo, $initial);
25092 $this->install($repo, $target);
25093 }
25094
25095 protected function installCode(PackageInterface $package)
25096 {
25097 parent::installCode($package);
25098
25099 $isWindows = Platform::isWindows();
25100 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
25101
25102 if (!$isWindows) {
25103 $php_bin = '/usr/bin/env ' . $php_bin;
25104 }
25105
25106 $installPath = $this->getInstallPath($package);
25107 $vars = array(
25108 'os' => $isWindows ? 'windows' : 'linux',
25109 'php_bin' => $php_bin,
25110 'pear_php' => $installPath,
25111 'php_dir' => $installPath,
25112 'bin_dir' => $installPath . '/bin',
25113 'data_dir' => $installPath . '/data',
25114 'version' => $package->getPrettyVersion(),
25115 );
25116
25117 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
25118 $pearExtractor = new PearPackageExtractor($packageArchive);
25119 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
25120
25121 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
25122 $this->filesystem->unlink($packageArchive);
25123 }
25124 }
25125 <?php
25126
25127
25128
25129
25130
25131
25132
25133
25134
25135
25136
25137 namespace Composer\Installer;
25138
25139 use Composer\Composer;
25140 use Composer\IO\IOInterface;
25141 use Composer\Repository\InstalledRepositoryInterface;
25142 use Composer\Package\PackageInterface;
25143
25144
25145
25146
25147
25148
25149
25150 class PluginInstaller extends LibraryInstaller
25151 {
25152 private $installationManager;
25153
25154
25155
25156
25157
25158
25159
25160 public function __construct(IOInterface $io, Composer $composer)
25161 {
25162 parent::__construct($io, $composer, 'composer-plugin');
25163 $this->installationManager = $composer->getInstallationManager();
25164 }
25165
25166
25167
25168
25169 public function supports($packageType)
25170 {
25171 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
25172 }
25173
25174
25175
25176
25177 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
25178 {
25179 $extra = $package->getExtra();
25180 if (empty($extra['class'])) {
25181 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
25182 }
25183
25184 parent::install($repo, $package);
25185 try {
25186 $this->composer->getPluginManager()->registerPackage($package, true);
25187 } catch (\Exception $e) {
25188
25189  $this->io->writeError('Plugin installation failed ('.$e->getMessage().'), rolling back');
25190 parent::uninstall($repo, $package);
25191 throw $e;
25192 }
25193 }
25194
25195
25196
25197
25198 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
25199 {
25200 $extra = $target->getExtra();
25201 if (empty($extra['class'])) {
25202 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
25203 }
25204
25205 parent::update($repo, $initial, $target);
25206 $this->composer->getPluginManager()->registerPackage($target, true);
25207 }
25208 }
25209 <?php
25210
25211
25212
25213
25214
25215
25216
25217
25218
25219
25220
25221 namespace Composer\Installer;
25222
25223 use Composer\Package\PackageInterface;
25224 use Composer\Downloader\DownloadManager;
25225 use Composer\Repository\InstalledRepositoryInterface;
25226 use Composer\Util\Filesystem;
25227
25228
25229
25230
25231
25232
25233
25234 class ProjectInstaller implements InstallerInterface
25235 {
25236 private $installPath;
25237 private $downloadManager;
25238 private $filesystem;
25239
25240 public function __construct($installPath, DownloadManager $dm)
25241 {
25242 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
25243 $this->downloadManager = $dm;
25244 $this->filesystem = new Filesystem;
25245 }
25246
25247
25248
25249
25250
25251
25252
25253 public function supports($packageType)
25254 {
25255 return true;
25256 }
25257
25258
25259
25260
25261 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
25262 {
25263 return false;
25264 }
25265
25266
25267
25268
25269 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
25270 {
25271 $installPath = $this->installPath;
25272 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
25273 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
25274 }
25275 if (!is_dir($installPath)) {
25276 mkdir($installPath, 0777, true);
25277 }
25278 $this->downloadManager->download($package, $installPath);
25279 }
25280
25281
25282
25283
25284 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
25285 {
25286 throw new \InvalidArgumentException("not supported");
25287 }
25288
25289
25290
25291
25292 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
25293 {
25294 throw new \InvalidArgumentException("not supported");
25295 }
25296
25297
25298
25299
25300
25301
25302
25303 public function getInstallPath(PackageInterface $package)
25304 {
25305 return $this->installPath;
25306 }
25307 }
25308 <?php
25309
25310
25311
25312
25313
25314
25315
25316
25317
25318
25319
25320 namespace Composer\Installer;
25321
25322 use Composer\IO\IOInterface;
25323 use Composer\Package\PackageInterface;
25324 use Composer\Repository\RepositoryInterface;
25325 use Symfony\Component\Console\Formatter\OutputFormatter;
25326
25327
25328
25329
25330
25331
25332 class SuggestedPackagesReporter
25333 {
25334
25335
25336
25337 protected $suggestedPackages = array();
25338
25339
25340
25341
25342 private $io;
25343
25344 public function __construct(IOInterface $io)
25345 {
25346 $this->io = $io;
25347 }
25348
25349
25350
25351
25352 public function getPackages()
25353 {
25354 return $this->suggestedPackages;
25355 }
25356
25357
25358
25359
25360
25361
25362
25363
25364
25365
25366
25367
25368 public function addPackage($source, $target, $reason)
25369 {
25370 $this->suggestedPackages[] = array(
25371 'source' => $source,
25372 'target' => $target,
25373 'reason' => $reason,
25374 );
25375
25376 return $this;
25377 }
25378
25379
25380
25381
25382
25383
25384
25385 public function addSuggestionsFromPackage(PackageInterface $package)
25386 {
25387 $source = $package->getPrettyName();
25388 foreach ($package->getSuggests() as $target => $reason) {
25389 $this->addPackage(
25390 $source,
25391 $target,
25392 $reason
25393 );
25394 }
25395
25396 return $this;
25397 }
25398
25399
25400
25401
25402
25403
25404
25405
25406 public function output(RepositoryInterface $installedRepo = null)
25407 {
25408 $suggestedPackages = $this->getPackages();
25409 $installedPackages = array();
25410 if (null !== $installedRepo && ! empty($suggestedPackages)) {
25411 foreach ($installedRepo->getPackages() as $package) {
25412 $installedPackages = array_merge(
25413 $installedPackages,
25414 $package->getNames()
25415 );
25416 }
25417 }
25418
25419 foreach ($suggestedPackages as $suggestion) {
25420 if (in_array($suggestion['target'], $installedPackages)) {
25421 continue;
25422 }
25423
25424 $this->io->writeError(sprintf(
25425 '%s suggests installing %s%s',
25426 $suggestion['source'],
25427 $this->escapeOutput($suggestion['target']),
25428 $this->escapeOutput('' !== $suggestion['reason'] ? ' ('.$suggestion['reason'].')' : '')
25429 ));
25430 }
25431
25432 return $this;
25433 }
25434
25435
25436
25437
25438
25439 private function escapeOutput($string)
25440 {
25441 return OutputFormatter::escape(
25442 $this->removeControlCharacters($string)
25443 );
25444 }
25445
25446
25447
25448
25449
25450 private function removeControlCharacters($string)
25451 {
25452 return preg_replace(
25453 '/[[:cntrl:]]/',
25454 '',
25455 str_replace("\n", ' ', $string)
25456 );
25457 }
25458 }
25459 <?php
25460
25461
25462
25463
25464
25465
25466
25467
25468
25469
25470
25471 namespace Composer\Json;
25472
25473 use JsonSchema\Validator;
25474 use Seld\JsonLint\JsonParser;
25475 use Seld\JsonLint\ParsingException;
25476 use Composer\Util\RemoteFilesystem;
25477 use Composer\IO\IOInterface;
25478 use Composer\Downloader\TransportException;
25479
25480
25481
25482
25483
25484
25485
25486 class JsonFile
25487 {
25488 const LAX_SCHEMA = 1;
25489 const STRICT_SCHEMA = 2;
25490
25491 const JSON_UNESCAPED_SLASHES = 64;
25492 const JSON_PRETTY_PRINT = 128;
25493 const JSON_UNESCAPED_UNICODE = 256;
25494
25495 const COMPOSER_SCHEMA_PATH = '/../../../res/composer-schema.json';
25496
25497 private $path;
25498 private $rfs;
25499 private $io;
25500
25501
25502
25503
25504
25505
25506
25507
25508
25509 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
25510 {
25511 $this->path = $path;
25512
25513 if (null === $rfs && preg_match('{^https?://}i', $path)) {
25514 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
25515 }
25516 $this->rfs = $rfs;
25517 $this->io = $io;
25518 }
25519
25520
25521
25522
25523 public function getPath()
25524 {
25525 return $this->path;
25526 }
25527
25528
25529
25530
25531
25532
25533 public function exists()
25534 {
25535 return is_file($this->path);
25536 }
25537
25538
25539
25540
25541
25542
25543
25544 public function read()
25545 {
25546 try {
25547 if ($this->rfs) {
25548 $json = $this->rfs->getContents($this->path, $this->path, false);
25549 } else {
25550 if ($this->io && $this->io->isDebug()) {
25551 $this->io->writeError('Reading ' . $this->path);
25552 }
25553 $json = file_get_contents($this->path);
25554 }
25555 } catch (TransportException $e) {
25556 throw new \RuntimeException($e->getMessage(), 0, $e);
25557 } catch (\Exception $e) {
25558 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
25559 }
25560
25561 return static::parseJson($json, $this->path);
25562 }
25563
25564
25565
25566
25567
25568
25569
25570
25571 public function write(array $hash, $options = 448)
25572 {
25573 $dir = dirname($this->path);
25574 if (!is_dir($dir)) {
25575 if (file_exists($dir)) {
25576 throw new \UnexpectedValueException(
25577 $dir.' exists and is not a directory.'
25578 );
25579 }
25580 if (!@mkdir($dir, 0777, true)) {
25581 throw new \UnexpectedValueException(
25582 $dir.' does not exist and could not be created.'
25583 );
25584 }
25585 }
25586
25587 $retries = 3;
25588 while ($retries--) {
25589 try {
25590 $this->filePutContentsIfModified($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
25591 break;
25592 } catch (\Exception $e) {
25593 if ($retries) {
25594 usleep(500000);
25595 continue;
25596 }
25597
25598 throw $e;
25599 }
25600 }
25601 }
25602
25603
25604
25605
25606 private function filePutContentsIfModified($path, $content)
25607 {
25608 $currentContent = @file_get_contents($path);
25609 if (!$currentContent || ($currentContent != $content)) {
25610 return file_put_contents($path, $content);
25611 }
25612
25613 return 0;
25614 }
25615
25616
25617
25618
25619
25620
25621
25622
25623
25624 public function validateSchema($schema = self::STRICT_SCHEMA, $schemaFile = null)
25625 {
25626 $content = file_get_contents($this->path);
25627 $data = json_decode($content);
25628
25629 if (null === $data && 'null' !== $content) {
25630 self::validateSyntax($content, $this->path);
25631 }
25632
25633 if (null === $schemaFile) {
25634 $schemaFile = __DIR__ . self::COMPOSER_SCHEMA_PATH;
25635 }
25636
25637
25638  if (false === strpos($schemaFile, '://')) {
25639 $schemaFile = 'file://' . $schemaFile;
25640 }
25641
25642 $schemaData = (object) array('$ref' => $schemaFile);
25643
25644 if ($schema === self::LAX_SCHEMA) {
25645 $schemaData->additionalProperties = true;
25646 $schemaData->required = array();
25647 }
25648
25649 $validator = new Validator();
25650 $validator->check($data, $schemaData);
25651
25652
25653
25654 if (!$validator->isValid()) {
25655 $errors = array();
25656 foreach ((array) $validator->getErrors() as $error) {
25657 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
25658 }
25659 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
25660 }
25661
25662 return true;
25663 }
25664
25665
25666
25667
25668
25669
25670
25671
25672 public static function encode($data, $options = 448)
25673 {
25674 if (PHP_VERSION_ID >= 50400) {
25675 $json = json_encode($data, $options);
25676 if (false === $json) {
25677 self::throwEncodeError(json_last_error());
25678 }
25679
25680
25681  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
25682 $json = preg_replace('/\[\s+\]/', '[]', $json);
25683 $json = preg_replace('/\{\s+\}/', '{}', $json);
25684 }
25685
25686 return $json;
25687 }
25688
25689 $json = json_encode($data);
25690 if (false === $json) {
25691 self::throwEncodeError(json_last_error());
25692 }
25693
25694 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
25695 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
25696 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
25697
25698 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
25699 return $json;
25700 }
25701
25702 return JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
25703 }
25704
25705
25706
25707
25708
25709
25710
25711 private static function throwEncodeError($code)
25712 {
25713 switch ($code) {
25714 case JSON_ERROR_DEPTH:
25715 $msg = 'Maximum stack depth exceeded';
25716 break;
25717 case JSON_ERROR_STATE_MISMATCH:
25718 $msg = 'Underflow or the modes mismatch';
25719 break;
25720 case JSON_ERROR_CTRL_CHAR:
25721 $msg = 'Unexpected control character found';
25722 break;
25723 case JSON_ERROR_UTF8:
25724 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
25725 break;
25726 default:
25727 $msg = 'Unknown error';
25728 }
25729
25730 throw new \RuntimeException('JSON encoding failed: '.$msg);
25731 }
25732
25733
25734
25735
25736
25737
25738
25739
25740
25741 public static function parseJson($json, $file = null)
25742 {
25743 if (null === $json) {
25744 return;
25745 }
25746 $data = json_decode($json, true);
25747 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
25748 self::validateSyntax($json, $file);
25749 }
25750
25751 return $data;
25752 }
25753
25754
25755
25756
25757
25758
25759
25760
25761
25762
25763 protected static function validateSyntax($json, $file = null)
25764 {
25765 $parser = new JsonParser();
25766 $result = $parser->lint($json);
25767 if (null === $result) {
25768 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
25769 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
25770 }
25771
25772 return true;
25773 }
25774
25775 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
25776 }
25777 }
25778 <?php
25779
25780
25781
25782
25783
25784
25785
25786
25787
25788
25789
25790 namespace Composer\Json;
25791
25792
25793
25794
25795
25796
25797
25798
25799
25800 class JsonFormatter
25801 {
25802
25803
25804
25805
25806
25807
25808
25809
25810
25811
25812
25813
25814 public static function format($json, $unescapeUnicode, $unescapeSlashes)
25815 {
25816 $result = '';
25817 $pos = 0;
25818 $strLen = strlen($json);
25819 $indentStr = '    ';
25820 $newLine = "\n";
25821 $outOfQuotes = true;
25822 $buffer = '';
25823 $noescape = true;
25824
25825 for ($i = 0; $i < $strLen; $i++) {
25826
25827  $char = substr($json, $i, 1);
25828
25829
25830  if ('"' === $char && $noescape) {
25831 $outOfQuotes = !$outOfQuotes;
25832 }
25833
25834 if (!$outOfQuotes) {
25835 $buffer .= $char;
25836 $noescape = '\\' === $char ? !$noescape : true;
25837 continue;
25838 } elseif ('' !== $buffer) {
25839 if ($unescapeSlashes) {
25840 $buffer = str_replace('\\/', '/', $buffer);
25841 }
25842
25843 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
25844
25845  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
25846 $l = strlen($match[1]);
25847
25848 if ($l % 2) {
25849 $code = hexdec($match[2]);
25850
25851  
25852  if (0xD800 <= $code && 0xDFFF >= $code) {
25853 return $match[0];
25854 }
25855
25856 return str_repeat('\\', $l - 1) . mb_convert_encoding(
25857 pack('H*', $match[2]),
25858 'UTF-8',
25859 'UCS-2BE'
25860 );
25861 }
25862
25863 return $match[0];
25864 }, $buffer);
25865 }
25866
25867 $result .= $buffer.$char;
25868 $buffer = '';
25869 continue;
25870 }
25871
25872 if (':' === $char) {
25873
25874  $char .= ' ';
25875 } elseif ('}' === $char || ']' === $char) {
25876 $pos--;
25877 $prevChar = substr($json, $i - 1, 1);
25878
25879 if ('{' !== $prevChar && '[' !== $prevChar) {
25880
25881  
25882  $result .= $newLine;
25883 for ($j = 0; $j < $pos; $j++) {
25884 $result .= $indentStr;
25885 }
25886 } else {
25887
25888  $result = rtrim($result);
25889 }
25890 }
25891
25892 $result .= $char;
25893
25894
25895  
25896  if (',' === $char || '{' === $char || '[' === $char) {
25897 $result .= $newLine;
25898
25899 if ('{' === $char || '[' === $char) {
25900 $pos++;
25901 }
25902
25903 for ($j = 0; $j < $pos; $j++) {
25904 $result .= $indentStr;
25905 }
25906 }
25907 }
25908
25909 return $result;
25910 }
25911 }
25912 <?php
25913
25914
25915
25916
25917
25918
25919
25920
25921
25922
25923
25924 namespace Composer\Json;
25925
25926 use Composer\Repository\PlatformRepository;
25927
25928
25929
25930
25931 class JsonManipulator
25932 {
25933 private static $DEFINES = '(?(DEFINE)
25934        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
25935        (?<boolean>   true | false | null )
25936        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
25937        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
25938        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
25939        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
25940        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
25941     )';
25942
25943 private $contents;
25944 private $newline;
25945 private $indent;
25946
25947 public function __construct($contents)
25948 {
25949 $contents = trim($contents);
25950 if ($contents === '') {
25951 $contents = '{}';
25952 }
25953 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
25954 throw new \InvalidArgumentException('The json file must be an object ({})');
25955 }
25956 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
25957 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
25958 $this->detectIndenting();
25959 }
25960
25961 public function getContents()
25962 {
25963 return $this->contents . $this->newline;
25964 }
25965
25966 public function addLink($type, $package, $constraint, $sortPackages = false)
25967 {
25968 $decoded = JsonFile::parseJson($this->contents);
25969
25970
25971  if (!isset($decoded[$type])) {
25972 return $this->addMainKey($type, array($package => $constraint));
25973 }
25974
25975 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
25976 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
25977 if (!$this->pregMatch($regex, $this->contents, $matches)) {
25978 return false;
25979 }
25980
25981 $links = $matches['value'];
25982
25983
25984  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
25985 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
25986 if ($this->pregMatch($regex, $links, $packageMatches)) {
25987
25988  $existingPackage = $packageMatches['package'];
25989 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
25990 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
25991 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
25992 }, $links);
25993 } else {
25994 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
25995
25996  $links = preg_replace(
25997 '{'.preg_quote($match[1]).'$}',
25998
25999  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
26000 $links
26001 );
26002 } else {
26003
26004  $links = '{' . $this->newline .
26005 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
26006 $this->indent . '}';
26007 }
26008 }
26009
26010 if (true === $sortPackages) {
26011 $requirements = json_decode($links, true);
26012 $this->sortPackages($requirements);
26013 $links = $this->format($requirements);
26014 }
26015
26016 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
26017
26018 return true;
26019 }
26020
26021
26022
26023
26024
26025
26026
26027
26028 private function sortPackages(array &$packages = array())
26029 {
26030 $prefix = function ($requirement) {
26031 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
26032 return preg_replace(
26033 array(
26034 '/^php/',
26035 '/^hhvm/',
26036 '/^ext/',
26037 '/^lib/',
26038 '/^\D/',
26039 ),
26040 array(
26041 '0-$0',
26042 '1-$0',
26043 '2-$0',
26044 '3-$0',
26045 '4-$0',
26046 ),
26047 $requirement
26048 );
26049 }
26050
26051 return '5-'.$requirement;
26052 };
26053
26054 uksort($packages, function ($a, $b) use ($prefix) {
26055 return strnatcmp($prefix($a), $prefix($b));
26056 });
26057 }
26058
26059 public function addRepository($name, $config)
26060 {
26061 return $this->addSubNode('repositories', $name, $config);
26062 }
26063
26064 public function removeRepository($name)
26065 {
26066 return $this->removeSubNode('repositories', $name);
26067 }
26068
26069 public function addConfigSetting($name, $value)
26070 {
26071 return $this->addSubNode('config', $name, $value);
26072 }
26073
26074 public function removeConfigSetting($name)
26075 {
26076 return $this->removeSubNode('config', $name);
26077 }
26078
26079 public function addProperty($name, $value)
26080 {
26081 if (substr($name, 0, 8) === 'suggest.') {
26082 return $this->addSubNode('suggest', substr($name, 8), $value);
26083 }
26084
26085 if (substr($name, 0, 6) === 'extra.') {
26086 return $this->addSubNode('extra', substr($name, 6), $value);
26087 }
26088
26089 if (substr($name, 0, 8) === 'scripts.') {
26090 return $this->addSubNode('scripts', substr($name, 8), $value);
26091 }
26092
26093 return $this->addMainKey($name, $value);
26094 }
26095
26096 public function removeProperty($name)
26097 {
26098 if (substr($name, 0, 8) === 'suggest.') {
26099 return $this->removeSubNode('suggest', substr($name, 8));
26100 }
26101
26102 if (substr($name, 0, 6) === 'extra.') {
26103 return $this->removeSubNode('extra', substr($name, 6));
26104 }
26105
26106 if (substr($name, 0, 8) === 'scripts.') {
26107 return $this->removeSubNode('scripts', substr($name, 8));
26108 }
26109
26110 return $this->removeMainKey($name);
26111 }
26112
26113 public function addSubNode($mainNode, $name, $value)
26114 {
26115 $decoded = JsonFile::parseJson($this->contents);
26116
26117 $subName = null;
26118 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
26119 list($name, $subName) = explode('.', $name, 2);
26120 }
26121
26122
26123  if (!isset($decoded[$mainNode])) {
26124 if ($subName !== null) {
26125 $this->addMainKey($mainNode, array($name => array($subName => $value)));
26126 } else {
26127 $this->addMainKey($mainNode, array($name => $value));
26128 }
26129
26130 return true;
26131 }
26132
26133
26134  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
26135 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
26136
26137 try {
26138 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
26139 return false;
26140 }
26141 } catch (\RuntimeException $e) {
26142 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
26143 return false;
26144 }
26145 throw $e;
26146 }
26147
26148 $children = $match['content'];
26149
26150  if (!@json_decode($children)) {
26151 return false;
26152 }
26153
26154 $that = $this;
26155
26156
26157  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
26158 if ($this->pregMatch($childRegex, $children, $matches)) {
26159 $children = preg_replace_callback($childRegex, function ($matches) use ($subName, $value, $that) {
26160 if ($subName !== null) {
26161 $curVal = json_decode($matches['content'], true);
26162 if (!is_array($curVal)) {
26163 $curVal = array();
26164 }
26165 $curVal[$subName] = $value;
26166 $value = $curVal;
26167 }
26168
26169 return $matches['start'] . $that->format($value, 1) . $matches['end'];
26170 }, $children);
26171 } else {
26172 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
26173
26174 $whitespace = '';
26175 if (!empty($match['trailingspace'])) {
26176 $whitespace = $match['trailingspace'];
26177 }
26178
26179 if (!empty($match['content'])) {
26180 if ($subName !== null) {
26181 $value = array($subName => $value);
26182 }
26183
26184
26185  $children = preg_replace(
26186 '#'.$whitespace.'}$#',
26187 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
26188 $children
26189 );
26190 } else {
26191 if ($subName !== null) {
26192 $value = array($subName => $value);
26193 }
26194
26195
26196  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
26197 }
26198 }
26199
26200 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
26201 return $m['start'] . $children . $m['end'];
26202 }, $this->contents);
26203
26204 return true;
26205 }
26206
26207 public function removeSubNode($mainNode, $name)
26208 {
26209 $decoded = JsonFile::parseJson($this->contents);
26210
26211
26212  if (empty($decoded[$mainNode])) {
26213 return true;
26214 }
26215
26216
26217  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
26218 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
26219 try {
26220 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
26221 return false;
26222 }
26223 } catch (\RuntimeException $e) {
26224 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
26225 return false;
26226 }
26227 throw $e;
26228 }
26229
26230 $children = $match['content'];
26231
26232
26233  if (!@json_decode($children, true)) {
26234 return false;
26235 }
26236
26237 $subName = null;
26238 if (in_array($mainNode, array('config', 'extra', 'scripts')) && false !== strpos($name, '.')) {
26239 list($name, $subName) = explode('.', $name, 2);
26240 }
26241
26242
26243  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
26244 return true;
26245 }
26246
26247
26248  $keyRegex = str_replace('/', '\\\\?/', preg_quote($name));
26249 if ($this->pregMatch('{"'.$keyRegex.'"\s*:}i', $children)) {
26250
26251  if (preg_match_all('{'.self::$DEFINES.'"'.$keyRegex.'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
26252 $bestMatch = '';
26253 foreach ($matches[0] as $match) {
26254 if (strlen($bestMatch) < strlen($match)) {
26255 $bestMatch = $match;
26256 }
26257 }
26258 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
26259 if (1 !== $count) {
26260 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
26261 if (1 !== $count) {
26262 return false;
26263 }
26264 }
26265 }
26266 } else {
26267 $childrenClean = $children;
26268 }
26269
26270
26271  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
26272 if (empty($match['content'])) {
26273 $newline = $this->newline;
26274 $indent = $this->indent;
26275
26276 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
26277 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
26278 }, $this->contents);
26279
26280
26281  if ($subName !== null) {
26282 $curVal = json_decode($children, true);
26283 unset($curVal[$name][$subName]);
26284 $this->addSubNode($mainNode, $name, $curVal[$name]);
26285 }
26286
26287 return true;
26288 }
26289
26290 $that = $this;
26291 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
26292 if ($subName !== null) {
26293 $curVal = json_decode($matches['content'], true);
26294 unset($curVal[$name][$subName]);
26295 $childrenClean = $that->format($curVal, 0);
26296 }
26297
26298 return $matches['start'] . $childrenClean . $matches['end'];
26299 }, $this->contents);
26300
26301 return true;
26302 }
26303
26304 public function addMainKey($key, $content)
26305 {
26306 $decoded = JsonFile::parseJson($this->contents);
26307 $content = $this->format($content);
26308
26309
26310  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
26311 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
26312 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
26313
26314  if (!@json_decode('{'.$matches['key'].'}')) {
26315 return false;
26316 }
26317
26318 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
26319
26320 return true;
26321 }
26322
26323
26324  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
26325 $this->contents = preg_replace(
26326 '#'.$match[1].'\}$#',
26327 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
26328 $this->contents
26329 );
26330
26331 return true;
26332 }
26333
26334
26335  $this->contents = preg_replace(
26336 '#\}$#',
26337 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
26338 $this->contents
26339 );
26340
26341 return true;
26342 }
26343
26344 public function removeMainKey($key)
26345 {
26346 $decoded = JsonFile::parseJson($this->contents);
26347
26348 if (!array_key_exists($key, $decoded)) {
26349 return true;
26350 }
26351
26352
26353  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
26354 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
26355 if ($this->pregMatch($regex, $this->contents, $matches)) {
26356
26357  if (!@json_decode('{'.$matches['removal'].'}')) {
26358 return false;
26359 }
26360
26361
26362  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
26363 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
26364 }
26365
26366 $this->contents = $matches['start'] . $matches['end'];
26367 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
26368 $this->contents = "{\n}";
26369 }
26370
26371 return true;
26372 }
26373
26374 return false;
26375 }
26376
26377 public function format($data, $depth = 0)
26378 {
26379 if (is_array($data)) {
26380 reset($data);
26381
26382 if (is_numeric(key($data))) {
26383 foreach ($data as $key => $val) {
26384 $data[$key] = $this->format($val, $depth + 1);
26385 }
26386
26387 return '['.implode(', ', $data).']';
26388 }
26389
26390 $out = '{' . $this->newline;
26391 $elems = array();
26392 foreach ($data as $key => $val) {
26393 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
26394 }
26395
26396 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
26397 }
26398
26399 return JsonFile::encode($data);
26400 }
26401
26402 protected function detectIndenting()
26403 {
26404 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
26405 $this->indent = $match[1];
26406 } else {
26407 $this->indent = '    ';
26408 }
26409 }
26410
26411 protected function pregMatch($re, $str, &$matches = array())
26412 {
26413 $count = preg_match($re, $str, $matches);
26414
26415 if ($count === false) {
26416 switch (preg_last_error()) {
26417 case PREG_NO_ERROR:
26418 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
26419 case PREG_INTERNAL_ERROR:
26420 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
26421 case PREG_BACKTRACK_LIMIT_ERROR:
26422 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
26423 case PREG_RECURSION_LIMIT_ERROR:
26424 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
26425 case PREG_BAD_UTF8_ERROR:
26426 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
26427 case PREG_BAD_UTF8_OFFSET_ERROR:
26428 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
26429 case 6: 
26430  if (PHP_VERSION_ID > 70000) {
26431 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
26432 }
26433
26434  default:
26435 throw new \RuntimeException('Failed to execute regex: Unknown error');
26436 }
26437 }
26438
26439 return $count;
26440 }
26441 }
26442 <?php
26443
26444
26445
26446
26447
26448
26449
26450
26451
26452
26453
26454 namespace Composer\Json;
26455
26456 use Exception;
26457
26458
26459
26460
26461 class JsonValidationException extends Exception
26462 {
26463 protected $errors;
26464
26465 public function __construct($message, $errors = array(), Exception $previous = null)
26466 {
26467 $this->errors = $errors;
26468 parent::__construct($message, 0, $previous);
26469 }
26470
26471 public function getErrors()
26472 {
26473 return $this->errors;
26474 }
26475 }
26476 <?php
26477
26478
26479
26480
26481
26482
26483
26484
26485
26486
26487
26488 namespace Composer\Package;
26489
26490 use Composer\Semver\Constraint\Constraint;
26491 use Composer\Package\Version\VersionParser;
26492
26493
26494
26495
26496 class AliasPackage extends BasePackage implements CompletePackageInterface
26497 {
26498 protected $version;
26499 protected $prettyVersion;
26500 protected $dev;
26501 protected $rootPackageAlias = false;
26502 protected $stability;
26503
26504
26505 protected $aliasOf;
26506
26507 protected $requires;
26508
26509 protected $devRequires;
26510
26511 protected $conflicts;
26512
26513 protected $provides;
26514
26515 protected $replaces;
26516
26517
26518
26519
26520
26521
26522
26523
26524 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
26525 {
26526 parent::__construct($aliasOf->getName());
26527
26528 $this->version = $version;
26529 $this->prettyVersion = $prettyVersion;
26530 $this->aliasOf = $aliasOf;
26531 $this->stability = VersionParser::parseStability($version);
26532 $this->dev = $this->stability === 'dev';
26533
26534 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
26535 $links = $aliasOf->{'get' . ucfirst($type)}();
26536 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
26537 }
26538 }
26539
26540
26541
26542
26543 public function getAliasOf()
26544 {
26545 return $this->aliasOf;
26546 }
26547
26548
26549
26550
26551 public function getVersion()
26552 {
26553 return $this->version;
26554 }
26555
26556
26557
26558
26559 public function getStability()
26560 {
26561 return $this->stability;
26562 }
26563
26564
26565
26566
26567 public function getPrettyVersion()
26568 {
26569 return $this->prettyVersion;
26570 }
26571
26572
26573
26574
26575 public function isDev()
26576 {
26577 return $this->dev;
26578 }
26579
26580
26581
26582
26583 public function getRequires()
26584 {
26585 return $this->requires;
26586 }
26587
26588
26589
26590
26591 public function getConflicts()
26592 {
26593 return $this->conflicts;
26594 }
26595
26596
26597
26598
26599 public function getProvides()
26600 {
26601 return $this->provides;
26602 }
26603
26604
26605
26606
26607 public function getReplaces()
26608 {
26609 return $this->replaces;
26610 }
26611
26612
26613
26614
26615 public function getDevRequires()
26616 {
26617 return $this->devRequires;
26618 }
26619
26620
26621
26622
26623
26624
26625
26626
26627
26628
26629 public function setRootPackageAlias($value)
26630 {
26631 return $this->rootPackageAlias = $value;
26632 }
26633
26634
26635
26636
26637
26638 public function isRootPackageAlias()
26639 {
26640 return $this->rootPackageAlias;
26641 }
26642
26643
26644
26645
26646
26647
26648
26649 protected function replaceSelfVersionDependencies(array $links, $linkType)
26650 {
26651 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
26652 $newLinks = array();
26653 foreach ($links as $link) {
26654
26655  if ('self.version' === $link->getPrettyConstraint()) {
26656 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
26657 }
26658 }
26659 $links = array_merge($links, $newLinks);
26660 } else {
26661 foreach ($links as $index => $link) {
26662 if ('self.version' === $link->getPrettyConstraint()) {
26663 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
26664 }
26665 }
26666 }
26667
26668 return $links;
26669 }
26670
26671
26672
26673
26674
26675 public function getType()
26676 {
26677 return $this->aliasOf->getType();
26678 }
26679
26680 public function getTargetDir()
26681 {
26682 return $this->aliasOf->getTargetDir();
26683 }
26684
26685 public function getExtra()
26686 {
26687 return $this->aliasOf->getExtra();
26688 }
26689
26690 public function setInstallationSource($type)
26691 {
26692 $this->aliasOf->setInstallationSource($type);
26693 }
26694
26695 public function getInstallationSource()
26696 {
26697 return $this->aliasOf->getInstallationSource();
26698 }
26699
26700 public function getSourceType()
26701 {
26702 return $this->aliasOf->getSourceType();
26703 }
26704
26705 public function getSourceUrl()
26706 {
26707 return $this->aliasOf->getSourceUrl();
26708 }
26709
26710 public function getSourceUrls()
26711 {
26712 return $this->aliasOf->getSourceUrls();
26713 }
26714
26715 public function getSourceReference()
26716 {
26717 return $this->aliasOf->getSourceReference();
26718 }
26719
26720 public function setSourceReference($reference)
26721 {
26722 return $this->aliasOf->setSourceReference($reference);
26723 }
26724
26725 public function setSourceMirrors($mirrors)
26726 {
26727 return $this->aliasOf->setSourceMirrors($mirrors);
26728 }
26729
26730 public function getSourceMirrors()
26731 {
26732 return $this->aliasOf->getSourceMirrors();
26733 }
26734
26735 public function getDistType()
26736 {
26737 return $this->aliasOf->getDistType();
26738 }
26739
26740 public function getDistUrl()
26741 {
26742 return $this->aliasOf->getDistUrl();
26743 }
26744
26745 public function getDistUrls()
26746 {
26747 return $this->aliasOf->getDistUrls();
26748 }
26749
26750 public function getDistReference()
26751 {
26752 return $this->aliasOf->getDistReference();
26753 }
26754
26755 public function setDistReference($reference)
26756 {
26757 return $this->aliasOf->setDistReference($reference);
26758 }
26759
26760 public function getDistSha1Checksum()
26761 {
26762 return $this->aliasOf->getDistSha1Checksum();
26763 }
26764
26765 public function setTransportOptions(array $options)
26766 {
26767 return $this->aliasOf->setTransportOptions($options);
26768 }
26769
26770 public function getTransportOptions()
26771 {
26772 return $this->aliasOf->getTransportOptions();
26773 }
26774
26775 public function setDistMirrors($mirrors)
26776 {
26777 return $this->aliasOf->setDistMirrors($mirrors);
26778 }
26779
26780 public function getDistMirrors()
26781 {
26782 return $this->aliasOf->getDistMirrors();
26783 }
26784
26785 public function getScripts()
26786 {
26787 return $this->aliasOf->getScripts();
26788 }
26789
26790 public function getLicense()
26791 {
26792 return $this->aliasOf->getLicense();
26793 }
26794
26795 public function getAutoload()
26796 {
26797 return $this->aliasOf->getAutoload();
26798 }
26799
26800 public function getDevAutoload()
26801 {
26802 return $this->aliasOf->getDevAutoload();
26803 }
26804
26805 public function getIncludePaths()
26806 {
26807 return $this->aliasOf->getIncludePaths();
26808 }
26809
26810 public function getRepositories()
26811 {
26812 return $this->aliasOf->getRepositories();
26813 }
26814
26815 public function getReleaseDate()
26816 {
26817 return $this->aliasOf->getReleaseDate();
26818 }
26819
26820 public function getBinaries()
26821 {
26822 return $this->aliasOf->getBinaries();
26823 }
26824
26825 public function getKeywords()
26826 {
26827 return $this->aliasOf->getKeywords();
26828 }
26829
26830 public function getDescription()
26831 {
26832 return $this->aliasOf->getDescription();
26833 }
26834
26835 public function getHomepage()
26836 {
26837 return $this->aliasOf->getHomepage();
26838 }
26839
26840 public function getSuggests()
26841 {
26842 return $this->aliasOf->getSuggests();
26843 }
26844
26845 public function getAuthors()
26846 {
26847 return $this->aliasOf->getAuthors();
26848 }
26849
26850 public function getSupport()
26851 {
26852 return $this->aliasOf->getSupport();
26853 }
26854
26855 public function getFunding()
26856 {
26857 return $this->aliasOf->getFunding();
26858 }
26859
26860 public function getNotificationUrl()
26861 {
26862 return $this->aliasOf->getNotificationUrl();
26863 }
26864
26865 public function getArchiveExcludes()
26866 {
26867 return $this->aliasOf->getArchiveExcludes();
26868 }
26869
26870 public function isAbandoned()
26871 {
26872 return $this->aliasOf->isAbandoned();
26873 }
26874
26875 public function getReplacementPackage()
26876 {
26877 return $this->aliasOf->getReplacementPackage();
26878 }
26879
26880 public function __toString()
26881 {
26882 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
26883 }
26884
26885 public function setDistUrl($url)
26886 {
26887 return $this->aliasOf->setDistUrl($url);
26888 }
26889
26890 public function setDistType($type)
26891 {
26892 return $this->aliasOf->setDistType($type);
26893 }
26894 }
26895 <?php
26896
26897
26898
26899
26900
26901
26902
26903
26904
26905
26906
26907 namespace Composer\Package\Archiver;
26908
26909 use FilterIterator;
26910 use PharData;
26911
26912 class ArchivableFilesFilter extends FilterIterator
26913 {
26914 private $dirs = array();
26915
26916
26917
26918
26919 public function accept()
26920 {
26921 $file = $this->getInnerIterator()->current();
26922 if ($file->isDir()) {
26923 $this->dirs[] = (string) $file;
26924
26925 return false;
26926 }
26927
26928 return true;
26929 }
26930
26931 public function addEmptyDir(PharData $phar, $sources)
26932 {
26933 foreach ($this->dirs as $filepath) {
26934 $localname = str_replace($sources . "/", '', $filepath);
26935 $phar->addEmptyDir($localname);
26936 }
26937 }
26938 }
26939 <?php
26940
26941
26942
26943
26944
26945
26946
26947
26948
26949
26950
26951 namespace Composer\Package\Archiver;
26952
26953 use Composer\Util\Filesystem;
26954 use FilesystemIterator;
26955 use Symfony\Component\Finder\Finder;
26956 use Symfony\Component\Finder\SplFileInfo;
26957
26958
26959
26960
26961
26962
26963
26964
26965
26966 class ArchivableFilesFinder extends \FilterIterator
26967 {
26968
26969
26970
26971 protected $finder;
26972
26973
26974
26975
26976
26977
26978
26979
26980 public function __construct($sources, array $excludes, $ignoreFilters = false)
26981 {
26982 $fs = new Filesystem();
26983
26984 $sources = $fs->normalizePath($sources);
26985
26986 if ($ignoreFilters) {
26987 $filters = array();
26988 } else {
26989 $filters = array(
26990 new HgExcludeFilter($sources),
26991 new GitExcludeFilter($sources),
26992 new ComposerExcludeFilter($sources, $excludes),
26993 );
26994 }
26995
26996 $this->finder = new Finder();
26997
26998 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
26999 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
27000 return false;
27001 }
27002
27003 $relativePath = preg_replace(
27004 '#^'.preg_quote($sources, '#').'#',
27005 '',
27006 $fs->normalizePath($file->getRealPath())
27007 );
27008
27009 $exclude = false;
27010 foreach ($filters as $filter) {
27011 $exclude = $filter->filter($relativePath, $exclude);
27012 }
27013
27014 return !$exclude;
27015 };
27016
27017 if (method_exists($filter, 'bindTo')) {
27018 $filter = $filter->bindTo(null);
27019 }
27020
27021 $this->finder
27022 ->in($sources)
27023 ->filter($filter)
27024 ->ignoreVCS(true)
27025 ->ignoreDotFiles(false);
27026
27027 parent::__construct($this->finder->getIterator());
27028 }
27029
27030 public function accept()
27031 {
27032
27033 $current = $this->getInnerIterator()->current();
27034
27035 if (!$current->isDir()) {
27036 return true;
27037 }
27038
27039 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
27040
27041 return !$iterator->valid();
27042 }
27043 }
27044 <?php
27045
27046
27047
27048
27049
27050
27051
27052
27053
27054
27055
27056 namespace Composer\Package\Archiver;
27057
27058 use Composer\Downloader\DownloadManager;
27059 use Composer\Package\PackageInterface;
27060 use Composer\Package\RootPackageInterface;
27061 use Composer\Util\Filesystem;
27062 use Composer\Json\JsonFile;
27063
27064
27065
27066
27067
27068 class ArchiveManager
27069 {
27070 protected $downloadManager;
27071
27072 protected $archivers = array();
27073
27074
27075
27076
27077 protected $overwriteFiles = true;
27078
27079
27080
27081
27082 public function __construct(DownloadManager $downloadManager)
27083 {
27084 $this->downloadManager = $downloadManager;
27085 }
27086
27087
27088
27089
27090 public function addArchiver(ArchiverInterface $archiver)
27091 {
27092 $this->archivers[] = $archiver;
27093 }
27094
27095
27096
27097
27098
27099
27100
27101
27102 public function setOverwriteFiles($overwriteFiles)
27103 {
27104 $this->overwriteFiles = $overwriteFiles;
27105
27106 return $this;
27107 }
27108
27109
27110
27111
27112
27113
27114
27115
27116 public function getPackageFilename(PackageInterface $package)
27117 {
27118 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
27119
27120 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
27121 array_push($nameParts, $package->getDistReference(), $package->getDistType());
27122 } else {
27123 array_push($nameParts, $package->getPrettyVersion(), $package->getDistReference());
27124 }
27125
27126 if ($package->getSourceReference()) {
27127 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
27128 }
27129
27130 $name = implode('-', array_filter($nameParts, function ($p) {
27131 return !empty($p);
27132 }));
27133
27134 return str_replace('/', '-', $name);
27135 }
27136
27137
27138
27139
27140
27141
27142
27143
27144
27145
27146
27147
27148
27149
27150 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
27151 {
27152 if (empty($format)) {
27153 throw new \InvalidArgumentException('Format must be specified');
27154 }
27155
27156
27157  $usableArchiver = null;
27158 foreach ($this->archivers as $archiver) {
27159 if ($archiver->supports($format, $package->getSourceType())) {
27160 $usableArchiver = $archiver;
27161 break;
27162 }
27163 }
27164
27165
27166  if (null === $usableArchiver) {
27167 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
27168 }
27169
27170 $filesystem = new Filesystem();
27171 if (null === $fileName) {
27172 $packageName = $this->getPackageFilename($package);
27173 } else {
27174 $packageName = $fileName;
27175 }
27176
27177
27178  $filesystem->ensureDirectoryExists($targetDir);
27179 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
27180 $filesystem->ensureDirectoryExists(dirname($target));
27181
27182 if (!$this->overwriteFiles && file_exists($target)) {
27183 return $target;
27184 }
27185
27186 if ($package instanceof RootPackageInterface) {
27187 $sourcePath = realpath('.');
27188 } else {
27189
27190  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
27191 $filesystem->ensureDirectoryExists($sourcePath);
27192
27193 try {
27194
27195  $this->downloadManager->download($package, $sourcePath);
27196 } catch (\Exception $e) {
27197 $filesystem->removeDirectory($sourcePath);
27198 throw $e;
27199 }
27200
27201
27202  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
27203 $jsonFile = new JsonFile($composerJsonPath);
27204 $jsonData = $jsonFile->read();
27205 if (!empty($jsonData['archive']['exclude'])) {
27206 $package->setArchiveExcludes($jsonData['archive']['exclude']);
27207 }
27208 }
27209 }
27210
27211
27212  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
27213 $filesystem->ensureDirectoryExists(dirname($tempTarget));
27214
27215 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
27216 $filesystem->rename($archivePath, $target);
27217
27218
27219  if (!$package instanceof RootPackageInterface) {
27220 $filesystem->removeDirectory($sourcePath);
27221 }
27222 $filesystem->remove($tempTarget);
27223
27224 return $target;
27225 }
27226 }
27227 <?php
27228
27229
27230
27231
27232
27233
27234
27235
27236
27237
27238
27239 namespace Composer\Package\Archiver;
27240
27241
27242
27243
27244
27245
27246 interface ArchiverInterface
27247 {
27248
27249
27250
27251
27252
27253
27254
27255
27256
27257
27258 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
27259
27260
27261
27262
27263
27264
27265
27266
27267
27268 public function supports($format, $sourceType);
27269 }
27270 <?php
27271
27272
27273
27274
27275
27276
27277
27278
27279
27280
27281
27282 namespace Composer\Package\Archiver;
27283
27284 use Symfony\Component\Finder;
27285
27286
27287
27288
27289 abstract class BaseExcludeFilter
27290 {
27291
27292
27293
27294 protected $sourcePath;
27295
27296
27297
27298
27299 protected $excludePatterns;
27300
27301
27302
27303
27304 public function __construct($sourcePath)
27305 {
27306 $this->sourcePath = $sourcePath;
27307 $this->excludePatterns = array();
27308 }
27309
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320 public function filter($relativePath, $exclude)
27321 {
27322 foreach ($this->excludePatterns as $patternData) {
27323 list($pattern, $negate, $stripLeadingSlash) = $patternData;
27324
27325 if ($stripLeadingSlash) {
27326 $path = substr($relativePath, 1);
27327 } else {
27328 $path = $relativePath;
27329 }
27330
27331 if (preg_match($pattern, $path)) {
27332 $exclude = !$negate;
27333 }
27334 }
27335
27336 return $exclude;
27337 }
27338
27339
27340
27341
27342
27343
27344
27345
27346
27347 protected function parseLines(array $lines, $lineParser)
27348 {
27349 return array_filter(
27350 array_map(
27351 function ($line) use ($lineParser) {
27352 $line = trim($line);
27353
27354 if (!$line || 0 === strpos($line, '#')) {
27355 return null;
27356 }
27357
27358 return call_user_func($lineParser, $line);
27359 },
27360 $lines
27361 ),
27362 function ($pattern) {
27363 return $pattern !== null;
27364 }
27365 );
27366 }
27367
27368
27369
27370
27371
27372
27373
27374
27375 protected function generatePatterns($rules)
27376 {
27377 $patterns = array();
27378 foreach ($rules as $rule) {
27379 $patterns[] = $this->generatePattern($rule);
27380 }
27381
27382 return $patterns;
27383 }
27384
27385
27386
27387
27388
27389
27390
27391
27392 protected function generatePattern($rule)
27393 {
27394 $negate = false;
27395 $pattern = '{';
27396
27397 if (strlen($rule) && $rule[0] === '!') {
27398 $negate = true;
27399 $rule = substr($rule, 1);
27400 }
27401
27402 if (strlen($rule) && $rule[0] === '/') {
27403 $pattern .= '^/';
27404 $rule = substr($rule, 1);
27405 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
27406 $pattern .= '/';
27407 $rule = substr($rule, 0, -1);
27408 } elseif (false === strpos($rule, '/')) {
27409 $pattern .= '/';
27410 }
27411
27412
27413  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
27414
27415 return array($pattern . '}', $negate, false);
27416 }
27417 }
27418 <?php
27419
27420
27421
27422
27423
27424
27425
27426
27427
27428
27429
27430 namespace Composer\Package\Archiver;
27431
27432
27433
27434
27435
27436
27437 class ComposerExcludeFilter extends BaseExcludeFilter
27438 {
27439
27440
27441
27442
27443 public function __construct($sourcePath, array $excludeRules)
27444 {
27445 parent::__construct($sourcePath);
27446 $this->excludePatterns = $this->generatePatterns($excludeRules);
27447 }
27448 }
27449 <?php
27450
27451
27452
27453
27454
27455
27456
27457
27458
27459
27460
27461 namespace Composer\Package\Archiver;
27462
27463
27464
27465
27466
27467
27468
27469
27470 class GitExcludeFilter extends BaseExcludeFilter
27471 {
27472
27473
27474
27475
27476
27477 public function __construct($sourcePath)
27478 {
27479 parent::__construct($sourcePath);
27480
27481 if (file_exists($sourcePath.'/.gitignore')) {
27482 $this->excludePatterns = $this->parseLines(
27483 file($sourcePath.'/.gitignore'),
27484 array($this, 'parseGitIgnoreLine')
27485 );
27486 }
27487 if (file_exists($sourcePath.'/.gitattributes')) {
27488 $this->excludePatterns = array_merge(
27489 $this->excludePatterns,
27490 $this->parseLines(
27491 file($sourcePath.'/.gitattributes'),
27492 array($this, 'parseGitAttributesLine')
27493 )
27494 );
27495 }
27496 }
27497
27498
27499
27500
27501
27502
27503
27504
27505 public function parseGitIgnoreLine($line)
27506 {
27507 return $this->generatePattern($line);
27508 }
27509
27510
27511
27512
27513
27514
27515
27516
27517 public function parseGitAttributesLine($line)
27518 {
27519 $parts = preg_split('#\s+#', $line);
27520
27521 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
27522 return $this->generatePattern($parts[0]);
27523 }
27524
27525 return null;
27526 }
27527 }
27528 <?php
27529
27530
27531
27532
27533
27534
27535
27536
27537
27538
27539
27540 namespace Composer\Package\Archiver;
27541
27542 use Symfony\Component\Finder;
27543
27544
27545
27546
27547
27548
27549 class HgExcludeFilter extends BaseExcludeFilter
27550 {
27551 const HG_IGNORE_REGEX = 1;
27552 const HG_IGNORE_GLOB = 2;
27553
27554
27555
27556
27557
27558 protected $patternMode;
27559
27560
27561
27562
27563
27564
27565 public function __construct($sourcePath)
27566 {
27567 parent::__construct($sourcePath);
27568
27569 $this->patternMode = self::HG_IGNORE_REGEX;
27570
27571 if (file_exists($sourcePath.'/.hgignore')) {
27572 $this->excludePatterns = $this->parseLines(
27573 file($sourcePath.'/.hgignore'),
27574 array($this, 'parseHgIgnoreLine')
27575 );
27576 }
27577 }
27578
27579
27580
27581
27582
27583
27584
27585
27586 public function parseHgIgnoreLine($line)
27587 {
27588 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
27589 if ($matches[1] === 'glob') {
27590 $this->patternMode = self::HG_IGNORE_GLOB;
27591 } else {
27592 $this->patternMode = self::HG_IGNORE_REGEX;
27593 }
27594
27595 return null;
27596 }
27597
27598 if ($this->patternMode == self::HG_IGNORE_GLOB) {
27599 return $this->patternFromGlob($line);
27600 }
27601
27602 return $this->patternFromRegex($line);
27603 }
27604
27605
27606
27607
27608
27609
27610
27611
27612 protected function patternFromGlob($line)
27613 {
27614 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
27615 $pattern = str_replace('[^/]*', '.*', $pattern);
27616
27617 return array($pattern, false, true);
27618 }
27619
27620
27621
27622
27623
27624
27625
27626
27627 public function patternFromRegex($line)
27628 {
27629
27630  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
27631
27632 return array($pattern, false, true);
27633 }
27634 }
27635 <?php
27636
27637
27638
27639
27640
27641
27642
27643
27644
27645
27646
27647 namespace Composer\Package\Archiver;
27648
27649
27650
27651
27652
27653
27654 class PharArchiver implements ArchiverInterface
27655 {
27656 protected static $formats = array(
27657 'zip' => \Phar::ZIP,
27658 'tar' => \Phar::TAR,
27659 'tar.gz' => \Phar::TAR,
27660 'tar.bz2' => \Phar::TAR,
27661 );
27662
27663 protected static $compressFormats = array(
27664 'tar.gz' => \Phar::GZ,
27665 'tar.bz2' => \Phar::BZ2,
27666 );
27667
27668
27669
27670
27671 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
27672 {
27673 $sources = realpath($sources);
27674
27675
27676  if (file_exists($target)) {
27677 unlink($target);
27678 }
27679
27680 try {
27681 $filename = substr($target, 0, strrpos($target, $format) - 1);
27682
27683
27684  if (isset(static::$compressFormats[$format])) {
27685
27686  $target = $filename . '.tar';
27687 }
27688
27689 $phar = new \PharData($target, null, null, static::$formats[$format]);
27690 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
27691 $filesOnly = new ArchivableFilesFilter($files);
27692 $phar->buildFromIterator($filesOnly, $sources);
27693 $filesOnly->addEmptyDir($phar, $sources);
27694
27695 if (isset(static::$compressFormats[$format])) {
27696
27697  if (!$phar->canCompress(static::$compressFormats[$format])) {
27698 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
27699 }
27700
27701
27702  unlink($target);
27703
27704
27705  $phar->compress(static::$compressFormats[$format]);
27706
27707
27708  $target = $filename . '.' . $format;
27709 }
27710
27711 return $target;
27712 } catch (\UnexpectedValueException $e) {
27713 $message = sprintf(
27714 "Could not create archive '%s' from '%s': %s",
27715 $target,
27716 $sources,
27717 $e->getMessage()
27718 );
27719
27720 throw new \RuntimeException($message, $e->getCode(), $e);
27721 }
27722 }
27723
27724
27725
27726
27727 public function supports($format, $sourceType)
27728 {
27729 return isset(static::$formats[$format]);
27730 }
27731 }
27732 <?php
27733
27734
27735
27736
27737
27738
27739
27740
27741
27742
27743
27744 namespace Composer\Package\Archiver;
27745
27746 use ZipArchive;
27747 use Composer\Util\Filesystem;
27748
27749
27750
27751
27752 class ZipArchiver implements ArchiverInterface
27753 {
27754 protected static $formats = array(
27755 'zip' => 1,
27756 );
27757
27758
27759
27760
27761 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
27762 {
27763 $fs = new Filesystem();
27764 $sources = $fs->normalizePath($sources);
27765
27766 $zip = new ZipArchive();
27767 $res = $zip->open($target, ZipArchive::CREATE);
27768 if ($res === true) {
27769 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
27770 foreach ($files as $file) {
27771
27772 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
27773 $localname = str_replace($sources.'/', '', $filepath);
27774 if ($file->isDir()) {
27775 $zip->addEmptyDir($localname);
27776 } else {
27777 $zip->addFile($filepath, $localname);
27778 }
27779
27780
27781
27782
27783 if (PHP_VERSION_ID >= 50600) {
27784 $perms = fileperms($filepath);
27785
27786
27787
27788
27789 $zip->setExternalAttributesName($localname, ZipArchive::OPSYS_UNIX, $perms << 16);
27790 }
27791 }
27792 if ($zip->close()) {
27793 return $target;
27794 }
27795 }
27796 $message = sprintf(
27797 "Could not create archive '%s' from '%s': %s",
27798 $target,
27799 $sources,
27800 $zip->getStatusString()
27801 );
27802 throw new \RuntimeException($message);
27803 }
27804
27805
27806
27807
27808 public function supports($format, $sourceType)
27809 {
27810 return isset(static::$formats[$format]) && $this->compressionAvailable();
27811 }
27812
27813 private function compressionAvailable()
27814 {
27815 return class_exists('ZipArchive');
27816 }
27817 }
27818 <?php
27819
27820
27821
27822
27823
27824
27825
27826
27827
27828
27829
27830 namespace Composer\Package;
27831
27832 use Composer\Repository\RepositoryInterface;
27833 use Composer\Repository\PlatformRepository;
27834
27835
27836
27837
27838
27839
27840 abstract class BasePackage implements PackageInterface
27841 {
27842 public static $supportedLinkTypes = array(
27843 'require' => array('description' => 'requires', 'method' => 'requires'),
27844 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
27845 'provide' => array('description' => 'provides', 'method' => 'provides'),
27846 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
27847 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
27848 );
27849
27850 const STABILITY_STABLE = 0;
27851 const STABILITY_RC = 5;
27852 const STABILITY_BETA = 10;
27853 const STABILITY_ALPHA = 15;
27854 const STABILITY_DEV = 20;
27855
27856 public static $stabilities = array(
27857 'stable' => self::STABILITY_STABLE,
27858 'RC' => self::STABILITY_RC,
27859 'beta' => self::STABILITY_BETA,
27860 'alpha' => self::STABILITY_ALPHA,
27861 'dev' => self::STABILITY_DEV,
27862 );
27863
27864
27865
27866
27867
27868 public $id;
27869
27870 protected $name;
27871
27872 protected $prettyName;
27873
27874 protected $repository;
27875
27876 protected $transportOptions = array();
27877
27878
27879
27880
27881
27882
27883 public function __construct($name)
27884 {
27885 $this->prettyName = $name;
27886 $this->name = strtolower($name);
27887 $this->id = -1;
27888 }
27889
27890
27891
27892
27893 public function getName()
27894 {
27895 return $this->name;
27896 }
27897
27898
27899
27900
27901 public function getPrettyName()
27902 {
27903 return $this->prettyName;
27904 }
27905
27906
27907
27908
27909 public function getNames()
27910 {
27911 $names = array(
27912 $this->getName() => true,
27913 );
27914
27915 foreach ($this->getProvides() as $link) {
27916 $names[$link->getTarget()] = true;
27917 }
27918
27919 foreach ($this->getReplaces() as $link) {
27920 $names[$link->getTarget()] = true;
27921 }
27922
27923 return array_keys($names);
27924 }
27925
27926
27927
27928
27929 public function setId($id)
27930 {
27931 $this->id = $id;
27932 }
27933
27934
27935
27936
27937 public function getId()
27938 {
27939 return $this->id;
27940 }
27941
27942
27943
27944
27945 public function setRepository(RepositoryInterface $repository)
27946 {
27947 if ($this->repository && $repository !== $this->repository) {
27948 throw new \LogicException('A package can only be added to one repository');
27949 }
27950 $this->repository = $repository;
27951 }
27952
27953
27954
27955
27956 public function getRepository()
27957 {
27958 return $this->repository;
27959 }
27960
27961
27962
27963
27964 public function getTransportOptions()
27965 {
27966 return $this->transportOptions;
27967 }
27968
27969
27970
27971
27972
27973
27974 public function setTransportOptions(array $options)
27975 {
27976 $this->transportOptions = $options;
27977 }
27978
27979
27980
27981
27982
27983
27984 public function isPlatform()
27985 {
27986 return $this->getRepository() instanceof PlatformRepository;
27987 }
27988
27989
27990
27991
27992
27993
27994 public function getUniqueName()
27995 {
27996 return $this->getName().'-'.$this->getVersion();
27997 }
27998
27999 public function equals(PackageInterface $package)
28000 {
28001 $self = $this;
28002 if ($this instanceof AliasPackage) {
28003 $self = $this->getAliasOf();
28004 }
28005 if ($package instanceof AliasPackage) {
28006 $package = $package->getAliasOf();
28007 }
28008
28009 return $package === $self;
28010 }
28011
28012
28013
28014
28015
28016
28017 public function __toString()
28018 {
28019 return $this->getUniqueName();
28020 }
28021
28022 public function getPrettyString()
28023 {
28024 return $this->getPrettyName().' '.$this->getPrettyVersion();
28025 }
28026
28027
28028
28029
28030 public function getFullPrettyVersion($truncate = true)
28031 {
28032 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
28033 return $this->getPrettyVersion();
28034 }
28035
28036
28037  if ($truncate && strlen($this->getSourceReference()) === 40) {
28038 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
28039 }
28040
28041 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
28042 }
28043
28044 public function getStabilityPriority()
28045 {
28046 return self::$stabilities[$this->getStability()];
28047 }
28048
28049 public function __clone()
28050 {
28051 $this->repository = null;
28052 $this->id = -1;
28053 }
28054
28055
28056
28057
28058
28059
28060
28061
28062 public static function packageNameToRegexp($whiteListedPattern, $wrap = '{^%s$}i')
28063 {
28064 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
28065
28066 return sprintf($wrap, $cleanedWhiteListedPattern);
28067 }
28068 }
28069 <?php
28070
28071
28072
28073
28074
28075
28076
28077
28078
28079
28080
28081 namespace Composer\Package\Comparer;
28082
28083
28084
28085
28086
28087
28088 class Comparer
28089 {
28090 private $source;
28091 private $update;
28092 private $changed;
28093
28094 public function setSource($source)
28095 {
28096 $this->source = $source;
28097 }
28098
28099 public function setUpdate($update)
28100 {
28101 $this->update = $update;
28102 }
28103
28104 public function getChanged($toString = false, $explicated = false)
28105 {
28106 $changed = $this->changed;
28107 if (!count($changed)) {
28108 return false;
28109 }
28110 if ($explicated) {
28111 foreach ($changed as $sectionKey => $itemSection) {
28112 foreach ($itemSection as $itemKey => $item) {
28113 $changed[$sectionKey][$itemKey] = $item.' ('.$sectionKey.')';
28114 }
28115 }
28116 }
28117
28118 if ($toString) {
28119 foreach ($changed as $sectionKey => $itemSection) {
28120 foreach ($itemSection as $itemKey => $item) {
28121 $changed['string'][] = $item."\r\n";
28122 }
28123 }
28124 $changed = implode("\r\n", $changed['string']);
28125 }
28126
28127 return $changed;
28128 }
28129
28130 public function doCompare()
28131 {
28132 $source = array();
28133 $destination = array();
28134 $this->changed = array();
28135 $currentDirectory = getcwd();
28136 chdir($this->source);
28137 $source = $this->doTree('.', $source);
28138 if (!is_array($source)) {
28139 return;
28140 }
28141 chdir($currentDirectory);
28142 chdir($this->update);
28143 $destination = $this->doTree('.', $destination);
28144 if (!is_array($destination)) {
28145 exit;
28146 }
28147 chdir($currentDirectory);
28148 foreach ($source as $dir => $value) {
28149 foreach ($value as $file => $hash) {
28150 if (isset($destination[$dir][$file])) {
28151 if ($hash !== $destination[$dir][$file]) {
28152 $this->changed['changed'][] = $dir.'/'.$file;
28153 }
28154 } else {
28155 $this->changed['removed'][] = $dir.'/'.$file;
28156 }
28157 }
28158 }
28159 foreach ($destination as $dir => $value) {
28160 foreach ($value as $file => $hash) {
28161 if (!isset($source[$dir][$file])) {
28162 $this->changed['added'][] = $dir.'/'.$file;
28163 }
28164 }
28165 }
28166 }
28167
28168 private function doTree($dir, &$array)
28169 {
28170 if ($dh = opendir($dir)) {
28171 while ($file = readdir($dh)) {
28172 if ($file !== '.' && $file !== '..') {
28173 if (is_dir($dir.'/'.$file)) {
28174 if (!count($array)) {
28175 $array[0] = 'Temp';
28176 }
28177 if (!$this->doTree($dir.'/'.$file, $array)) {
28178 return false;
28179 }
28180 } else {
28181 if (filesize($dir.'/'.$file)) {
28182 set_time_limit(30);
28183 $array[$dir][$file] = md5_file($dir.'/'.$file);
28184 }
28185 }
28186 }
28187 }
28188 if (count($array) > 1 && isset($array['0'])) {
28189 unset($array['0']);
28190 }
28191
28192 return $array;
28193 }
28194
28195 return false;
28196 }
28197 }
28198 <?php
28199
28200
28201
28202
28203
28204
28205
28206
28207
28208
28209
28210 namespace Composer\Package;
28211
28212
28213
28214
28215
28216
28217 class CompletePackage extends Package implements CompletePackageInterface
28218 {
28219 protected $repositories;
28220 protected $license = array();
28221 protected $keywords;
28222 protected $authors;
28223 protected $description;
28224 protected $homepage;
28225 protected $scripts = array();
28226 protected $support = array();
28227 protected $funding = array();
28228 protected $abandoned = false;
28229
28230
28231
28232
28233 public function setScripts(array $scripts)
28234 {
28235 $this->scripts = $scripts;
28236 }
28237
28238
28239
28240
28241 public function getScripts()
28242 {
28243 return $this->scripts;
28244 }
28245
28246
28247
28248
28249
28250
28251 public function setRepositories($repositories)
28252 {
28253 $this->repositories = $repositories;
28254 }
28255
28256
28257
28258
28259 public function getRepositories()
28260 {
28261 return $this->repositories;
28262 }
28263
28264
28265
28266
28267
28268
28269 public function setLicense(array $license)
28270 {
28271 $this->license = $license;
28272 }
28273
28274
28275
28276
28277 public function getLicense()
28278 {
28279 return $this->license;
28280 }
28281
28282
28283
28284
28285
28286
28287 public function setKeywords(array $keywords)
28288 {
28289 $this->keywords = $keywords;
28290 }
28291
28292
28293
28294
28295 public function getKeywords()
28296 {
28297 return $this->keywords;
28298 }
28299
28300
28301
28302
28303
28304
28305 public function setAuthors(array $authors)
28306 {
28307 $this->authors = $authors;
28308 }
28309
28310
28311
28312
28313 public function getAuthors()
28314 {
28315 return $this->authors;
28316 }
28317
28318
28319
28320
28321
28322
28323 public function setDescription($description)
28324 {
28325 $this->description = $description;
28326 }
28327
28328
28329
28330
28331 public function getDescription()
28332 {
28333 return $this->description;
28334 }
28335
28336
28337
28338
28339
28340
28341 public function setHomepage($homepage)
28342 {
28343 $this->homepage = $homepage;
28344 }
28345
28346
28347
28348
28349 public function getHomepage()
28350 {
28351 return $this->homepage;
28352 }
28353
28354
28355
28356
28357
28358
28359 public function setSupport(array $support)
28360 {
28361 $this->support = $support;
28362 }
28363
28364
28365
28366
28367 public function getSupport()
28368 {
28369 return $this->support;
28370 }
28371
28372
28373
28374
28375
28376
28377 public function setFunding(array $funding)
28378 {
28379 $this->funding = $funding;
28380 }
28381
28382
28383
28384
28385 public function getFunding()
28386 {
28387 return $this->funding;
28388 }
28389
28390
28391
28392
28393 public function isAbandoned()
28394 {
28395 return (bool) $this->abandoned;
28396 }
28397
28398
28399
28400
28401 public function setAbandoned($abandoned)
28402 {
28403 $this->abandoned = $abandoned;
28404 }
28405
28406
28407
28408
28409
28410
28411 public function getReplacementPackage()
28412 {
28413 return is_string($this->abandoned) ? $this->abandoned : null;
28414 }
28415 }
28416 <?php
28417
28418
28419
28420
28421
28422
28423
28424
28425
28426
28427
28428 namespace Composer\Package;
28429
28430
28431
28432
28433
28434
28435 interface CompletePackageInterface extends PackageInterface
28436 {
28437
28438
28439
28440
28441
28442 public function getScripts();
28443
28444
28445
28446
28447
28448
28449
28450
28451 public function getRepositories();
28452
28453
28454
28455
28456
28457
28458 public function getLicense();
28459
28460
28461
28462
28463
28464
28465 public function getKeywords();
28466
28467
28468
28469
28470
28471
28472 public function getDescription();
28473
28474
28475
28476
28477
28478
28479 public function getHomepage();
28480
28481
28482
28483
28484
28485
28486
28487
28488 public function getAuthors();
28489
28490
28491
28492
28493
28494
28495 public function getSupport();
28496
28497
28498
28499
28500
28501
28502
28503
28504 public function getFunding();
28505
28506
28507
28508
28509
28510
28511 public function isAbandoned();
28512
28513
28514
28515
28516
28517
28518 public function getReplacementPackage();
28519 }
28520 <?php
28521
28522
28523
28524
28525
28526
28527
28528
28529
28530
28531
28532 namespace Composer\Package\Dumper;
28533
28534 use Composer\Package\BasePackage;
28535 use Composer\Package\PackageInterface;
28536 use Composer\Package\CompletePackageInterface;
28537 use Composer\Package\RootPackageInterface;
28538
28539
28540
28541
28542
28543 class ArrayDumper
28544 {
28545 public function dump(PackageInterface $package)
28546 {
28547 $keys = array(
28548 'binaries' => 'bin',
28549 'type',
28550 'extra',
28551 'installationSource' => 'installation-source',
28552 'autoload',
28553 'devAutoload' => 'autoload-dev',
28554 'notificationUrl' => 'notification-url',
28555 'includePaths' => 'include-path',
28556 );
28557
28558 $data = array();
28559 $data['name'] = $package->getPrettyName();
28560 $data['version'] = $package->getPrettyVersion();
28561 $data['version_normalized'] = $package->getVersion();
28562
28563 if ($package->getTargetDir()) {
28564 $data['target-dir'] = $package->getTargetDir();
28565 }
28566
28567 if ($package->getSourceType()) {
28568 $data['source']['type'] = $package->getSourceType();
28569 $data['source']['url'] = $package->getSourceUrl();
28570 if (null !== ($value = $package->getSourceReference())) {
28571 $data['source']['reference'] = $value;
28572 }
28573 if ($mirrors = $package->getSourceMirrors()) {
28574 $data['source']['mirrors'] = $mirrors;
28575 }
28576 }
28577
28578 if ($package->getDistType()) {
28579 $data['dist']['type'] = $package->getDistType();
28580 $data['dist']['url'] = $package->getDistUrl();
28581 if (null !== ($value = $package->getDistReference())) {
28582 $data['dist']['reference'] = $value;
28583 }
28584 if (null !== ($value = $package->getDistSha1Checksum())) {
28585 $data['dist']['shasum'] = $value;
28586 }
28587 if ($mirrors = $package->getDistMirrors()) {
28588 $data['dist']['mirrors'] = $mirrors;
28589 }
28590 }
28591
28592 if ($package->getArchiveExcludes()) {
28593 $data['archive']['exclude'] = $package->getArchiveExcludes();
28594 }
28595
28596 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
28597 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
28598 foreach ($links as $link) {
28599 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
28600 }
28601 ksort($data[$type]);
28602 }
28603 }
28604
28605 if ($packages = $package->getSuggests()) {
28606 ksort($packages);
28607 $data['suggest'] = $packages;
28608 }
28609
28610 if ($package->getReleaseDate()) {
28611 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
28612 }
28613
28614 $data = $this->dumpValues($package, $keys, $data);
28615
28616 if ($package instanceof CompletePackageInterface) {
28617 $keys = array(
28618 'scripts',
28619 'license',
28620 'authors',
28621 'description',
28622 'homepage',
28623 'keywords',
28624 'repositories',
28625 'support',
28626 'funding',
28627 );
28628
28629 $data = $this->dumpValues($package, $keys, $data);
28630
28631 if (isset($data['keywords']) && is_array($data['keywords'])) {
28632 sort($data['keywords']);
28633 }
28634
28635 if ($package->isAbandoned()) {
28636 $data['abandoned'] = $package->getReplacementPackage() ?: true;
28637 }
28638 }
28639
28640 if ($package instanceof RootPackageInterface) {
28641 $minimumStability = $package->getMinimumStability();
28642 if ($minimumStability) {
28643 $data['minimum-stability'] = $minimumStability;
28644 }
28645 }
28646
28647 if (count($package->getTransportOptions()) > 0) {
28648 $data['transport-options'] = $package->getTransportOptions();
28649 }
28650
28651 return $data;
28652 }
28653
28654 private function dumpValues(PackageInterface $package, array $keys, array $data)
28655 {
28656 foreach ($keys as $method => $key) {
28657 if (is_numeric($method)) {
28658 $method = $key;
28659 }
28660
28661 $getter = 'get'.ucfirst($method);
28662 $value = $package->$getter();
28663
28664 if (null !== $value && !(is_array($value) && 0 === count($value))) {
28665 $data[$key] = $value;
28666 }
28667 }
28668
28669 return $data;
28670 }
28671 }
28672 <?php
28673
28674
28675
28676
28677
28678
28679
28680
28681
28682
28683
28684 namespace Composer\Package;
28685
28686 use Composer\Semver\Constraint\ConstraintInterface;
28687
28688
28689
28690
28691
28692
28693 class Link
28694 {
28695
28696
28697
28698 protected $source;
28699
28700
28701
28702
28703 protected $target;
28704
28705
28706
28707
28708 protected $constraint;
28709
28710
28711
28712
28713 protected $description;
28714
28715
28716
28717
28718 protected $prettyConstraint;
28719
28720
28721
28722
28723
28724
28725
28726
28727
28728
28729 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
28730 {
28731 $this->source = strtolower($source);
28732 $this->target = strtolower($target);
28733 $this->constraint = $constraint;
28734 $this->description = $description;
28735 $this->prettyConstraint = $prettyConstraint;
28736 }
28737
28738
28739
28740
28741 public function getDescription()
28742 {
28743 return $this->description;
28744 }
28745
28746
28747
28748
28749 public function getSource()
28750 {
28751 return $this->source;
28752 }
28753
28754
28755
28756
28757 public function getTarget()
28758 {
28759 return $this->target;
28760 }
28761
28762
28763
28764
28765 public function getConstraint()
28766 {
28767 return $this->constraint;
28768 }
28769
28770
28771
28772
28773
28774 public function getPrettyConstraint()
28775 {
28776 if (null === $this->prettyConstraint) {
28777 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
28778 }
28779
28780 return $this->prettyConstraint;
28781 }
28782
28783
28784
28785
28786 public function __toString()
28787 {
28788 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
28789 }
28790
28791
28792
28793
28794
28795 public function getPrettyString(PackageInterface $sourcePackage)
28796 {
28797 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
28798 }
28799 }
28800 <?php
28801
28802
28803
28804
28805
28806
28807
28808
28809
28810
28811
28812 namespace Composer\Package\LinkConstraint;
28813
28814 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
28815
28816 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
28817
28818
28819
28820
28821 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
28822 {
28823 }
28824 <?php
28825
28826
28827
28828
28829
28830
28831
28832
28833
28834
28835
28836 namespace Composer\Package\LinkConstraint;
28837
28838 use Composer\Semver\Constraint\ConstraintInterface;
28839
28840 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
28841
28842
28843
28844
28845 interface LinkConstraintInterface extends ConstraintInterface
28846 {
28847 }
28848 <?php
28849
28850
28851
28852
28853
28854
28855
28856
28857
28858
28859
28860 namespace Composer\Package\LinkConstraint;
28861
28862 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
28863
28864 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
28865
28866
28867
28868
28869 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
28870 {
28871 }
28872 <?php
28873
28874
28875
28876
28877
28878
28879
28880
28881
28882
28883
28884 namespace Composer\Package\LinkConstraint;
28885
28886 use Composer\Semver\Constraint\AbstractConstraint;
28887
28888 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
28889
28890
28891
28892
28893 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
28894 {
28895 }
28896 <?php
28897
28898
28899
28900
28901
28902
28903
28904
28905
28906
28907
28908 namespace Composer\Package\LinkConstraint;
28909
28910 use Composer\Semver\Constraint\Constraint;
28911
28912 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
28913
28914
28915
28916
28917 class VersionConstraint extends Constraint implements LinkConstraintInterface
28918 {
28919 }
28920 <?php
28921
28922
28923
28924
28925
28926
28927
28928
28929
28930
28931
28932 namespace Composer\Package\Loader;
28933
28934 use Composer\Package;
28935 use Composer\Package\AliasPackage;
28936 use Composer\Package\Link;
28937 use Composer\Package\RootAliasPackage;
28938 use Composer\Package\RootPackageInterface;
28939 use Composer\Package\Version\VersionParser;
28940 use Composer\Semver\VersionParser as SemverVersionParser;
28941
28942
28943
28944
28945
28946 class ArrayLoader implements LoaderInterface
28947 {
28948 protected $versionParser;
28949 protected $loadOptions;
28950
28951 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
28952 {
28953 if (!$parser) {
28954 $parser = new VersionParser;
28955 }
28956 $this->versionParser = $parser;
28957 $this->loadOptions = $loadOptions;
28958 }
28959
28960 public function load(array $config, $class = 'Composer\Package\CompletePackage')
28961 {
28962 if (!isset($config['name'])) {
28963 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
28964 }
28965 if (!isset($config['version'])) {
28966 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
28967 }
28968
28969
28970  if (isset($config['version_normalized'])) {
28971 $version = $config['version_normalized'];
28972 } else {
28973 $version = $this->versionParser->normalize($config['version']);
28974 }
28975 $package = new $class($config['name'], $version, $config['version']);
28976 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
28977
28978 if (isset($config['target-dir'])) {
28979 $package->setTargetDir($config['target-dir']);
28980 }
28981
28982 if (isset($config['extra']) && is_array($config['extra'])) {
28983 $package->setExtra($config['extra']);
28984 }
28985
28986 if (isset($config['bin'])) {
28987 foreach ((array) $config['bin'] as $key => $bin) {
28988 $config['bin'][$key] = ltrim($bin, '/');
28989 }
28990 $package->setBinaries((array) $config['bin']);
28991 }
28992
28993 if (isset($config['installation-source'])) {
28994 $package->setInstallationSource($config['installation-source']);
28995 }
28996
28997 if (isset($config['source'])) {
28998 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
28999 throw new \UnexpectedValueException(sprintf(
29000 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
29001 $config['name'],
29002 json_encode($config['source'])
29003 ));
29004 }
29005 $package->setSourceType($config['source']['type']);
29006 $package->setSourceUrl($config['source']['url']);
29007 $package->setSourceReference(isset($config['source']['reference']) ? $config['source']['reference'] : null);
29008 if (isset($config['source']['mirrors'])) {
29009 $package->setSourceMirrors($config['source']['mirrors']);
29010 }
29011 }
29012
29013 if (isset($config['dist'])) {
29014 if (!isset($config['dist']['type'])
29015 || !isset($config['dist']['url'])) {
29016 throw new \UnexpectedValueException(sprintf(
29017 "Package %s's dist key should be specified as ".
29018 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
29019 $config['name'],
29020 json_encode($config['dist'])
29021 ));
29022 }
29023 $package->setDistType($config['dist']['type']);
29024 $package->setDistUrl($config['dist']['url']);
29025 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
29026 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
29027 if (isset($config['dist']['mirrors'])) {
29028 $package->setDistMirrors($config['dist']['mirrors']);
29029 }
29030 }
29031
29032 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
29033 if (isset($config[$type])) {
29034 $method = 'set'.ucfirst($opts['method']);
29035 $package->{$method}(
29036 $this->parseLinks(
29037 $package->getName(),
29038 $package->getPrettyVersion(),
29039 $opts['description'],
29040 $config[$type]
29041 )
29042 );
29043 }
29044 }
29045
29046 if (isset($config['suggest']) && is_array($config['suggest'])) {
29047 foreach ($config['suggest'] as $target => $reason) {
29048 if ('self.version' === trim($reason)) {
29049 $config['suggest'][$target] = $package->getPrettyVersion();
29050 }
29051 }
29052 $package->setSuggests($config['suggest']);
29053 }
29054
29055 if (isset($config['autoload'])) {
29056 $package->setAutoload($config['autoload']);
29057 }
29058
29059 if (isset($config['autoload-dev'])) {
29060 $package->setDevAutoload($config['autoload-dev']);
29061 }
29062
29063 if (isset($config['include-path'])) {
29064 $package->setIncludePaths($config['include-path']);
29065 }
29066
29067 if (!empty($config['time'])) {
29068 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
29069
29070 try {
29071 $date = new \DateTime($time, new \DateTimeZone('UTC'));
29072 $package->setReleaseDate($date);
29073 } catch (\Exception $e) {
29074 }
29075 }
29076
29077 if (!empty($config['notification-url'])) {
29078 $package->setNotificationUrl($config['notification-url']);
29079 }
29080
29081 if (!empty($config['archive']['exclude'])) {
29082 $package->setArchiveExcludes($config['archive']['exclude']);
29083 }
29084
29085 if ($package instanceof Package\CompletePackageInterface) {
29086 if (isset($config['scripts']) && is_array($config['scripts'])) {
29087 foreach ($config['scripts'] as $event => $listeners) {
29088 $config['scripts'][$event] = (array) $listeners;
29089 }
29090 if (isset($config['scripts']['composer'])) {
29091 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
29092 }
29093 $package->setScripts($config['scripts']);
29094 }
29095
29096 if (!empty($config['description']) && is_string($config['description'])) {
29097 $package->setDescription($config['description']);
29098 }
29099
29100 if (!empty($config['homepage']) && is_string($config['homepage'])) {
29101 $package->setHomepage($config['homepage']);
29102 }
29103
29104 if (!empty($config['keywords']) && is_array($config['keywords'])) {
29105 $package->setKeywords($config['keywords']);
29106 }
29107
29108 if (!empty($config['license'])) {
29109 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
29110 }
29111
29112 if (!empty($config['authors']) && is_array($config['authors'])) {
29113 $package->setAuthors($config['authors']);
29114 }
29115
29116 if (isset($config['support'])) {
29117 $package->setSupport($config['support']);
29118 }
29119
29120 if (!empty($config['funding']) && is_array($config['funding'])) {
29121 $package->setFunding($config['funding']);
29122 }
29123
29124 if (isset($config['abandoned'])) {
29125 $package->setAbandoned($config['abandoned']);
29126 }
29127 }
29128
29129 if ($aliasNormalized = $this->getBranchAlias($config)) {
29130 if ($package instanceof RootPackageInterface) {
29131 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
29132 } else {
29133 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
29134 }
29135 }
29136
29137 if ($this->loadOptions && isset($config['transport-options'])) {
29138 $package->setTransportOptions($config['transport-options']);
29139 }
29140
29141 return $package;
29142 }
29143
29144
29145
29146
29147
29148
29149
29150
29151 public function parseLinks($source, $sourceVersion, $description, $links)
29152 {
29153 $res = array();
29154 foreach ($links as $target => $constraint) {
29155 if (!is_string($constraint)) {
29156 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
29157 }
29158 if ('self.version' === $constraint) {
29159 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
29160 } else {
29161 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
29162 }
29163
29164 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
29165 }
29166
29167 return $res;
29168 }
29169
29170
29171
29172
29173
29174
29175
29176 public function getBranchAlias(array $config)
29177 {
29178 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
29179 || !isset($config['extra']['branch-alias'])
29180 || !is_array($config['extra']['branch-alias'])
29181 ) {
29182 return;
29183 }
29184
29185 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
29186
29187  if ('-dev' !== substr($targetBranch, -4)) {
29188 continue;
29189 }
29190
29191
29192  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
29193 if ('-dev' !== substr($validatedTargetBranch, -4)) {
29194 continue;
29195 }
29196
29197
29198  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
29199 continue;
29200 }
29201
29202
29203  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
29204 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
29205 && (stripos($targetPrefix, $sourcePrefix) !== 0)
29206 ) {
29207 continue;
29208 }
29209
29210 return $validatedTargetBranch;
29211 }
29212 }
29213 }
29214 <?php
29215
29216
29217
29218
29219
29220
29221
29222
29223
29224
29225
29226 namespace Composer\Package\Loader;
29227
29228
29229
29230
29231 class InvalidPackageException extends \Exception
29232 {
29233 private $errors;
29234 private $warnings;
29235 private $data;
29236
29237 public function __construct(array $errors, array $warnings, array $data)
29238 {
29239 $this->errors = $errors;
29240 $this->warnings = $warnings;
29241 $this->data = $data;
29242 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
29243 }
29244
29245 public function getData()
29246 {
29247 return $this->data;
29248 }
29249
29250 public function getErrors()
29251 {
29252 return $this->errors;
29253 }
29254
29255 public function getWarnings()
29256 {
29257 return $this->warnings;
29258 }
29259 }
29260 <?php
29261
29262
29263
29264
29265
29266
29267
29268
29269
29270
29271
29272 namespace Composer\Package\Loader;
29273
29274 use Composer\Json\JsonFile;
29275
29276
29277
29278
29279 class JsonLoader
29280 {
29281 private $loader;
29282
29283 public function __construct(LoaderInterface $loader)
29284 {
29285 $this->loader = $loader;
29286 }
29287
29288
29289
29290
29291
29292 public function load($json)
29293 {
29294 if ($json instanceof JsonFile) {
29295 $config = $json->read();
29296 } elseif (file_exists($json)) {
29297 $config = JsonFile::parseJson(file_get_contents($json), $json);
29298 } elseif (is_string($json)) {
29299 $config = JsonFile::parseJson($json);
29300 }
29301
29302 return $this->loader->load($config);
29303 }
29304 }
29305 <?php
29306
29307
29308
29309
29310
29311
29312
29313
29314
29315
29316
29317 namespace Composer\Package\Loader;
29318
29319
29320
29321
29322
29323
29324 interface LoaderInterface
29325 {
29326
29327
29328
29329
29330
29331
29332
29333 public function load(array $package, $class = 'Composer\Package\CompletePackage');
29334 }
29335 <?php
29336
29337
29338
29339
29340
29341
29342
29343
29344
29345
29346
29347 namespace Composer\Package\Loader;
29348
29349 use Composer\Package\BasePackage;
29350 use Composer\Package\AliasPackage;
29351 use Composer\Config;
29352 use Composer\IO\IOInterface;
29353 use Composer\Package\RootPackageInterface;
29354 use Composer\Repository\RepositoryFactory;
29355 use Composer\Package\Version\VersionGuesser;
29356 use Composer\Package\Version\VersionParser;
29357 use Composer\Repository\RepositoryManager;
29358 use Composer\Util\ProcessExecutor;
29359
29360
29361
29362
29363
29364
29365
29366
29367 class RootPackageLoader extends ArrayLoader
29368 {
29369
29370
29371
29372 private $manager;
29373
29374
29375
29376
29377 private $config;
29378
29379
29380
29381
29382 private $versionGuesser;
29383
29384
29385
29386
29387 private $io;
29388
29389 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null, IOInterface $io = null)
29390 {
29391 parent::__construct($parser);
29392
29393 $this->manager = $manager;
29394 $this->config = $config;
29395 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
29396 $this->io = $io;
29397 }
29398
29399
29400
29401
29402
29403
29404
29405 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
29406 {
29407 if (!isset($config['name'])) {
29408 $config['name'] = '__root__';
29409 } elseif ($this->io) {
29410 if ($err = ValidatingArrayLoader::hasPackageNamingError($config['name'])) {
29411 $this->io->writeError('<warning>Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
29412 }
29413 }
29414 $autoVersioned = false;
29415 if (!isset($config['version'])) {
29416 $commit = null;
29417
29418
29419  if (getenv('COMPOSER_ROOT_VERSION')) {
29420 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
29421 } else {
29422 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
29423 if ($versionData) {
29424 $config['version'] = $versionData['pretty_version'];
29425 $config['version_normalized'] = $versionData['version'];
29426 $commit = $versionData['commit'];
29427 }
29428 }
29429
29430 if (!isset($config['version'])) {
29431 $config['version'] = '1.0.0';
29432 $autoVersioned = true;
29433 }
29434
29435 if ($commit) {
29436 $config['source'] = array(
29437 'type' => '',
29438 'url' => '',
29439 'reference' => $commit,
29440 );
29441 $config['dist'] = array(
29442 'type' => '',
29443 'url' => '',
29444 'reference' => $commit,
29445 );
29446 }
29447 }
29448
29449 $realPackage = $package = parent::load($config, $class);
29450 if ($realPackage instanceof AliasPackage) {
29451 $realPackage = $package->getAliasOf();
29452 }
29453
29454 if ($autoVersioned) {
29455 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
29456 }
29457
29458 if (isset($config['minimum-stability'])) {
29459 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
29460 }
29461
29462 $aliases = array();
29463 $stabilityFlags = array();
29464 $references = array();
29465 foreach (array('require', 'require-dev') as $linkType) {
29466 if (isset($config[$linkType])) {
29467 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
29468 $method = 'get'.ucfirst($linkInfo['method']);
29469 $links = array();
29470 foreach ($realPackage->$method() as $link) {
29471 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
29472 }
29473 $aliases = $this->extractAliases($links, $aliases);
29474 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
29475 $references = $this->extractReferences($links, $references);
29476
29477 if (isset($links[$config['name']])) {
29478 throw new \RuntimeException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
29479 'Did you accidentally name your root package after an external package?', $config['name']));
29480 }
29481 }
29482 }
29483
29484 if ($this->io) {
29485 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
29486 if (isset($config[$linkType])) {
29487 foreach ($config[$linkType] as $linkName => $constraint) {
29488 if ($err = ValidatingArrayLoader::hasPackageNamingError($linkName, true)) {
29489 $this->io->writeError('<warning>Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.</warning>');
29490 }
29491 }
29492 }
29493 }
29494 }
29495
29496 $realPackage->setAliases($aliases);
29497 $realPackage->setStabilityFlags($stabilityFlags);
29498 $realPackage->setReferences($references);
29499
29500 if (isset($config['prefer-stable'])) {
29501 $realPackage->setPreferStable((bool) $config['prefer-stable']);
29502 }
29503
29504 if (isset($config['config'])) {
29505 $realPackage->setConfig($config['config']);
29506 }
29507
29508 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
29509 foreach ($repos as $repo) {
29510 $this->manager->addRepository($repo);
29511 }
29512 $realPackage->setRepositories($this->config->getRepositories());
29513
29514 return $package;
29515 }
29516
29517 private function extractAliases(array $requires, array $aliases)
29518 {
29519 foreach ($requires as $reqName => $reqVersion) {
29520 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
29521 $aliases[] = array(
29522 'package' => strtolower($reqName),
29523 'version' => $this->versionParser->normalize($match[1], $reqVersion),
29524 'alias' => $match[2],
29525 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
29526 );
29527 }
29528 }
29529
29530 return $aliases;
29531 }
29532
29533 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
29534 {
29535 $stabilities = BasePackage::$stabilities;
29536 $minimumStability = $stabilities[$minimumStability];
29537 foreach ($requires as $reqName => $reqVersion) {
29538 $constraints = array();
29539
29540
29541  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
29542 foreach ($orSplit as $orConstraint) {
29543 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
29544 foreach ($andSplit as $andConstraint) {
29545 $constraints[] = $andConstraint;
29546 }
29547 }
29548
29549
29550  $match = false;
29551 foreach ($constraints as $constraint) {
29552 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
29553 $name = strtolower($reqName);
29554 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
29555
29556 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
29557 continue;
29558 }
29559 $stabilityFlags[$name] = $stability;
29560 $match = true;
29561 }
29562 }
29563
29564 if ($match) {
29565 continue;
29566 }
29567
29568 foreach ($constraints as $constraint) {
29569
29570  
29571  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
29572 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
29573 $name = strtolower($reqName);
29574 $stability = $stabilities[$stabilityName];
29575 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
29576 continue;
29577 }
29578 $stabilityFlags[$name] = $stability;
29579 }
29580 }
29581 }
29582
29583 return $stabilityFlags;
29584 }
29585
29586 private function extractReferences(array $requires, array $references)
29587 {
29588 foreach ($requires as $reqName => $reqVersion) {
29589 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
29590 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) {
29591 $name = strtolower($reqName);
29592 $references[$name] = $match[1];
29593 }
29594 }
29595
29596 return $references;
29597 }
29598 }
29599 <?php
29600
29601
29602
29603
29604
29605
29606
29607
29608
29609
29610
29611 namespace Composer\Package\Loader;
29612
29613 use Composer\Package\BasePackage;
29614 use Composer\Semver\Constraint\Constraint;
29615 use Composer\Package\Version\VersionParser;
29616 use Composer\Repository\PlatformRepository;
29617 use Composer\Spdx\SpdxLicenses;
29618
29619
29620
29621
29622 class ValidatingArrayLoader implements LoaderInterface
29623 {
29624 const CHECK_ALL = 3;
29625 const CHECK_UNBOUND_CONSTRAINTS = 1;
29626 const CHECK_STRICT_CONSTRAINTS = 2;
29627
29628 private $loader;
29629 private $versionParser;
29630 private $errors;
29631 private $warnings;
29632 private $config;
29633 private $strictName;
29634 private $flags;
29635
29636 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
29637 {
29638 $this->loader = $loader;
29639 $this->versionParser = $parser ?: new VersionParser();
29640 $this->strictName = $strictName;
29641 $this->flags = $flags;
29642 }
29643
29644 public function load(array $config, $class = 'Composer\Package\CompletePackage')
29645 {
29646 $this->errors = array();
29647 $this->warnings = array();
29648 $this->config = $config;
29649
29650 if ($err = self::hasPackageNamingError($config['name'])) {
29651 $this->warnings[] = 'Deprecation warning: Your package name '.$err.' Make sure you fix this as Composer 2.0 will error.';
29652 }
29653
29654 if ($this->strictName) {
29655 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
29656 } else {
29657 $this->validateString('name', true);
29658 }
29659
29660 if (!empty($this->config['version'])) {
29661 try {
29662 $this->versionParser->normalize($this->config['version']);
29663 } catch (\Exception $e) {
29664 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
29665 unset($this->config['version']);
29666 }
29667 }
29668
29669 if (!empty($this->config['config']['platform'])) {
29670 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
29671 try {
29672 $this->versionParser->normalize($platform);
29673 } catch (\Exception $e) {
29674 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
29675 }
29676 }
29677 }
29678
29679 $this->validateRegex('type', '[A-Za-z0-9-]+');
29680 $this->validateString('target-dir');
29681 $this->validateArray('extra');
29682
29683 if (isset($this->config['bin'])) {
29684 if (is_string($this->config['bin'])) {
29685 $this->validateString('bin');
29686 } else {
29687 $this->validateFlatArray('bin');
29688 }
29689 }
29690
29691 $this->validateArray('scripts'); 
29692  $this->validateString('description');
29693 $this->validateUrl('homepage');
29694 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
29695
29696 $releaseDate = null;
29697 $this->validateString('time');
29698 if (!empty($this->config['time'])) {
29699 try {
29700 $releaseDate = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
29701 } catch (\Exception $e) {
29702 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
29703 unset($this->config['time']);
29704 }
29705 }
29706
29707
29708  if (isset($this->config['license']) && (!$releaseDate || $releaseDate->getTimestamp() >= strtotime('-8days'))) {
29709 if (is_array($this->config['license']) || is_string($this->config['license'])) {
29710 $licenses = (array) $this->config['license'];
29711
29712
29713  foreach ($licenses as $key => $license) {
29714 if ('proprietary' === $license) {
29715 unset($licenses[$key]);
29716 }
29717 }
29718
29719 $licenseValidator = new SpdxLicenses();
29720 if (count($licenses) === 1 && !$licenseValidator->validate($licenses) && $licenseValidator->validate(trim($licenses[0]))) {
29721 $this->warnings[] = sprintf(
29722 'License %s must not contain extra spaces, make sure to trim it.',
29723 json_encode($this->config['license'])
29724 );
29725 } elseif (array() !== $licenses && !$licenseValidator->validate($licenses)) {
29726 $this->warnings[] = sprintf(
29727 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.' . PHP_EOL .
29728 'If the software is closed-source, you may use "proprietary" as license.',
29729 json_encode($this->config['license'])
29730 );
29731 }
29732 }
29733 }
29734
29735 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
29736 foreach ($this->config['authors'] as $key => $author) {
29737 if (!is_array($author)) {
29738 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
29739 unset($this->config['authors'][$key]);
29740 continue;
29741 }
29742 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
29743 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
29744 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
29745 unset($this->config['authors'][$key][$authorData]);
29746 }
29747 }
29748 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
29749 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
29750 unset($this->config['authors'][$key]['homepage']);
29751 }
29752 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
29753 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
29754 unset($this->config['authors'][$key]['email']);
29755 }
29756 if (empty($this->config['authors'][$key])) {
29757 unset($this->config['authors'][$key]);
29758 }
29759 }
29760 if (empty($this->config['authors'])) {
29761 unset($this->config['authors']);
29762 }
29763 }
29764
29765 if ($this->validateArray('support') && !empty($this->config['support'])) {
29766 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss', 'chat') as $key) {
29767 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
29768 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
29769 unset($this->config['support'][$key]);
29770 }
29771 }
29772
29773 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
29774 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
29775 unset($this->config['support']['email']);
29776 }
29777
29778 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
29779 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
29780 unset($this->config['support']['irc']);
29781 }
29782
29783 foreach (array('issues', 'forum', 'wiki', 'source', 'docs', 'chat') as $key) {
29784 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
29785 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
29786 unset($this->config['support'][$key]);
29787 }
29788 }
29789 if (empty($this->config['support'])) {
29790 unset($this->config['support']);
29791 }
29792 }
29793
29794 if ($this->validateArray('funding') && !empty($this->config['funding'])) {
29795 foreach ($this->config['funding'] as $key => $fundingOption) {
29796 if (!is_array($fundingOption)) {
29797 $this->errors[] = 'funding.'.$key.' : should be an array, '.gettype($fundingOption).' given';
29798 unset($this->config['funding'][$key]);
29799 continue;
29800 }
29801 foreach (array('type', 'url') as $fundingData) {
29802 if (isset($fundingOption[$fundingData]) && !is_string($fundingOption[$fundingData])) {
29803 $this->errors[] = 'funding.'.$key.'.'.$fundingData.' : invalid value, must be a string';
29804 unset($this->config['funding'][$key][$fundingData]);
29805 }
29806 }
29807 if (isset($fundingOption['url']) && !$this->filterUrl($fundingOption['url'])) {
29808 $this->warnings[] = 'funding.'.$key.'.url : invalid value ('.$fundingOption['url'].'), must be an http/https URL';
29809 unset($this->config['funding'][$key]['url']);
29810 }
29811 if (empty($this->config['funding'][$key])) {
29812 unset($this->config['funding'][$key]);
29813 }
29814 }
29815 if (empty($this->config['funding'])) {
29816 unset($this->config['funding']);
29817 }
29818 }
29819
29820 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
29821 $stableConstraint = new Constraint('=', '1.0.0');
29822
29823 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
29824 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
29825 foreach ($this->config[$linkType] as $package => $constraint) {
29826 if ($err = self::hasPackageNamingError($package, true)) {
29827 $this->warnings[] = 'Deprecation warning: '.$linkType.'.'.$err.' Make sure you fix this as Composer 2.0 will error.';
29828 } elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
29829 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
29830 }
29831 if (!is_string($constraint)) {
29832 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
29833 unset($this->config[$linkType][$package]);
29834 } elseif ('self.version' !== $constraint) {
29835 try {
29836 $linkConstraint = $this->versionParser->parseConstraints($constraint);
29837 } catch (\Exception $e) {
29838 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
29839 unset($this->config[$linkType][$package]);
29840 continue;
29841 }
29842
29843
29844  if (
29845 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
29846 && 'require' === $linkType
29847 && $linkConstraint->matches($unboundConstraint)
29848 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
29849 ) {
29850 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
29851 } elseif (
29852
29853  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
29854 && 'require' === $linkType
29855 && substr($linkConstraint, 0, 1) === '='
29856 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
29857 ) {
29858 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
29859 }
29860 }
29861 }
29862 }
29863 }
29864
29865 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
29866 foreach ($this->config['suggest'] as $package => $description) {
29867 if (!is_string($description)) {
29868 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
29869 unset($this->config['suggest'][$package]);
29870 }
29871 }
29872 }
29873
29874 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
29875 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
29876 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
29877 unset($this->config['minimum-stability']);
29878 }
29879 }
29880
29881 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
29882 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
29883 foreach ($this->config['autoload'] as $type => $typeConfig) {
29884 if (!in_array($type, $types)) {
29885 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
29886 unset($this->config['autoload'][$type]);
29887 }
29888 if ($type === 'psr-4') {
29889 foreach ($typeConfig as $namespace => $dirs) {
29890 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
29891 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
29892 }
29893 }
29894 }
29895 }
29896 }
29897
29898 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
29899 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
29900
29901  
29902  unset($this->config['autoload']['psr-4']);
29903 }
29904
29905
29906  
29907
29908
29909  
29910
29911 $this->validateFlatArray('include-path');
29912 $this->validateArray('transport-options');
29913
29914
29915  if (isset($this->config['extra']['branch-alias'])) {
29916 if (!is_array($this->config['extra']['branch-alias'])) {
29917 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
29918 } else {
29919 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
29920
29921  if ('-dev' !== substr($targetBranch, -4)) {
29922 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
29923 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29924
29925 continue;
29926 }
29927
29928
29929  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
29930 if ('-dev' !== substr($validatedTargetBranch, -4)) {
29931 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
29932 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29933
29934 continue;
29935 }
29936
29937
29938  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
29939 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
29940 && (stripos($targetPrefix, $sourcePrefix) !== 0)
29941 ) {
29942 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
29943 unset($this->config['extra']['branch-alias'][$sourceBranch]);
29944 }
29945 }
29946 }
29947 }
29948
29949 if ($this->errors) {
29950 throw new InvalidPackageException($this->errors, $this->warnings, $config);
29951 }
29952
29953 $package = $this->loader->load($this->config, $class);
29954 $this->config = null;
29955
29956 return $package;
29957 }
29958
29959 public function getWarnings()
29960 {
29961 return $this->warnings;
29962 }
29963
29964 public function getErrors()
29965 {
29966 return $this->errors;
29967 }
29968
29969 public static function hasPackageNamingError($name, $isLink = false)
29970 {
29971 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
29972 return;
29973 }
29974
29975 if (!preg_match('{^[a-z0-9](?:[_.-]?[a-z0-9]+)*/[a-z0-9](?:(?:[_.]?|-{0,2})[a-z0-9]+)*$}iD', $name)) {
29976 return $name.' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".';
29977 }
29978
29979 $reservedNames = array('nul', 'con', 'prn', 'aux', 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9', 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9');
29980 $bits = explode('/', strtolower($name));
29981 if (in_array($bits[0], $reservedNames, true) || in_array($bits[1], $reservedNames, true)) {
29982 return $name.' is reserved, package and vendor names can not match any of: '.implode(', ', $reservedNames).'.';
29983 }
29984
29985 if (preg_match('{\.json$}', $name)) {
29986 return $name.' is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.';
29987 }
29988
29989 if (preg_match('{[A-Z]}', $name)) {
29990 if ($isLink) {
29991 return $name.' is invalid, it should not contain uppercase characters. Please use '.strtolower($name).' instead.';
29992 }
29993
29994 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
29995 $suggestName = strtolower($suggestName);
29996
29997 return $name.' is invalid, it should not contain uppercase characters. We suggest using '.$suggestName.' instead.';
29998 }
29999 }
30000
30001 private function validateRegex($property, $regex, $mandatory = false)
30002 {
30003 if (!$this->validateString($property, $mandatory)) {
30004 return false;
30005 }
30006
30007 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
30008 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
30009 if ($mandatory) {
30010 $this->errors[] = $message;
30011 } else {
30012 $this->warnings[] = $message;
30013 }
30014 unset($this->config[$property]);
30015
30016 return false;
30017 }
30018
30019 return true;
30020 }
30021
30022 private function validateString($property, $mandatory = false)
30023 {
30024 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
30025 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
30026 unset($this->config[$property]);
30027
30028 return false;
30029 }
30030
30031 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
30032 if ($mandatory) {
30033 $this->errors[] = $property.' : must be present';
30034 }
30035 unset($this->config[$property]);
30036
30037 return false;
30038 }
30039
30040 return true;
30041 }
30042
30043 private function validateArray($property, $mandatory = false)
30044 {
30045 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
30046 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
30047 unset($this->config[$property]);
30048
30049 return false;
30050 }
30051
30052 if (!isset($this->config[$property]) || !count($this->config[$property])) {
30053 if ($mandatory) {
30054 $this->errors[] = $property.' : must be present and contain at least one element';
30055 }
30056 unset($this->config[$property]);
30057
30058 return false;
30059 }
30060
30061 return true;
30062 }
30063
30064 private function validateFlatArray($property, $regex = null, $mandatory = false)
30065 {
30066 if (!$this->validateArray($property, $mandatory)) {
30067 return false;
30068 }
30069
30070 $pass = true;
30071 foreach ($this->config[$property] as $key => $value) {
30072 if (!is_string($value) && !is_numeric($value)) {
30073 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
30074 unset($this->config[$property][$key]);
30075 $pass = false;
30076
30077 continue;
30078 }
30079
30080 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
30081 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
30082 unset($this->config[$property][$key]);
30083 $pass = false;
30084 }
30085 }
30086
30087 return $pass;
30088 }
30089
30090 private function validateUrl($property, $mandatory = false)
30091 {
30092 if (!$this->validateString($property, $mandatory)) {
30093 return false;
30094 }
30095
30096 if (!$this->filterUrl($this->config[$property])) {
30097 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
30098 unset($this->config[$property]);
30099
30100 return false;
30101 }
30102
30103 return true;
30104 }
30105
30106 private function filterUrl($value, array $schemes = array('http', 'https'))
30107 {
30108 if ($value === '') {
30109 return true;
30110 }
30111
30112 $bits = parse_url($value);
30113 if (empty($bits['scheme']) || empty($bits['host'])) {
30114 return false;
30115 }
30116
30117 if (!in_array($bits['scheme'], $schemes, true)) {
30118 return false;
30119 }
30120
30121 return true;
30122 }
30123 }
30124 <?php
30125
30126
30127
30128
30129
30130
30131
30132
30133
30134
30135
30136 namespace Composer\Package;
30137
30138 use Composer\Json\JsonFile;
30139 use Composer\Installer\InstallationManager;
30140 use Composer\Repository\RepositoryManager;
30141 use Composer\Util\ProcessExecutor;
30142 use Composer\Repository\ArrayRepository;
30143 use Composer\Package\Dumper\ArrayDumper;
30144 use Composer\Package\Loader\ArrayLoader;
30145 use Composer\Plugin\PluginInterface;
30146 use Composer\Util\Git as GitUtil;
30147 use Composer\IO\IOInterface;
30148 use Seld\JsonLint\ParsingException;
30149
30150
30151
30152
30153
30154
30155
30156 class Locker
30157 {
30158 private $lockFile;
30159 private $repositoryManager;
30160 private $installationManager;
30161 private $hash;
30162 private $contentHash;
30163 private $loader;
30164 private $dumper;
30165 private $process;
30166 private $lockDataCache;
30167
30168
30169
30170
30171
30172
30173
30174
30175
30176
30177 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
30178 {
30179 $this->lockFile = $lockFile;
30180 $this->repositoryManager = $repositoryManager;
30181 $this->installationManager = $installationManager;
30182 $this->hash = md5($composerFileContents);
30183 $this->contentHash = self::getContentHash($composerFileContents);
30184 $this->loader = new ArrayLoader(null, true);
30185 $this->dumper = new ArrayDumper();
30186 $this->process = new ProcessExecutor($io);
30187 }
30188
30189
30190
30191
30192
30193
30194
30195
30196 public static function getContentHash($composerFileContents)
30197 {
30198 $content = json_decode($composerFileContents, true);
30199
30200 $relevantKeys = array(
30201 'name',
30202 'version',
30203 'require',
30204 'require-dev',
30205 'conflict',
30206 'replace',
30207 'provide',
30208 'minimum-stability',
30209 'prefer-stable',
30210 'repositories',
30211 'extra',
30212 );
30213
30214 $relevantContent = array();
30215
30216 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
30217 $relevantContent[$key] = $content[$key];
30218 }
30219 if (isset($content['config']['platform'])) {
30220 $relevantContent['config']['platform'] = $content['config']['platform'];
30221 }
30222
30223 ksort($relevantContent);
30224
30225 return md5(json_encode($relevantContent));
30226 }
30227
30228
30229
30230
30231
30232
30233 public function isLocked()
30234 {
30235 if (!$this->lockFile->exists()) {
30236 return false;
30237 }
30238
30239 $data = $this->getLockData();
30240
30241 return isset($data['packages']);
30242 }
30243
30244
30245
30246
30247
30248
30249 public function isFresh()
30250 {
30251 $lock = $this->lockFile->read();
30252
30253 if (!empty($lock['content-hash'])) {
30254
30255  return $this->contentHash === $lock['content-hash'];
30256 }
30257
30258
30259  if (!empty($lock['hash'])) {
30260 return $this->hash === $lock['hash'];
30261 }
30262
30263
30264  return false;
30265 }
30266
30267
30268
30269
30270
30271
30272
30273
30274 public function getLockedRepository($withDevReqs = false)
30275 {
30276 $lockData = $this->getLockData();
30277 $packages = new ArrayRepository();
30278
30279 $lockedPackages = $lockData['packages'];
30280 if ($withDevReqs) {
30281 if (isset($lockData['packages-dev'])) {
30282 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
30283 } else {
30284 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.');
30285 }
30286 }
30287
30288 if (empty($lockedPackages)) {
30289 return $packages;
30290 }
30291
30292 if (isset($lockedPackages[0]['name'])) {
30293 foreach ($lockedPackages as $info) {
30294 $packages->addPackage($this->loader->load($info));
30295 }
30296
30297 return $packages;
30298 }
30299
30300 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.');
30301 }
30302
30303
30304
30305
30306
30307
30308
30309 public function getPlatformRequirements($withDevReqs = false)
30310 {
30311 $lockData = $this->getLockData();
30312 $requirements = array();
30313
30314 if (!empty($lockData['platform'])) {
30315 $requirements = $this->loader->parseLinks(
30316 '__ROOT__',
30317 '1.0.0',
30318 'requires',
30319 isset($lockData['platform']) ? $lockData['platform'] : array()
30320 );
30321 }
30322
30323 if ($withDevReqs && !empty($lockData['platform-dev'])) {
30324 $devRequirements = $this->loader->parseLinks(
30325 '__ROOT__',
30326 '1.0.0',
30327 'requires',
30328 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
30329 );
30330
30331 $requirements = array_merge($requirements, $devRequirements);
30332 }
30333
30334 return $requirements;
30335 }
30336
30337 public function getMinimumStability()
30338 {
30339 $lockData = $this->getLockData();
30340
30341 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
30342 }
30343
30344 public function getStabilityFlags()
30345 {
30346 $lockData = $this->getLockData();
30347
30348 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
30349 }
30350
30351 public function getPreferStable()
30352 {
30353 $lockData = $this->getLockData();
30354
30355
30356  
30357  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
30358 }
30359
30360 public function getPreferLowest()
30361 {
30362 $lockData = $this->getLockData();
30363
30364
30365  
30366  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
30367 }
30368
30369 public function getPlatformOverrides()
30370 {
30371 $lockData = $this->getLockData();
30372
30373 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
30374 }
30375
30376 public function getAliases()
30377 {
30378 $lockData = $this->getLockData();
30379
30380 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
30381 }
30382
30383 public function getLockData()
30384 {
30385 if (null !== $this->lockDataCache) {
30386 return $this->lockDataCache;
30387 }
30388
30389 if (!$this->lockFile->exists()) {
30390 throw new \LogicException('No lockfile found. Unable to read locked packages');
30391 }
30392
30393 return $this->lockDataCache = $this->lockFile->read();
30394 }
30395
30396
30397
30398
30399
30400
30401
30402
30403
30404
30405
30406
30407
30408
30409
30410
30411
30412 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
30413 {
30414 $lock = array(
30415 '_readme' => array('This file locks the dependencies of your project to a known state',
30416 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies',
30417 'This file is @gener'.'ated automatically', ),
30418 'content-hash' => $this->contentHash,
30419 'packages' => null,
30420 'packages-dev' => null,
30421 'aliases' => array(),
30422 'minimum-stability' => $minimumStability,
30423 'stability-flags' => $stabilityFlags,
30424 'prefer-stable' => $preferStable,
30425 'prefer-lowest' => $preferLowest,
30426 );
30427
30428 foreach ($aliases as $package => $versions) {
30429 foreach ($versions as $version => $alias) {
30430 $lock['aliases'][] = array(
30431 'alias' => $alias['alias'],
30432 'alias_normalized' => $alias['alias_normalized'],
30433 'version' => $version,
30434 'package' => $package,
30435 );
30436 }
30437 }
30438
30439 $lock['packages'] = $this->lockPackages($packages);
30440 if (null !== $devPackages) {
30441 $lock['packages-dev'] = $this->lockPackages($devPackages);
30442 }
30443
30444 $lock['platform'] = $platformReqs;
30445 $lock['platform-dev'] = $platformDevReqs;
30446 if ($platformOverrides) {
30447 $lock['platform-overrides'] = $platformOverrides;
30448 }
30449 $lock['plugin-api-version'] = PluginInterface::PLUGIN_API_VERSION;
30450
30451 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
30452 if ($this->lockFile->exists()) {
30453 unlink($this->lockFile->getPath());
30454 }
30455
30456 return false;
30457 }
30458
30459 try {
30460 $isLocked = $this->isLocked();
30461 } catch (ParsingException $e) {
30462 $isLocked = false;
30463 }
30464 if (!$isLocked || $lock !== $this->getLockData()) {
30465 $this->lockFile->write($lock);
30466 $this->lockDataCache = null;
30467
30468 return true;
30469 }
30470
30471 return false;
30472 }
30473
30474 private function lockPackages(array $packages)
30475 {
30476 $locked = array();
30477
30478 foreach ($packages as $package) {
30479 if ($package instanceof AliasPackage) {
30480 continue;
30481 }
30482
30483 $name = $package->getPrettyName();
30484 $version = $package->getPrettyVersion();
30485
30486 if (!$name || !$version) {
30487 throw new \LogicException(sprintf(
30488 'Package "%s" has no version or name and can not be locked',
30489 $package
30490 ));
30491 }
30492
30493 $spec = $this->dumper->dump($package);
30494 unset($spec['version_normalized']);
30495
30496
30497  $time = isset($spec['time']) ? $spec['time'] : null;
30498 unset($spec['time']);
30499 if ($package->isDev() && $package->getInstallationSource() === 'source') {
30500
30501  $time = $this->getPackageTime($package) ?: $time;
30502 }
30503 if (null !== $time) {
30504 $spec['time'] = $time;
30505 }
30506
30507 unset($spec['installation-source']);
30508
30509 $locked[] = $spec;
30510 }
30511
30512 usort($locked, function ($a, $b) {
30513 $comparison = strcmp($a['name'], $b['name']);
30514
30515 if (0 !== $comparison) {
30516 return $comparison;
30517 }
30518
30519
30520  return strcmp($a['version'], $b['version']);
30521 });
30522
30523 return $locked;
30524 }
30525
30526
30527
30528
30529
30530
30531
30532 private function getPackageTime(PackageInterface $package)
30533 {
30534 if (!function_exists('proc_open')) {
30535 return null;
30536 }
30537
30538 $path = realpath($this->installationManager->getInstallPath($package));
30539 $sourceType = $package->getSourceType();
30540 $datetime = null;
30541
30542 if ($path && in_array($sourceType, array('git', 'hg'))) {
30543 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
30544 switch ($sourceType) {
30545 case 'git':
30546 GitUtil::cleanEnv();
30547
30548 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
30549 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
30550 }
30551 break;
30552
30553 case 'hg':
30554 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
30555 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
30556 }
30557 break;
30558 }
30559 }
30560
30561 return $datetime ? $datetime->format(DATE_RFC3339) : null;
30562 }
30563 }
30564 <?php
30565
30566
30567
30568
30569
30570
30571
30572
30573
30574
30575
30576 namespace Composer\Package;
30577
30578 use Composer\Package\Version\VersionParser;
30579 use Composer\Util\ComposerMirror;
30580
30581
30582
30583
30584
30585
30586 class Package extends BasePackage
30587 {
30588 protected $type;
30589 protected $targetDir;
30590 protected $installationSource;
30591 protected $sourceType;
30592 protected $sourceUrl;
30593 protected $sourceReference;
30594 protected $sourceMirrors;
30595 protected $distType;
30596 protected $distUrl;
30597 protected $distReference;
30598 protected $distSha1Checksum;
30599 protected $distMirrors;
30600 protected $version;
30601 protected $prettyVersion;
30602 protected $releaseDate;
30603 protected $extra = array();
30604 protected $binaries = array();
30605 protected $dev;
30606 protected $stability;
30607 protected $notificationUrl;
30608
30609
30610 protected $requires = array();
30611
30612 protected $conflicts = array();
30613
30614 protected $provides = array();
30615
30616 protected $replaces = array();
30617
30618 protected $devRequires = array();
30619 protected $suggests = array();
30620 protected $autoload = array();
30621 protected $devAutoload = array();
30622 protected $includePaths = array();
30623 protected $archiveExcludes = array();
30624
30625
30626
30627
30628
30629
30630
30631
30632 public function __construct($name, $version, $prettyVersion)
30633 {
30634 parent::__construct($name);
30635
30636 $this->version = $version;
30637 $this->prettyVersion = $prettyVersion;
30638
30639 $this->stability = VersionParser::parseStability($version);
30640 $this->dev = $this->stability === 'dev';
30641 }
30642
30643
30644
30645
30646 public function isDev()
30647 {
30648 return $this->dev;
30649 }
30650
30651
30652
30653
30654 public function setType($type)
30655 {
30656 $this->type = $type;
30657 }
30658
30659
30660
30661
30662 public function getType()
30663 {
30664 return $this->type ?: 'library';
30665 }
30666
30667
30668
30669
30670 public function getStability()
30671 {
30672 return $this->stability;
30673 }
30674
30675
30676
30677
30678 public function setTargetDir($targetDir)
30679 {
30680 $this->targetDir = $targetDir;
30681 }
30682
30683
30684
30685
30686 public function getTargetDir()
30687 {
30688 if (null === $this->targetDir) {
30689 return;
30690 }
30691
30692 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
30693 }
30694
30695
30696
30697
30698 public function setExtra(array $extra)
30699 {
30700 $this->extra = $extra;
30701 }
30702
30703
30704
30705
30706 public function getExtra()
30707 {
30708 return $this->extra;
30709 }
30710
30711
30712
30713
30714 public function setBinaries(array $binaries)
30715 {
30716 $this->binaries = $binaries;
30717 }
30718
30719
30720
30721
30722 public function getBinaries()
30723 {
30724 return $this->binaries;
30725 }
30726
30727
30728
30729
30730 public function setInstallationSource($type)
30731 {
30732 $this->installationSource = $type;
30733 }
30734
30735
30736
30737
30738 public function getInstallationSource()
30739 {
30740 return $this->installationSource;
30741 }
30742
30743
30744
30745
30746 public function setSourceType($type)
30747 {
30748 $this->sourceType = $type;
30749 }
30750
30751
30752
30753
30754 public function getSourceType()
30755 {
30756 return $this->sourceType;
30757 }
30758
30759
30760
30761
30762 public function setSourceUrl($url)
30763 {
30764 $this->sourceUrl = $url;
30765 }
30766
30767
30768
30769
30770 public function getSourceUrl()
30771 {
30772 return $this->sourceUrl;
30773 }
30774
30775
30776
30777
30778 public function setSourceReference($reference)
30779 {
30780 $this->sourceReference = $reference;
30781 }
30782
30783
30784
30785
30786 public function getSourceReference()
30787 {
30788 return $this->sourceReference;
30789 }
30790
30791
30792
30793
30794 public function setSourceMirrors($mirrors)
30795 {
30796 $this->sourceMirrors = $mirrors;
30797 }
30798
30799
30800
30801
30802 public function getSourceMirrors()
30803 {
30804 return $this->sourceMirrors;
30805 }
30806
30807
30808
30809
30810 public function getSourceUrls()
30811 {
30812 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
30813 }
30814
30815
30816
30817
30818 public function setDistType($type)
30819 {
30820 $this->distType = $type;
30821 }
30822
30823
30824
30825
30826 public function getDistType()
30827 {
30828 return $this->distType;
30829 }
30830
30831
30832
30833
30834 public function setDistUrl($url)
30835 {
30836 $this->distUrl = $url;
30837 }
30838
30839
30840
30841
30842 public function getDistUrl()
30843 {
30844 return $this->distUrl;
30845 }
30846
30847
30848
30849
30850 public function setDistReference($reference)
30851 {
30852 $this->distReference = $reference;
30853 }
30854
30855
30856
30857
30858 public function getDistReference()
30859 {
30860 return $this->distReference;
30861 }
30862
30863
30864
30865
30866 public function setDistSha1Checksum($sha1checksum)
30867 {
30868 $this->distSha1Checksum = $sha1checksum;
30869 }
30870
30871
30872
30873
30874 public function getDistSha1Checksum()
30875 {
30876 return $this->distSha1Checksum;
30877 }
30878
30879
30880
30881
30882 public function setDistMirrors($mirrors)
30883 {
30884 $this->distMirrors = $mirrors;
30885 }
30886
30887
30888
30889
30890 public function getDistMirrors()
30891 {
30892 return $this->distMirrors;
30893 }
30894
30895
30896
30897
30898 public function getDistUrls()
30899 {
30900 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
30901 }
30902
30903
30904
30905
30906 public function getVersion()
30907 {
30908 return $this->version;
30909 }
30910
30911
30912
30913
30914 public function getPrettyVersion()
30915 {
30916 return $this->prettyVersion;
30917 }
30918
30919
30920
30921
30922
30923
30924 public function setReleaseDate(\DateTime $releaseDate)
30925 {
30926 $this->releaseDate = $releaseDate;
30927 }
30928
30929
30930
30931
30932 public function getReleaseDate()
30933 {
30934 return $this->releaseDate;
30935 }
30936
30937
30938
30939
30940
30941
30942 public function setRequires(array $requires)
30943 {
30944 $this->requires = $requires;
30945 }
30946
30947
30948
30949
30950 public function getRequires()
30951 {
30952 return $this->requires;
30953 }
30954
30955
30956
30957
30958
30959
30960 public function setConflicts(array $conflicts)
30961 {
30962 $this->conflicts = $conflicts;
30963 }
30964
30965
30966
30967
30968 public function getConflicts()
30969 {
30970 return $this->conflicts;
30971 }
30972
30973
30974
30975
30976
30977
30978 public function setProvides(array $provides)
30979 {
30980 $this->provides = $provides;
30981 }
30982
30983
30984
30985
30986 public function getProvides()
30987 {
30988 return $this->provides;
30989 }
30990
30991
30992
30993
30994
30995
30996 public function setReplaces(array $replaces)
30997 {
30998 $this->replaces = $replaces;
30999 }
31000
31001
31002
31003
31004 public function getReplaces()
31005 {
31006 return $this->replaces;
31007 }
31008
31009
31010
31011
31012
31013
31014 public function setDevRequires(array $devRequires)
31015 {
31016 $this->devRequires = $devRequires;
31017 }
31018
31019
31020
31021
31022 public function getDevRequires()
31023 {
31024 return $this->devRequires;
31025 }
31026
31027
31028
31029
31030
31031
31032 public function setSuggests(array $suggests)
31033 {
31034 $this->suggests = $suggests;
31035 }
31036
31037
31038
31039
31040 public function getSuggests()
31041 {
31042 return $this->suggests;
31043 }
31044
31045
31046
31047
31048
31049
31050 public function setAutoload(array $autoload)
31051 {
31052 $this->autoload = $autoload;
31053 }
31054
31055
31056
31057
31058 public function getAutoload()
31059 {
31060 return $this->autoload;
31061 }
31062
31063
31064
31065
31066
31067
31068 public function setDevAutoload(array $devAutoload)
31069 {
31070 $this->devAutoload = $devAutoload;
31071 }
31072
31073
31074
31075
31076 public function getDevAutoload()
31077 {
31078 return $this->devAutoload;
31079 }
31080
31081
31082
31083
31084
31085
31086 public function setIncludePaths(array $includePaths)
31087 {
31088 $this->includePaths = $includePaths;
31089 }
31090
31091
31092
31093
31094 public function getIncludePaths()
31095 {
31096 return $this->includePaths;
31097 }
31098
31099
31100
31101
31102
31103
31104 public function setNotificationUrl($notificationUrl)
31105 {
31106 $this->notificationUrl = $notificationUrl;
31107 }
31108
31109
31110
31111
31112 public function getNotificationUrl()
31113 {
31114 return $this->notificationUrl;
31115 }
31116
31117
31118
31119
31120
31121
31122 public function setArchiveExcludes(array $excludes)
31123 {
31124 $this->archiveExcludes = $excludes;
31125 }
31126
31127
31128
31129
31130 public function getArchiveExcludes()
31131 {
31132 return $this->archiveExcludes;
31133 }
31134
31135
31136
31137
31138
31139
31140
31141
31142 public function replaceVersion($version, $prettyVersion)
31143 {
31144 $this->version = $version;
31145 $this->prettyVersion = $prettyVersion;
31146
31147 $this->stability = VersionParser::parseStability($version);
31148 $this->dev = $this->stability === 'dev';
31149 }
31150
31151 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
31152 {
31153 if (!$url) {
31154 return array();
31155 }
31156 $urls = array($url);
31157 if ($mirrors) {
31158 foreach ($mirrors as $mirror) {
31159 if ($urlType === 'dist') {
31160 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
31161 } elseif ($urlType === 'source' && $type === 'git') {
31162 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
31163 } elseif ($urlType === 'source' && $type === 'hg') {
31164 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
31165 }
31166 if (!in_array($mirrorUrl, $urls)) {
31167 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
31168 $func($urls, $mirrorUrl);
31169 }
31170 }
31171 }
31172
31173 return $urls;
31174 }
31175 }
31176 <?php
31177
31178
31179
31180
31181
31182
31183
31184
31185
31186
31187
31188 namespace Composer\Package;
31189
31190 use Composer\Repository\RepositoryInterface;
31191
31192
31193
31194
31195
31196
31197 interface PackageInterface
31198 {
31199
31200
31201
31202
31203
31204 public function getName();
31205
31206
31207
31208
31209
31210
31211 public function getPrettyName();
31212
31213
31214
31215
31216
31217
31218
31219
31220
31221 public function getNames();
31222
31223
31224
31225
31226
31227
31228 public function setId($id);
31229
31230
31231
31232
31233
31234
31235 public function getId();
31236
31237
31238
31239
31240
31241
31242 public function isDev();
31243
31244
31245
31246
31247
31248
31249 public function getType();
31250
31251
31252
31253
31254
31255
31256 public function getTargetDir();
31257
31258
31259
31260
31261
31262
31263 public function getExtra();
31264
31265
31266
31267
31268
31269
31270 public function setInstallationSource($type);
31271
31272
31273
31274
31275
31276
31277 public function getInstallationSource();
31278
31279
31280
31281
31282
31283
31284 public function getSourceType();
31285
31286
31287
31288
31289
31290
31291 public function getSourceUrl();
31292
31293
31294
31295
31296
31297
31298 public function getSourceUrls();
31299
31300
31301
31302
31303
31304
31305 public function getSourceReference();
31306
31307
31308
31309
31310
31311
31312 public function getSourceMirrors();
31313
31314
31315
31316
31317
31318
31319 public function getDistType();
31320
31321
31322
31323
31324
31325
31326 public function getDistUrl();
31327
31328
31329
31330
31331
31332
31333 public function getDistUrls();
31334
31335
31336
31337
31338
31339
31340 public function getDistReference();
31341
31342
31343
31344
31345
31346
31347 public function getDistSha1Checksum();
31348
31349
31350
31351
31352
31353
31354 public function getDistMirrors();
31355
31356
31357
31358
31359
31360
31361 public function getVersion();
31362
31363
31364
31365
31366
31367
31368 public function getPrettyVersion();
31369
31370
31371
31372
31373
31374
31375
31376
31377
31378 public function getFullPrettyVersion($truncate = true);
31379
31380
31381
31382
31383
31384
31385 public function getReleaseDate();
31386
31387
31388
31389
31390
31391
31392 public function getStability();
31393
31394
31395
31396
31397
31398
31399
31400 public function getRequires();
31401
31402
31403
31404
31405
31406
31407
31408 public function getConflicts();
31409
31410
31411
31412
31413
31414
31415
31416 public function getProvides();
31417
31418
31419
31420
31421
31422
31423
31424 public function getReplaces();
31425
31426
31427
31428
31429
31430
31431
31432 public function getDevRequires();
31433
31434
31435
31436
31437
31438
31439
31440 public function getSuggests();
31441
31442
31443
31444
31445
31446
31447
31448
31449
31450
31451
31452 public function getAutoload();
31453
31454
31455
31456
31457
31458
31459
31460
31461
31462
31463
31464 public function getDevAutoload();
31465
31466
31467
31468
31469
31470
31471
31472 public function getIncludePaths();
31473
31474
31475
31476
31477
31478
31479 public function setRepository(RepositoryInterface $repository);
31480
31481
31482
31483
31484
31485
31486 public function getRepository();
31487
31488
31489
31490
31491
31492
31493 public function getBinaries();
31494
31495
31496
31497
31498
31499
31500 public function getUniqueName();
31501
31502
31503
31504
31505
31506
31507 public function getNotificationUrl();
31508
31509
31510
31511
31512
31513
31514 public function __toString();
31515
31516
31517
31518
31519
31520
31521 public function getPrettyString();
31522
31523
31524
31525
31526
31527
31528 public function getArchiveExcludes();
31529
31530
31531
31532
31533
31534
31535 public function getTransportOptions();
31536
31537
31538
31539
31540
31541
31542 public function setSourceReference($reference);
31543
31544
31545
31546
31547
31548
31549 public function setDistUrl($url);
31550
31551
31552
31553
31554
31555
31556 public function setDistType($type);
31557
31558
31559
31560
31561
31562
31563 public function setDistReference($reference);
31564 }
31565 <?php
31566
31567
31568
31569
31570
31571
31572
31573
31574
31575
31576
31577 namespace Composer\Package;
31578
31579
31580
31581
31582 class RootAliasPackage extends AliasPackage implements RootPackageInterface
31583 {
31584 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
31585 {
31586 parent::__construct($aliasOf, $version, $prettyVersion);
31587 }
31588
31589
31590
31591
31592 public function getAliases()
31593 {
31594 return $this->aliasOf->getAliases();
31595 }
31596
31597
31598
31599
31600 public function getMinimumStability()
31601 {
31602 return $this->aliasOf->getMinimumStability();
31603 }
31604
31605
31606
31607
31608 public function getStabilityFlags()
31609 {
31610 return $this->aliasOf->getStabilityFlags();
31611 }
31612
31613
31614
31615
31616 public function getReferences()
31617 {
31618 return $this->aliasOf->getReferences();
31619 }
31620
31621
31622
31623
31624 public function getPreferStable()
31625 {
31626 return $this->aliasOf->getPreferStable();
31627 }
31628
31629
31630
31631
31632 public function getConfig()
31633 {
31634 return $this->aliasOf->getConfig();
31635 }
31636
31637
31638
31639
31640 public function setRequires(array $require)
31641 {
31642 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
31643
31644 $this->aliasOf->setRequires($require);
31645 }
31646
31647
31648
31649
31650 public function setDevRequires(array $devRequire)
31651 {
31652 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
31653
31654 $this->aliasOf->setDevRequires($devRequire);
31655 }
31656
31657
31658
31659
31660 public function setConflicts(array $conflicts)
31661 {
31662 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
31663 $this->aliasOf->setConflicts($conflicts);
31664 }
31665
31666
31667
31668
31669 public function setProvides(array $provides)
31670 {
31671 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
31672 $this->aliasOf->setProvides($provides);
31673 }
31674
31675
31676
31677
31678 public function setReplaces(array $replaces)
31679 {
31680 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
31681 $this->aliasOf->setReplaces($replaces);
31682 }
31683
31684
31685
31686
31687 public function setRepositories($repositories)
31688 {
31689 $this->aliasOf->setRepositories($repositories);
31690 }
31691
31692
31693
31694
31695 public function setAutoload(array $autoload)
31696 {
31697 $this->aliasOf->setAutoload($autoload);
31698 }
31699
31700
31701
31702
31703 public function setDevAutoload(array $devAutoload)
31704 {
31705 $this->aliasOf->setDevAutoload($devAutoload);
31706 }
31707
31708
31709
31710
31711 public function setStabilityFlags(array $stabilityFlags)
31712 {
31713 $this->aliasOf->setStabilityFlags($stabilityFlags);
31714 }
31715
31716
31717
31718
31719 public function setSuggests(array $suggests)
31720 {
31721 $this->aliasOf->setSuggests($suggests);
31722 }
31723
31724
31725
31726
31727 public function setExtra(array $extra)
31728 {
31729 $this->aliasOf->setExtra($extra);
31730 }
31731
31732 public function __clone()
31733 {
31734 parent::__clone();
31735 $this->aliasOf = clone $this->aliasOf;
31736 }
31737 }
31738 <?php
31739
31740
31741
31742
31743
31744
31745
31746
31747
31748
31749
31750 namespace Composer\Package;
31751
31752
31753
31754
31755
31756
31757 class RootPackage extends CompletePackage implements RootPackageInterface
31758 {
31759 protected $minimumStability = 'stable';
31760 protected $preferStable = false;
31761 protected $stabilityFlags = array();
31762 protected $config = array();
31763 protected $references = array();
31764 protected $aliases = array();
31765
31766
31767
31768
31769
31770
31771 public function setMinimumStability($minimumStability)
31772 {
31773 $this->minimumStability = $minimumStability;
31774 }
31775
31776
31777
31778
31779 public function getMinimumStability()
31780 {
31781 return $this->minimumStability;
31782 }
31783
31784
31785
31786
31787
31788
31789 public function setStabilityFlags(array $stabilityFlags)
31790 {
31791 $this->stabilityFlags = $stabilityFlags;
31792 }
31793
31794
31795
31796
31797 public function getStabilityFlags()
31798 {
31799 return $this->stabilityFlags;
31800 }
31801
31802
31803
31804
31805
31806
31807 public function setPreferStable($preferStable)
31808 {
31809 $this->preferStable = $preferStable;
31810 }
31811
31812
31813
31814
31815 public function getPreferStable()
31816 {
31817 return $this->preferStable;
31818 }
31819
31820
31821
31822
31823
31824
31825 public function setConfig(array $config)
31826 {
31827 $this->config = $config;
31828 }
31829
31830
31831
31832
31833 public function getConfig()
31834 {
31835 return $this->config;
31836 }
31837
31838
31839
31840
31841
31842
31843 public function setReferences(array $references)
31844 {
31845 $this->references = $references;
31846 }
31847
31848
31849
31850
31851 public function getReferences()
31852 {
31853 return $this->references;
31854 }
31855
31856
31857
31858
31859
31860
31861 public function setAliases(array $aliases)
31862 {
31863 $this->aliases = $aliases;
31864 }
31865
31866
31867
31868
31869 public function getAliases()
31870 {
31871 return $this->aliases;
31872 }
31873 }
31874 <?php
31875
31876
31877
31878
31879
31880
31881
31882
31883
31884
31885
31886 namespace Composer\Package;
31887
31888
31889
31890
31891
31892
31893 interface RootPackageInterface extends CompletePackageInterface
31894 {
31895
31896
31897
31898
31899
31900 public function getAliases();
31901
31902
31903
31904
31905
31906
31907 public function getMinimumStability();
31908
31909
31910
31911
31912
31913
31914
31915
31916 public function getStabilityFlags();
31917
31918
31919
31920
31921
31922
31923
31924
31925 public function getReferences();
31926
31927
31928
31929
31930
31931
31932 public function getPreferStable();
31933
31934
31935
31936
31937
31938
31939 public function getConfig();
31940
31941
31942
31943
31944
31945
31946 public function setRequires(array $requires);
31947
31948
31949
31950
31951
31952
31953 public function setDevRequires(array $devRequires);
31954
31955
31956
31957
31958
31959
31960 public function setConflicts(array $conflicts);
31961
31962
31963
31964
31965
31966
31967 public function setProvides(array $provides);
31968
31969
31970
31971
31972
31973
31974 public function setReplaces(array $replaces);
31975
31976
31977
31978
31979
31980
31981 public function setRepositories($repositories);
31982
31983
31984
31985
31986
31987
31988 public function setAutoload(array $autoload);
31989
31990
31991
31992
31993
31994
31995 public function setDevAutoload(array $devAutoload);
31996
31997
31998
31999
32000
32001
32002 public function setStabilityFlags(array $stabilityFlags);
32003
32004
32005
32006
32007
32008
32009 public function setSuggests(array $suggests);
32010
32011
32012
32013
32014 public function setExtra(array $extra);
32015 }
32016 <?php
32017
32018
32019
32020
32021
32022
32023
32024
32025
32026
32027
32028 namespace Composer\Package\Version;
32029
32030 use Composer\Config;
32031 use Composer\Repository\Vcs\HgDriver;
32032 use Composer\IO\NullIO;
32033 use Composer\Semver\VersionParser as SemverVersionParser;
32034 use Composer\Util\Git as GitUtil;
32035 use Composer\Util\ProcessExecutor;
32036 use Composer\Util\Svn as SvnUtil;
32037
32038
32039
32040
32041
32042
32043
32044 class VersionGuesser
32045 {
32046
32047
32048
32049 private $config;
32050
32051
32052
32053
32054 private $process;
32055
32056
32057
32058
32059 private $versionParser;
32060
32061
32062
32063
32064
32065
32066 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
32067 {
32068 $this->config = $config;
32069 $this->process = $process;
32070 $this->versionParser = $versionParser;
32071 }
32072
32073
32074
32075
32076
32077
32078
32079 public function guessVersion(array $packageConfig, $path)
32080 {
32081 if (!function_exists('proc_open')) {
32082 return null;
32083 }
32084
32085 $versionData = $this->guessGitVersion($packageConfig, $path);
32086 if (null !== $versionData && null !== $versionData['version']) {
32087 return $this->postprocess($versionData);
32088 }
32089
32090 $versionData = $this->guessHgVersion($packageConfig, $path);
32091 if (null !== $versionData && null !== $versionData['version']) {
32092 return $this->postprocess($versionData);
32093 }
32094
32095 $versionData = $this->guessFossilVersion($packageConfig, $path);
32096 if (null !== $versionData && null !== $versionData['version']) {
32097 return $this->postprocess($versionData);
32098 }
32099
32100 $versionData = $this->guessSvnVersion($packageConfig, $path);
32101 if (null !== $versionData && null !== $versionData['version']) {
32102 return $this->postprocess($versionData);
32103 }
32104
32105 return null;
32106 }
32107
32108 private function postprocess(array $versionData)
32109 {
32110 if (!empty($versionData['feature_version']) && $versionData['feature_version'] === $versionData['version'] && $versionData['feature_pretty_version'] === $versionData['feature_pretty_version']) {
32111 unset($versionData['feature_version'], $versionData['feature_pretty_version']);
32112 }
32113
32114 if ('-dev' === substr($versionData['version'], -4) && preg_match('{\.9{7}}', $versionData['version'])) {
32115 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
32116 }
32117
32118 if (!empty($versionData['feature_version']) && '-dev' === substr($versionData['feature_version'], -4) && preg_match('{\.9{7}}', $versionData['feature_version'])) {
32119 $versionData['feature_pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['feature_version']);
32120 }
32121
32122 return $versionData;
32123 }
32124
32125 private function guessGitVersion(array $packageConfig, $path)
32126 {
32127 GitUtil::cleanEnv();
32128 $commit = null;
32129 $version = null;
32130 $prettyVersion = null;
32131 $featureVersion = null;
32132 $featurePrettyVersion = null;
32133 $isDetached = false;
32134
32135
32136  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
32137 $branches = array();
32138 $isFeatureBranch = false;
32139
32140
32141  foreach ($this->process->splitLines($output) as $branch) {
32142 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
32143 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
32144 $version = 'dev-' . $match[2];
32145 $prettyVersion = $version;
32146 $isFeatureBranch = true;
32147 $isDetached = true;
32148 } else {
32149 $version = $this->versionParser->normalizeBranch($match[1]);
32150 $prettyVersion = 'dev-' . $match[1];
32151 $isFeatureBranch = 0 === strpos($version, 'dev-');
32152 }
32153
32154 if ($match[2]) {
32155 $commit = $match[2];
32156 }
32157 }
32158
32159 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
32160 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
32161 $branches[] = $match[1];
32162 }
32163 }
32164 }
32165
32166 if ($isFeatureBranch) {
32167 $featureVersion = $version;
32168 $featurePrettyVersion = $prettyVersion;
32169
32170  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
32171 $version = $result['version'];
32172 $prettyVersion = $result['pretty_version'];
32173 }
32174 }
32175
32176 if (!$version || $isDetached) {
32177 $result = $this->versionFromGitTags($path);
32178 if ($result) {
32179 $version = $result['version'];
32180 $prettyVersion = $result['pretty_version'];
32181 $featureVersion = null;
32182 $featurePrettyVersion = null;
32183 }
32184 }
32185
32186 if (!$commit) {
32187 $command = 'git log --pretty="%H" -n1 HEAD';
32188 if (0 === $this->process->execute($command, $output, $path)) {
32189 $commit = trim($output) ?: null;
32190 }
32191 }
32192
32193 if ($featureVersion) {
32194 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion, 'feature_version' => $featureVersion, 'feature_pretty_version' => $featurePrettyVersion);
32195 }
32196
32197 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
32198 }
32199
32200 private function versionFromGitTags($path)
32201 {
32202
32203  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
32204 try {
32205 $version = $this->versionParser->normalize(trim($output));
32206
32207 return array('version' => $version, 'pretty_version' => trim($output));
32208 } catch (\Exception $e) {
32209 }
32210 }
32211
32212 return null;
32213 }
32214
32215 private function guessHgVersion(array $packageConfig, $path)
32216 {
32217
32218  if (0 === $this->process->execute('hg branch', $output, $path)) {
32219 $branch = trim($output);
32220 $version = $this->versionParser->normalizeBranch($branch);
32221 $isFeatureBranch = 0 === strpos($version, 'dev-');
32222
32223 if ('9999999-dev' === $version) {
32224 return array('version' => $version, 'commit' => null, 'pretty_version' => 'dev-'.$branch);
32225 }
32226
32227 if (!$isFeatureBranch) {
32228 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
32229 }
32230
32231
32232  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
32233 $branches = array_keys($driver->getBranches());
32234
32235
32236  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
32237 $result['commit'] = '';
32238 $result['feature_version'] = $version;
32239 $result['feature_pretty_version'] = $version;
32240
32241 return $result;
32242 }
32243 }
32244
32245 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
32246 {
32247 $prettyVersion = $version;
32248
32249
32250  
32251  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
32252 || strpos(json_encode($packageConfig), '"self.version"')
32253 ) {
32254 $branch = preg_replace('{^dev-}', '', $version);
32255 $length = PHP_INT_MAX;
32256
32257 $nonFeatureBranches = '';
32258 if (!empty($packageConfig['non-feature-branches'])) {
32259 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
32260 }
32261
32262 foreach ($branches as $candidate) {
32263
32264  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
32265 break;
32266 }
32267
32268
32269  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
32270 continue;
32271 }
32272
32273 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
32274 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
32275 continue;
32276 }
32277
32278 if (strlen($output) < $length) {
32279 $length = strlen($output);
32280 $version = $this->versionParser->normalizeBranch($candidate);
32281 $prettyVersion = 'dev-' . $match[1];
32282 }
32283 }
32284 }
32285
32286 return array('version' => $version, 'pretty_version' => $prettyVersion);
32287 }
32288
32289 private function guessFossilVersion(array $packageConfig, $path)
32290 {
32291 $version = null;
32292 $prettyVersion = null;
32293
32294
32295  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
32296 $branch = trim($output);
32297 $version = $this->versionParser->normalizeBranch($branch);
32298 $prettyVersion = 'dev-' . $branch;
32299 }
32300
32301
32302  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
32303 try {
32304 $version = $this->versionParser->normalize(trim($output));
32305 $prettyVersion = trim($output);
32306 } catch (\Exception $e) {
32307 }
32308 }
32309
32310 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
32311 }
32312
32313 private function guessSvnVersion(array $packageConfig, $path)
32314 {
32315 SvnUtil::cleanEnv();
32316
32317
32318  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
32319 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
32320 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
32321 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
32322
32323 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
32324
32325 if (preg_match($urlPattern, $output, $matches)) {
32326 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
32327
32328  $version = $this->versionParser->normalizeBranch($matches[3]);
32329 $prettyVersion = 'dev-' . $matches[3];
32330
32331 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
32332 }
32333
32334 $prettyVersion = trim($matches[1]);
32335 $version = $this->versionParser->normalize($prettyVersion);
32336
32337 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
32338 }
32339 }
32340 }
32341 }
32342 <?php
32343
32344
32345
32346
32347
32348
32349
32350
32351
32352
32353
32354 namespace Composer\Package\Version;
32355
32356 use Composer\Repository\PlatformRepository;
32357 use Composer\Semver\VersionParser as SemverVersionParser;
32358 use Composer\Semver\Semver;
32359
32360 class VersionParser extends SemverVersionParser
32361 {
32362 private static $constraints = array();
32363
32364
32365
32366
32367 public function parseConstraints($constraints)
32368 {
32369 if (!isset(self::$constraints[$constraints])) {
32370 self::$constraints[$constraints] = parent::parseConstraints($constraints);
32371 }
32372
32373 return self::$constraints[$constraints];
32374 }
32375
32376
32377
32378
32379
32380
32381
32382
32383
32384
32385
32386 public function parseNameVersionPairs(array $pairs)
32387 {
32388 $pairs = array_values($pairs);
32389 $result = array();
32390
32391 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
32392 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
32393 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
32394 $pair .= ' '.$pairs[$i + 1];
32395 $i++;
32396 }
32397
32398 if (strpos($pair, ' ')) {
32399 list($name, $version) = explode(' ', $pair, 2);
32400 $result[] = array('name' => $name, 'version' => $version);
32401 } else {
32402 $result[] = array('name' => $pair);
32403 }
32404 }
32405
32406 return $result;
32407 }
32408
32409
32410
32411
32412 public static function isUpgrade($normalizedFrom, $normalizedTo)
32413 {
32414 if (substr($normalizedFrom, 0, 4) === 'dev-' || substr($normalizedTo, 0, 4) === 'dev-') {
32415 return true;
32416 }
32417
32418 $sorted = Semver::sort(array($normalizedTo, $normalizedFrom));
32419
32420 return $sorted[0] === $normalizedFrom;
32421 }
32422 }
32423 <?php
32424
32425
32426
32427
32428
32429
32430
32431
32432
32433
32434
32435 namespace Composer\Package\Version;
32436
32437 use Composer\DependencyResolver\Pool;
32438 use Composer\Package\BasePackage;
32439 use Composer\Package\PackageInterface;
32440 use Composer\Plugin\PluginInterface;
32441 use Composer\Composer;
32442 use Composer\Package\Loader\ArrayLoader;
32443 use Composer\Package\Dumper\ArrayDumper;
32444 use Composer\Semver\Constraint\Constraint;
32445
32446
32447
32448
32449
32450
32451
32452 class VersionSelector
32453 {
32454 private $pool;
32455
32456 private $parser;
32457
32458 public function __construct(Pool $pool)
32459 {
32460 $this->pool = $pool;
32461 }
32462
32463
32464
32465
32466
32467
32468
32469
32470
32471
32472
32473 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
32474 {
32475 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
32476 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
32477
32478 if ($targetPhpVersion) {
32479 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
32480 $composerRuntimeConstraint = new Constraint('==', $this->getParser()->normalize(Composer::RUNTIME_API_VERSION));
32481 $composerPluginConstraint = new Constraint('==', $this->getParser()->normalize(PluginInterface::PLUGIN_API_VERSION));
32482 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint, $composerPluginConstraint, $composerRuntimeConstraint) {
32483 $reqs = $pkg->getRequires();
32484
32485 return (!isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint))
32486 && (!isset($reqs['composer-plugin-api']) || $reqs['composer-plugin-api']->getConstraint()->matches($composerPluginConstraint))
32487 && (!isset($reqs['composer-runtime-api']) || $reqs['composer-runtime-api']->getConstraint()->matches($composerRuntimeConstraint));
32488 });
32489 }
32490
32491 if (!$candidates) {
32492 return false;
32493 }
32494
32495
32496  $package = reset($candidates);
32497 $minPriority = BasePackage::$stabilities[$preferredStability];
32498 foreach ($candidates as $candidate) {
32499 $candidatePriority = $candidate->getStabilityPriority();
32500 $currentPriority = $package->getStabilityPriority();
32501
32502
32503  
32504  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
32505 continue;
32506 }
32507
32508
32509  
32510  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
32511 $package = $candidate;
32512 continue;
32513 }
32514
32515
32516  
32517  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
32518 $package = $candidate;
32519 continue;
32520 }
32521
32522
32523  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
32524 $package = $candidate;
32525 }
32526 }
32527
32528 return $package;
32529 }
32530
32531
32532
32533
32534
32535
32536
32537
32538
32539
32540
32541
32542
32543
32544
32545
32546 public function findRecommendedRequireVersion(PackageInterface $package)
32547 {
32548 $version = $package->getVersion();
32549 if (!$package->isDev()) {
32550 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
32551 }
32552
32553 $loader = new ArrayLoader($this->getParser());
32554 $dumper = new ArrayDumper();
32555 $extra = $loader->getBranchAlias($dumper->dump($package));
32556 if ($extra) {
32557 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
32558 if ($count) {
32559 $extra = str_replace('.9999999', '.0', $extra);
32560
32561 return $this->transformVersion($extra, $extra, 'dev');
32562 }
32563 }
32564
32565 return $package->getPrettyVersion();
32566 }
32567
32568 private function transformVersion($version, $prettyVersion, $stability)
32569 {
32570
32571  
32572  $semanticVersionParts = explode('.', $version);
32573
32574
32575  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
32576
32577  if ($semanticVersionParts[0] === '0') {
32578 unset($semanticVersionParts[3]);
32579 } else {
32580 unset($semanticVersionParts[2], $semanticVersionParts[3]);
32581 }
32582 $version = implode('.', $semanticVersionParts);
32583 } else {
32584 return $prettyVersion;
32585 }
32586
32587
32588  if ($stability != 'stable') {
32589 $version .= '@'.$stability;
32590 }
32591
32592
32593  return '^' . $version;
32594 }
32595
32596 private function getParser()
32597 {
32598 if ($this->parser === null) {
32599 $this->parser = new VersionParser();
32600 }
32601
32602 return $this->parser;
32603 }
32604 }
32605 <?php
32606
32607
32608
32609
32610
32611
32612
32613
32614
32615
32616
32617 namespace Composer\Plugin\Capability;
32618
32619
32620
32621
32622
32623
32624
32625 interface Capability
32626 {
32627 }
32628 <?php
32629
32630
32631
32632
32633
32634
32635
32636
32637
32638
32639
32640 namespace Composer\Plugin\Capability;
32641
32642
32643
32644
32645
32646
32647
32648
32649
32650
32651
32652 interface CommandProvider extends Capability
32653 {
32654
32655
32656
32657
32658
32659 public function getCommands();
32660 }
32661 <?php
32662
32663
32664
32665
32666
32667
32668
32669
32670
32671
32672
32673 namespace Composer\Plugin;
32674
32675
32676
32677
32678
32679
32680
32681
32682 interface Capable
32683 {
32684
32685
32686
32687
32688
32689
32690
32691
32692
32693
32694
32695
32696
32697
32698
32699
32700
32701
32702 public function getCapabilities();
32703 }
32704 <?php
32705
32706
32707
32708
32709
32710
32711
32712
32713
32714
32715
32716 namespace Composer\Plugin;
32717
32718 use Composer\EventDispatcher\Event;
32719 use Symfony\Component\Console\Input\InputInterface;
32720 use Symfony\Component\Console\Output\OutputInterface;
32721
32722
32723
32724
32725
32726
32727 class CommandEvent extends Event
32728 {
32729
32730
32731
32732 private $commandName;
32733
32734
32735
32736
32737 private $input;
32738
32739
32740
32741
32742 private $output;
32743
32744
32745
32746
32747
32748
32749
32750
32751
32752
32753
32754 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
32755 {
32756 parent::__construct($name, $args, $flags);
32757 $this->commandName = $commandName;
32758 $this->input = $input;
32759 $this->output = $output;
32760 }
32761
32762
32763
32764
32765
32766
32767 public function getInput()
32768 {
32769 return $this->input;
32770 }
32771
32772
32773
32774
32775
32776
32777 public function getOutput()
32778 {
32779 return $this->output;
32780 }
32781
32782
32783
32784
32785
32786
32787 public function getCommandName()
32788 {
32789 return $this->commandName;
32790 }
32791 }
32792 <?php
32793
32794
32795
32796
32797
32798
32799
32800
32801
32802
32803
32804 namespace Composer\Plugin;
32805
32806
32807
32808
32809
32810
32811 class PluginEvents
32812 {
32813
32814
32815
32816
32817
32818
32819
32820
32821 const INIT = 'init';
32822
32823
32824
32825
32826
32827
32828
32829
32830
32831 const COMMAND = 'command';
32832
32833
32834
32835
32836
32837
32838
32839
32840
32841 const PRE_FILE_DOWNLOAD = 'pre-file-download';
32842
32843
32844
32845
32846
32847
32848
32849
32850
32851 const PRE_COMMAND_RUN = 'pre-command-run';
32852 }
32853 <?php
32854
32855
32856
32857
32858
32859
32860
32861
32862
32863
32864
32865 namespace Composer\Plugin;
32866
32867 use Composer\Composer;
32868 use Composer\IO\IOInterface;
32869
32870
32871
32872
32873
32874
32875 interface PluginInterface
32876 {
32877
32878
32879
32880
32881
32882 const PLUGIN_API_VERSION = '1.1.0';
32883
32884
32885
32886
32887
32888
32889
32890 public function activate(Composer $composer, IOInterface $io);
32891 }
32892 <?php
32893
32894
32895
32896
32897
32898
32899
32900
32901
32902
32903
32904 namespace Composer\Plugin;
32905
32906 use Composer\Composer;
32907 use Composer\EventDispatcher\EventSubscriberInterface;
32908 use Composer\IO\IOInterface;
32909 use Composer\Package\CompletePackage;
32910 use Composer\Package\Package;
32911 use Composer\Package\Version\VersionParser;
32912 use Composer\Repository\RepositoryInterface;
32913 use Composer\Package\PackageInterface;
32914 use Composer\Package\Link;
32915 use Composer\Semver\Constraint\Constraint;
32916 use Composer\DependencyResolver\Pool;
32917 use Composer\Plugin\Capability\Capability;
32918 use Composer\Util\PackageSorter;
32919
32920
32921
32922
32923
32924
32925
32926 class PluginManager
32927 {
32928 protected $composer;
32929 protected $io;
32930 protected $globalComposer;
32931 protected $versionParser;
32932 protected $disablePlugins = false;
32933
32934 protected $plugins = array();
32935 protected $registeredPlugins = array();
32936
32937 private static $classCounter = 0;
32938
32939
32940
32941
32942
32943
32944
32945
32946
32947 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
32948 {
32949 $this->io = $io;
32950 $this->composer = $composer;
32951 $this->globalComposer = $globalComposer;
32952 $this->versionParser = new VersionParser();
32953 $this->disablePlugins = $disablePlugins;
32954 }
32955
32956
32957
32958
32959 public function loadInstalledPlugins()
32960 {
32961 if ($this->disablePlugins) {
32962 return;
32963 }
32964
32965 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
32966 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
32967 if ($repo) {
32968 $this->loadRepository($repo);
32969 }
32970 if ($globalRepo) {
32971 $this->loadRepository($globalRepo);
32972 }
32973 }
32974
32975
32976
32977
32978
32979
32980 public function getPlugins()
32981 {
32982 return $this->plugins;
32983 }
32984
32985
32986
32987
32988
32989
32990 public function getGlobalComposer()
32991 {
32992 return $this->globalComposer;
32993 }
32994
32995
32996
32997
32998
32999
33000
33001
33002
33003
33004
33005
33006 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
33007 {
33008 if ($this->disablePlugins) {
33009 return;
33010 }
33011
33012 if ($package->getType() === 'composer-plugin') {
33013 $requiresComposer = null;
33014 foreach ($package->getRequires() as $link) { 
33015 if ('composer-plugin-api' === $link->getTarget()) {
33016 $requiresComposer = $link->getConstraint();
33017 break;
33018 }
33019 }
33020
33021 if (!$requiresComposer) {
33022 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
33023 }
33024
33025 $currentPluginApiVersion = $this->getPluginApiVersion();
33026 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
33027
33028 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
33029 $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>');
33030 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
33031 $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>');
33032
33033 return;
33034 }
33035 }
33036
33037 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
33038
33039 if (in_array($package->getName(), $this->registeredPlugins)) {
33040 return;
33041 }
33042
33043 $extra = $package->getExtra();
33044 if (empty($extra['class'])) {
33045 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
33046 }
33047 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
33048
33049 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
33050 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
33051
33052 $pool = new Pool('dev');
33053 $pool->addRepository($localRepo);
33054 if ($globalRepo) {
33055 $pool->addRepository($globalRepo);
33056 }
33057
33058 $autoloadPackages = array($package->getName() => $package);
33059 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
33060
33061 $generator = $this->composer->getAutoloadGenerator();
33062 $autoloads = array();
33063 foreach ($autoloadPackages as $autoloadPackage) {
33064 $downloadPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage));
33065 $autoloads[] = array($autoloadPackage, $downloadPath);
33066 }
33067
33068 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
33069 $classLoader = $generator->createLoader($map);
33070 $classLoader->register();
33071
33072 foreach ($classes as $class) {
33073 if (class_exists($class, false)) {
33074 $class = trim($class, '\\');
33075 $path = $classLoader->findFile($class);
33076 $code = file_get_contents($path);
33077 $separatorPos = strrpos($class, '\\');
33078 $className = $class;
33079 if ($separatorPos) {
33080 $className = substr($class, $separatorPos + 1);
33081 }
33082 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
33083 $code = str_replace('__FILE__', var_export($path, true), $code);
33084 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
33085 $code = str_replace('__CLASS__', var_export($class, true), $code);
33086 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
33087 eval($code);
33088 $class .= '_composer_tmp'.self::$classCounter;
33089 self::$classCounter++;
33090 }
33091
33092 if ($oldInstallerPlugin) {
33093 $installer = new $class($this->io, $this->composer);
33094 $this->composer->getInstallationManager()->addInstaller($installer);
33095 } elseif (class_exists($class)) {
33096 $plugin = new $class();
33097 $this->addPlugin($plugin);
33098 $this->registeredPlugins[] = $package->getName();
33099 } elseif ($failOnMissingClasses) {
33100 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
33101 }
33102 }
33103 }
33104
33105
33106
33107
33108
33109
33110 protected function getPluginApiVersion()
33111 {
33112 return PluginInterface::PLUGIN_API_VERSION;
33113 }
33114
33115
33116
33117
33118
33119
33120
33121
33122
33123
33124 public function addPlugin(PluginInterface $plugin)
33125 {
33126 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
33127 $this->plugins[] = $plugin;
33128 $plugin->activate($this->composer, $this->io);
33129
33130 if ($plugin instanceof EventSubscriberInterface) {
33131 $this->composer->getEventDispatcher()->addSubscriber($plugin);
33132 }
33133 }
33134
33135
33136
33137
33138
33139
33140
33141
33142
33143
33144
33145
33146 private function loadRepository(RepositoryInterface $repo)
33147 {
33148 $packages = $repo->getPackages();
33149 $sortedPackages = array_reverse(PackageSorter::sortPackages($packages));
33150 foreach ($sortedPackages as $package) {
33151 if (!($package instanceof CompletePackage)) {
33152 continue;
33153 }
33154 if ('composer-plugin' === $package->getType()) {
33155 $this->registerPackage($package);
33156
33157  } elseif ('composer-installer' === $package->getType()) {
33158 $this->registerPackage($package);
33159 }
33160 }
33161 }
33162
33163
33164
33165
33166
33167
33168
33169
33170
33171
33172 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
33173 {
33174 $requires = array_merge(
33175 $package->getRequires(),
33176 $package->getDevRequires()
33177 );
33178
33179 foreach ($requires as $requireLink) {
33180 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
33181 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
33182 $collected[$requiredPackage->getName()] = $requiredPackage;
33183 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
33184 }
33185 }
33186
33187 return $collected;
33188 }
33189
33190
33191
33192
33193
33194
33195
33196
33197
33198
33199
33200 private function lookupInstalledPackage(Pool $pool, Link $link)
33201 {
33202 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
33203
33204 return !empty($packages) ? $packages[0] : null;
33205 }
33206
33207
33208
33209
33210
33211
33212
33213
33214
33215 private function getInstallPath(PackageInterface $package, $global = false)
33216 {
33217 if (!$global) {
33218 return $this->composer->getInstallationManager()->getInstallPath($package);
33219 }
33220
33221 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
33222 }
33223
33224
33225
33226
33227
33228
33229
33230 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
33231 {
33232 if (!($plugin instanceof Capable)) {
33233 return null;
33234 }
33235
33236 $capabilities = (array) $plugin->getCapabilities();
33237
33238 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
33239 return trim($capabilities[$capability]);
33240 }
33241
33242 if (
33243 array_key_exists($capability, $capabilities)
33244 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
33245 ) {
33246 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
33247 }
33248 }
33249
33250
33251
33252
33253
33254
33255
33256
33257
33258 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
33259 {
33260 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
33261 if (!class_exists($capabilityClass)) {
33262 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
33263 }
33264
33265 $ctorArgs['plugin'] = $plugin;
33266 $capabilityObj = new $capabilityClass($ctorArgs);
33267
33268
33269  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
33270 throw new \RuntimeException(
33271 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
33272 );
33273 }
33274
33275 return $capabilityObj;
33276 }
33277 }
33278
33279
33280
33281
33282
33283
33284
33285
33286 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
33287 {
33288 $capabilities = array();
33289 foreach ($this->getPlugins() as $plugin) {
33290 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
33291 $capabilities[] = $capability;
33292 }
33293 }
33294
33295 return $capabilities;
33296 }
33297 }
33298 <?php
33299
33300
33301
33302
33303
33304
33305
33306
33307
33308
33309
33310 namespace Composer\Plugin;
33311
33312 use Composer\EventDispatcher\Event;
33313 use Symfony\Component\Console\Input\InputInterface;
33314
33315
33316
33317
33318
33319
33320 class PreCommandRunEvent extends Event
33321 {
33322
33323
33324
33325 private $input;
33326
33327
33328
33329
33330 private $command;
33331
33332
33333
33334
33335
33336
33337
33338
33339 public function __construct($name, InputInterface $input, $command)
33340 {
33341 parent::__construct($name);
33342 $this->input = $input;
33343 $this->command = $command;
33344 }
33345
33346
33347
33348
33349
33350
33351 public function getInput()
33352 {
33353 return $this->input;
33354 }
33355
33356
33357
33358
33359
33360
33361 public function getCommand()
33362 {
33363 return $this->command;
33364 }
33365 }
33366 <?php
33367
33368
33369
33370
33371
33372
33373
33374
33375
33376
33377
33378 namespace Composer\Plugin;
33379
33380 use Composer\EventDispatcher\Event;
33381 use Composer\Util\RemoteFilesystem;
33382
33383
33384
33385
33386
33387
33388 class PreFileDownloadEvent extends Event
33389 {
33390
33391
33392
33393 private $rfs;
33394
33395
33396
33397
33398 private $processedUrl;
33399
33400
33401
33402
33403
33404
33405
33406
33407 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
33408 {
33409 parent::__construct($name);
33410 $this->rfs = $rfs;
33411 $this->processedUrl = $processedUrl;
33412 }
33413
33414
33415
33416
33417
33418
33419 public function getRemoteFilesystem()
33420 {
33421 return $this->rfs;
33422 }
33423
33424
33425
33426
33427
33428
33429 public function setRemoteFilesystem(RemoteFilesystem $rfs)
33430 {
33431 $this->rfs = $rfs;
33432 }
33433
33434
33435
33436
33437
33438
33439 public function getProcessedUrl()
33440 {
33441 return $this->processedUrl;
33442 }
33443 }
33444 <?php
33445
33446
33447
33448
33449
33450
33451
33452
33453
33454
33455
33456 namespace Composer\Question;
33457
33458 use Symfony\Component\Console\Exception\InvalidArgumentException;
33459 use Symfony\Component\Console\Question\Question;
33460
33461
33462
33463
33464
33465
33466
33467
33468 class StrictConfirmationQuestion extends Question
33469 {
33470 private $trueAnswerRegex;
33471 private $falseAnswerRegex;
33472
33473
33474
33475
33476
33477
33478
33479
33480
33481 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
33482 {
33483 parent::__construct($question, (bool) $default);
33484
33485 $this->trueAnswerRegex = $trueAnswerRegex;
33486 $this->falseAnswerRegex = $falseAnswerRegex;
33487 $this->setNormalizer($this->getDefaultNormalizer());
33488 $this->setValidator($this->getDefaultValidator());
33489 }
33490
33491
33492
33493
33494
33495
33496 private function getDefaultNormalizer()
33497 {
33498 $default = $this->getDefault();
33499 $trueRegex = $this->trueAnswerRegex;
33500 $falseRegex = $this->falseAnswerRegex;
33501
33502 return function ($answer) use ($default, $trueRegex, $falseRegex) {
33503 if (is_bool($answer)) {
33504 return $answer;
33505 }
33506 if (empty($answer) && !empty($default)) {
33507 return $default;
33508 }
33509
33510 if (preg_match($trueRegex, $answer)) {
33511 return true;
33512 }
33513
33514 if (preg_match($falseRegex, $answer)) {
33515 return false;
33516 }
33517
33518 return null;
33519 };
33520 }
33521
33522
33523
33524
33525
33526
33527 private function getDefaultValidator()
33528 {
33529 return function ($answer) {
33530 if (!is_bool($answer)) {
33531 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
33532 }
33533
33534 return $answer;
33535 };
33536 }
33537 }
33538 <?php
33539
33540
33541
33542
33543
33544
33545
33546
33547
33548
33549
33550 namespace Composer\Repository;
33551
33552 use Composer\Package\AliasPackage;
33553 use Composer\Package\PackageInterface;
33554 use Composer\Package\CompletePackageInterface;
33555 use Composer\Package\Version\VersionParser;
33556 use Composer\Semver\Constraint\ConstraintInterface;
33557 use Composer\Semver\Constraint\Constraint;
33558
33559
33560
33561
33562
33563
33564 class ArrayRepository extends BaseRepository
33565 {
33566
33567 protected $packages;
33568
33569
33570
33571
33572 protected $packageMap;
33573
33574 public function __construct(array $packages = array())
33575 {
33576 foreach ($packages as $package) {
33577 $this->addPackage($package);
33578 }
33579 }
33580
33581
33582
33583
33584 public function findPackage($name, $constraint)
33585 {
33586 $name = strtolower($name);
33587
33588 if (!$constraint instanceof ConstraintInterface) {
33589 $versionParser = new VersionParser();
33590 $constraint = $versionParser->parseConstraints($constraint);
33591 }
33592
33593 foreach ($this->getPackages() as $package) {
33594 if ($name === $package->getName()) {
33595 $pkgConstraint = new Constraint('==', $package->getVersion());
33596 if ($constraint->matches($pkgConstraint)) {
33597 return $package;
33598 }
33599 }
33600 }
33601
33602 return null;
33603 }
33604
33605
33606
33607
33608 public function findPackages($name, $constraint = null)
33609 {
33610
33611  $name = strtolower($name);
33612 $packages = array();
33613
33614 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
33615 $versionParser = new VersionParser();
33616 $constraint = $versionParser->parseConstraints($constraint);
33617 }
33618
33619 foreach ($this->getPackages() as $package) {
33620 if ($name === $package->getName()) {
33621 $pkgConstraint = new Constraint('==', $package->getVersion());
33622 if (null === $constraint || $constraint->matches($pkgConstraint)) {
33623 $packages[] = $package;
33624 }
33625 }
33626 }
33627
33628 return $packages;
33629 }
33630
33631
33632
33633
33634 public function search($query, $mode = 0, $type = null)
33635 {
33636 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
33637
33638 $matches = array();
33639 foreach ($this->getPackages() as $package) {
33640 $name = $package->getName();
33641 if (isset($matches[$name])) {
33642 continue;
33643 }
33644 if (preg_match($regex, $name)
33645 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
33646 ) {
33647 if (null !== $type && $package->getType() !== $type) {
33648 continue;
33649 }
33650
33651 $matches[$name] = array(
33652 'name' => $package->getPrettyName(),
33653 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
33654 );
33655 }
33656 }
33657
33658 return array_values($matches);
33659 }
33660
33661
33662
33663
33664 public function hasPackage(PackageInterface $package)
33665 {
33666 if ($this->packageMap === null) {
33667 $this->packageMap = array();
33668 foreach ($this->getPackages() as $repoPackage) {
33669 $this->packageMap[$repoPackage->getUniqueName()] = $repoPackage;
33670 }
33671 }
33672
33673 return isset($this->packageMap[$package->getUniqueName()]);
33674 }
33675
33676
33677
33678
33679
33680
33681 public function addPackage(PackageInterface $package)
33682 {
33683 if (null === $this->packages) {
33684 $this->initialize();
33685 }
33686 $package->setRepository($this);
33687 $this->packages[] = $package;
33688
33689 if ($package instanceof AliasPackage) {
33690 $aliasedPackage = $package->getAliasOf();
33691 if (null === $aliasedPackage->getRepository()) {
33692 $this->addPackage($aliasedPackage);
33693 }
33694 }
33695
33696
33697  $this->packageMap = null;
33698 }
33699
33700 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
33701 {
33702 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
33703 }
33704
33705
33706
33707
33708
33709
33710 public function removePackage(PackageInterface $package)
33711 {
33712 $packageId = $package->getUniqueName();
33713
33714 foreach ($this->getPackages() as $key => $repoPackage) {
33715 if ($packageId === $repoPackage->getUniqueName()) {
33716 array_splice($this->packages, $key, 1);
33717
33718
33719  $this->packageMap = null;
33720
33721 return;
33722 }
33723 }
33724 }
33725
33726
33727
33728
33729 public function getPackages()
33730 {
33731 if (null === $this->packages) {
33732 $this->initialize();
33733 }
33734
33735 return $this->packages;
33736 }
33737
33738
33739
33740
33741
33742
33743 public function count()
33744 {
33745 return count($this->packages);
33746 }
33747
33748
33749
33750
33751 protected function initialize()
33752 {
33753 $this->packages = array();
33754 }
33755 }
33756 <?php
33757
33758
33759
33760
33761
33762
33763
33764
33765
33766
33767
33768 namespace Composer\Repository;
33769
33770 use Composer\IO\IOInterface;
33771 use Composer\Json\JsonFile;
33772 use Composer\Package\Loader\ArrayLoader;
33773 use Composer\Package\Loader\LoaderInterface;
33774 use Composer\Util\Zip;
33775
33776
33777
33778
33779 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33780 {
33781
33782 protected $loader;
33783
33784 protected $lookup;
33785 protected $repoConfig;
33786 private $io;
33787
33788 public function __construct(array $repoConfig, IOInterface $io)
33789 {
33790 parent::__construct();
33791 if (!extension_loaded('zip')) {
33792 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
33793 }
33794
33795 $this->loader = new ArrayLoader();
33796 $this->lookup = $repoConfig['url'];
33797 $this->io = $io;
33798 $this->repoConfig = $repoConfig;
33799 }
33800
33801 public function getRepoConfig()
33802 {
33803 return $this->repoConfig;
33804 }
33805
33806 protected function initialize()
33807 {
33808 parent::initialize();
33809
33810 $this->scanDirectory($this->lookup);
33811 }
33812
33813 private function scanDirectory($path)
33814 {
33815 $io = $this->io;
33816
33817 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
33818 $iterator = new \RecursiveIteratorIterator($directory);
33819 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
33820 foreach ($regex as $file) {
33821
33822 if (!$file->isFile()) {
33823 continue;
33824 }
33825
33826 $package = $this->getComposerInformation($file);
33827 if (!$package) {
33828 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
33829 continue;
33830 }
33831
33832 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
33833 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
33834
33835 $this->addPackage($package);
33836 }
33837 }
33838
33839 private function getComposerInformation(\SplFileInfo $file)
33840 {
33841 $json = Zip::getComposerJson($file->getPathname());
33842
33843 if (null === $json) {
33844 return false;
33845 }
33846
33847 $package = JsonFile::parseJson($json, $file->getPathname().'#composer.json');
33848 $package['dist'] = array(
33849 'type' => 'zip',
33850 'url' => strtr($file->getPathname(), '\\', '/'),
33851 'shasum' => sha1_file($file->getRealPath()),
33852 );
33853
33854 try {
33855 $package = $this->loader->load($package);
33856 } catch (\UnexpectedValueException $e) {
33857 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
33858 }
33859
33860 return $package;
33861 }
33862 }
33863 <?php
33864
33865
33866
33867
33868
33869
33870
33871
33872
33873
33874
33875 namespace Composer\Repository;
33876
33877 use Composer\Package\RootPackageInterface;
33878 use Composer\Semver\Constraint\ConstraintInterface;
33879 use Composer\Semver\Constraint\Constraint;
33880 use Composer\Package\Link;
33881
33882
33883
33884
33885
33886
33887 abstract class BaseRepository implements RepositoryInterface
33888 {
33889
33890
33891
33892
33893
33894
33895
33896
33897
33898
33899
33900
33901
33902 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
33903 {
33904 $needles = array_map('strtolower', (array) $needle);
33905 $results = array();
33906
33907
33908  if (null === $packagesFound) {
33909 $packagesFound = $needles;
33910 }
33911
33912
33913  $rootPackage = null;
33914 foreach ($this->getPackages() as $package) {
33915 if ($package instanceof RootPackageInterface) {
33916 $rootPackage = $package;
33917 break;
33918 }
33919 }
33920
33921
33922  foreach ($this->getPackages() as $package) {
33923 $links = $package->getRequires();
33924
33925
33926  
33927  $packagesInTree = $packagesFound;
33928
33929
33930  if (!$invert) {
33931 $links += $package->getReplaces();
33932
33933
33934  
33935  
33936  foreach ($package->getReplaces() as $link) {
33937 foreach ($needles as $needle) {
33938 if ($link->getSource() === $needle) {
33939 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
33940
33941  if (in_array($link->getTarget(), $packagesInTree)) {
33942 $results[] = array($package, $link, false);
33943 continue;
33944 }
33945 $packagesInTree[] = $link->getTarget();
33946 $dependents = $recurse ? $this->getDependents($link->getTarget(), null, false, true, $packagesInTree) : array();
33947 $results[] = array($package, $link, $dependents);
33948 $needles[] = $link->getTarget();
33949 }
33950 }
33951 }
33952 }
33953 }
33954
33955
33956  if ($package instanceof RootPackageInterface) {
33957 $links += $package->getDevRequires();
33958 }
33959
33960
33961  foreach ($links as $link) {
33962 foreach ($needles as $needle) {
33963 if ($link->getTarget() === $needle) {
33964 if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
33965
33966  if (in_array($link->getSource(), $packagesInTree)) {
33967 $results[] = array($package, $link, false);
33968 continue;
33969 }
33970 $packagesInTree[] = $link->getSource();
33971 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
33972 $results[] = array($package, $link, $dependents);
33973 }
33974 }
33975 }
33976 }
33977
33978
33979  if ($invert && in_array($package->getName(), $needles)) {
33980 foreach ($package->getConflicts() as $link) {
33981 foreach ($this->findPackages($link->getTarget()) as $pkg) {
33982 $version = new Constraint('=', $pkg->getVersion());
33983 if ($link->getConstraint()->matches($version) === $invert) {
33984 $results[] = array($package, $link, false);
33985 }
33986 }
33987 }
33988 }
33989
33990
33991  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
33992 foreach ($package->getRequires() as $link) {
33993 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
33994 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
33995 continue;
33996 }
33997
33998 $platformPkg = $this->findPackage($link->getTarget(), '*');
33999 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
34000 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
34001
34002 continue;
34003 }
34004
34005 foreach ($this->getPackages() as $pkg) {
34006 if (!in_array($link->getTarget(), $pkg->getNames())) {
34007 continue;
34008 }
34009
34010 $version = new Constraint('=', $pkg->getVersion());
34011 if (!$link->getConstraint()->matches($version)) {
34012
34013  
34014  if ($rootPackage) {
34015 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
34016 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
34017 $results[] = array($package, $link, false);
34018 $results[] = array($rootPackage, $rootReq, false);
34019 continue 3;
34020 }
34021 }
34022 $results[] = array($package, $link, false);
34023 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
34024 } else {
34025
34026  $results[] = array($package, $link, false);
34027 }
34028 }
34029
34030 continue 2;
34031 }
34032 }
34033 }
34034 }
34035
34036 ksort($results);
34037
34038 return $results;
34039 }
34040 }
34041 <?php
34042
34043
34044
34045
34046
34047
34048
34049
34050
34051
34052
34053 namespace Composer\Repository;
34054
34055 use Composer\Package\Loader\ArrayLoader;
34056 use Composer\Package\PackageInterface;
34057 use Composer\Package\AliasPackage;
34058 use Composer\Package\Version\VersionParser;
34059 use Composer\DependencyResolver\Pool;
34060 use Composer\Json\JsonFile;
34061 use Composer\Cache;
34062 use Composer\Config;
34063 use Composer\Composer;
34064 use Composer\Factory;
34065 use Composer\IO\IOInterface;
34066 use Composer\Util\RemoteFilesystem;
34067 use Composer\Plugin\PluginEvents;
34068 use Composer\Plugin\PreFileDownloadEvent;
34069 use Composer\EventDispatcher\EventDispatcher;
34070 use Composer\Downloader\TransportException;
34071 use Composer\Semver\Constraint\ConstraintInterface;
34072 use Composer\Semver\Constraint\Constraint;
34073
34074
34075
34076
34077 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
34078 {
34079 protected $config;
34080 protected $repoConfig;
34081 protected $options;
34082 protected $url;
34083 protected $baseUrl;
34084 protected $io;
34085 protected $rfs;
34086 protected $cache;
34087 protected $notifyUrl;
34088 protected $searchUrl;
34089 protected $hasProviders = false;
34090 protected $providersUrl;
34091 protected $lazyProvidersUrl;
34092 protected $providerListing;
34093 protected $providers = array();
34094 protected $providersByUid = array();
34095 protected $loader;
34096 protected $rootAliases;
34097 protected $allowSslDowngrade = false;
34098 protected $eventDispatcher;
34099 protected $sourceMirrors;
34100 protected $distMirrors;
34101 private $degradedMode = false;
34102 private $rootData;
34103 private $hasPartialPackages;
34104 private $partialPackagesByName;
34105
34106 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34107 {
34108 parent::__construct();
34109 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
34110
34111  $repoConfig['url'] = 'http://'.$repoConfig['url'];
34112 }
34113 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
34114
34115 if ('https?' === substr($repoConfig['url'], 0, 6)) {
34116 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
34117 }
34118
34119 $urlBits = parse_url($repoConfig['url']);
34120 if ($urlBits === false || empty($urlBits['scheme'])) {
34121 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
34122 }
34123
34124 if (!isset($repoConfig['options'])) {
34125 $repoConfig['options'] = array();
34126 }
34127 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
34128 $this->allowSslDowngrade = true;
34129 }
34130
34131 $this->config = $config;
34132 $this->options = $repoConfig['options'];
34133 $this->url = $repoConfig['url'];
34134
34135
34136  if (preg_match('{^(?P<proto>https?)://packagist\.org/?$}i', $this->url, $match)) {
34137 $this->url = $match['proto'].'://repo.packagist.org';
34138 }
34139
34140 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
34141 $this->io = $io;
34142 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
34143 $this->loader = new ArrayLoader();
34144 if ($rfs && $this->options) {
34145 $rfs = clone $rfs;
34146 $rfs->setOptions($this->options);
34147 }
34148 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
34149 $this->eventDispatcher = $eventDispatcher;
34150 $this->repoConfig = $repoConfig;
34151 }
34152
34153 public function getRepoConfig()
34154 {
34155 return $this->repoConfig;
34156 }
34157
34158 public function setRootAliases(array $rootAliases)
34159 {
34160 $this->rootAliases = $rootAliases;
34161 }
34162
34163
34164
34165
34166 public function findPackage($name, $constraint)
34167 {
34168 if (!$this->hasProviders()) {
34169 return parent::findPackage($name, $constraint);
34170 }
34171
34172 $name = strtolower($name);
34173 if (!$constraint instanceof ConstraintInterface) {
34174 $versionParser = new VersionParser();
34175 $constraint = $versionParser->parseConstraints($constraint);
34176 }
34177
34178 foreach ($this->getProviderNames() as $providerName) {
34179 if ($name === $providerName) {
34180 $packages = $this->whatProvides(new Pool('dev'), $providerName);
34181 foreach ($packages as $package) {
34182 if ($name === $package->getName()) {
34183 $pkgConstraint = new Constraint('==', $package->getVersion());
34184 if ($constraint->matches($pkgConstraint)) {
34185 return $package;
34186 }
34187 }
34188 }
34189 break;
34190 }
34191 }
34192 }
34193
34194
34195
34196
34197 public function findPackages($name, $constraint = null)
34198 {
34199 if (!$this->hasProviders()) {
34200 return parent::findPackages($name, $constraint);
34201 }
34202
34203  $name = strtolower($name);
34204
34205 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
34206 $versionParser = new VersionParser();
34207 $constraint = $versionParser->parseConstraints($constraint);
34208 }
34209
34210 $packages = array();
34211
34212 foreach ($this->getProviderNames() as $providerName) {
34213 if ($name === $providerName) {
34214 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
34215 foreach ($candidates as $package) {
34216 if ($name === $package->getName()) {
34217 $pkgConstraint = new Constraint('==', $package->getVersion());
34218 if (null === $constraint || $constraint->matches($pkgConstraint)) {
34219 $packages[] = $package;
34220 }
34221 }
34222 }
34223 break;
34224 }
34225 }
34226
34227 return $packages;
34228 }
34229
34230 public function getPackages()
34231 {
34232 if ($this->hasProviders()) {
34233 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
34234 }
34235
34236 return parent::getPackages();
34237 }
34238
34239
34240
34241
34242 public function search($query, $mode = 0, $type = null)
34243 {
34244 $this->loadRootServerFile();
34245
34246 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
34247 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
34248
34249 $origin = RemoteFilesystem::getOrigin($url);
34250 $json = $this->rfs->getContents($origin, $url, false);
34251 $search = JsonFile::parseJson($json, $url);
34252
34253 if (empty($search['results'])) {
34254 return array();
34255 }
34256
34257 $results = array();
34258 foreach ($search['results'] as $result) {
34259
34260  if (empty($result['virtual'])) {
34261 $results[] = $result;
34262 }
34263 }
34264
34265 return $results;
34266 }
34267
34268 if ($this->hasProviders()) {
34269 $results = array();
34270 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
34271
34272 foreach ($this->getProviderNames() as $name) {
34273 if (preg_match($regex, $name)) {
34274 $results[] = array('name' => $name);
34275 }
34276 }
34277
34278 return $results;
34279 }
34280
34281 return parent::search($query, $mode);
34282 }
34283
34284 public function getProviderNames()
34285 {
34286 $this->loadRootServerFile();
34287
34288 if (null === $this->providerListing) {
34289 $this->loadProviderListings($this->loadRootServerFile());
34290 }
34291
34292 if ($this->hasPartialPackages) {
34293 if (null === $this->partialPackagesByName) {
34294 $this->initializePartialPackages();
34295 }
34296
34297 return array_keys($this->partialPackagesByName);
34298 }
34299
34300 if ($this->lazyProvidersUrl) {
34301
34302  return array();
34303 }
34304
34305 if ($this->providersUrl) {
34306 return array_keys($this->providerListing);
34307 }
34308
34309 return array();
34310 }
34311
34312 protected function configurePackageTransportOptions(PackageInterface $package)
34313 {
34314 foreach ($package->getDistUrls() as $url) {
34315 if (strpos($url, $this->baseUrl) === 0) {
34316 $package->setTransportOptions($this->options);
34317
34318 return;
34319 }
34320 }
34321 }
34322
34323 public function hasProviders()
34324 {
34325 $this->loadRootServerFile();
34326
34327 return $this->hasProviders;
34328 }
34329
34330 public function resetPackageIds()
34331 {
34332 foreach ($this->providersByUid as $package) {
34333 if ($package instanceof AliasPackage) {
34334 $package->getAliasOf()->setId(-1);
34335 }
34336 $package->setId(-1);
34337 }
34338 }
34339
34340
34341
34342
34343
34344
34345
34346 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
34347 {
34348 if (isset($this->providers[$name]) && !$bypassFilters) {
34349 return $this->providers[$name];
34350 }
34351
34352 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
34353 $this->initializePartialPackages();
34354 }
34355
34356 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
34357
34358  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
34359 return array();
34360 }
34361
34362 if (null === $this->providerListing) {
34363 $this->loadProviderListings($this->loadRootServerFile());
34364 }
34365
34366 $useLastModifiedCheck = false;
34367 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
34368 $hash = null;
34369 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
34370 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
34371 $useLastModifiedCheck = true;
34372 } elseif ($this->providersUrl) {
34373
34374  if (!isset($this->providerListing[$name])) {
34375 return array();
34376 }
34377
34378 $hash = $this->providerListing[$name]['sha256'];
34379 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
34380 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
34381 } else {
34382 return array();
34383 }
34384
34385 $packages = null;
34386 if ($cacheKey) {
34387 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
34388 $packages = json_decode($this->cache->read($cacheKey), true);
34389 } elseif ($useLastModifiedCheck) {
34390 if ($contents = $this->cache->read($cacheKey)) {
34391 $contents = json_decode($contents, true);
34392 if (isset($contents['last-modified'])) {
34393 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
34394 if (true === $response) {
34395 $packages = $contents;
34396 } elseif ($response) {
34397 $packages = $response;
34398 }
34399 }
34400 }
34401 }
34402 }
34403
34404 if (!$packages) {
34405 try {
34406 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
34407 } catch (TransportException $e) {
34408
34409  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
34410 $packages = array('packages' => array());
34411 } else {
34412 throw $e;
34413 }
34414 }
34415 }
34416
34417 $loadingPartialPackage = false;
34418 } else {
34419 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
34420 $loadingPartialPackage = true;
34421 }
34422
34423 $this->providers[$name] = array();
34424 foreach ($packages['packages'] as $versions) {
34425 foreach ($versions as $version) {
34426 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
34427 continue;
34428 }
34429
34430
34431  if (isset($this->providersByUid[$version['uid']])) {
34432
34433  if (!isset($this->providers[$name][$version['uid']])) {
34434
34435  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
34436 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
34437 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
34438 } else {
34439 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
34440 }
34441
34442  if (isset($this->providersByUid[$version['uid'].'-root'])) {
34443 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
34444 }
34445 }
34446 } else {
34447 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
34448 continue;
34449 }
34450
34451
34452  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
34453 $package->setRepository($this);
34454
34455 if ($package instanceof AliasPackage) {
34456 $aliased = $package->getAliasOf();
34457 $aliased->setRepository($this);
34458
34459 $this->providers[$name][$version['uid']] = $aliased;
34460 $this->providers[$name][$version['uid'].'-alias'] = $package;
34461
34462
34463  $this->providersByUid[$version['uid']] = $package;
34464 } else {
34465 $this->providers[$name][$version['uid']] = $package;
34466 $this->providersByUid[$version['uid']] = $package;
34467 }
34468
34469
34470  unset($rootAliasData);
34471
34472 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
34473 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
34474 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
34475 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
34476 }
34477
34478 if (isset($rootAliasData)) {
34479 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
34480 $alias->setRepository($this);
34481
34482 $this->providers[$name][$version['uid'].'-root'] = $alias;
34483 $this->providersByUid[$version['uid'].'-root'] = $alias;
34484 }
34485 }
34486 }
34487 }
34488
34489 $result = $this->providers[$name];
34490
34491
34492  
34493  if ($bypassFilters) {
34494 foreach ($this->providers[$name] as $uid => $provider) {
34495 unset($this->providersByUid[$uid]);
34496 }
34497 unset($this->providers[$name]);
34498 }
34499
34500 return $result;
34501 }
34502
34503
34504
34505
34506 protected function initialize()
34507 {
34508 parent::initialize();
34509
34510 $repoData = $this->loadDataFromServer();
34511
34512 foreach ($repoData as $package) {
34513 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
34514 }
34515 }
34516
34517
34518
34519
34520
34521
34522 public function addPackage(PackageInterface $package)
34523 {
34524 parent::addPackage($package);
34525 $this->configurePackageTransportOptions($package);
34526 }
34527
34528 protected function loadRootServerFile()
34529 {
34530 if (null !== $this->rootData) {
34531 return $this->rootData;
34532 }
34533
34534 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
34535 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
34536 }
34537
34538 $jsonUrlParts = parse_url($this->url);
34539
34540 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
34541 $jsonUrl = $this->url;
34542 } else {
34543 $jsonUrl = $this->url . '/packages.json';
34544 }
34545
34546 $data = $this->fetchFile($jsonUrl, 'packages.json');
34547
34548 if (!empty($data['notify-batch'])) {
34549 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
34550 } elseif (!empty($data['notify'])) {
34551 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
34552 }
34553
34554 if (!empty($data['search'])) {
34555 $this->searchUrl = $this->canonicalizeUrl($data['search']);
34556 }
34557
34558 if (!empty($data['mirrors'])) {
34559 foreach ($data['mirrors'] as $mirror) {
34560 if (!empty($mirror['git-url'])) {
34561 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
34562 }
34563 if (!empty($mirror['hg-url'])) {
34564 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
34565 }
34566 if (!empty($mirror['dist-url'])) {
34567 $this->distMirrors[] = array(
34568 'url' => $this->canonicalizeUrl($mirror['dist-url']),
34569 'preferred' => !empty($mirror['preferred']),
34570 );
34571 }
34572 }
34573 }
34574
34575 if (!empty($data['providers-lazy-url'])) {
34576 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
34577 $this->hasProviders = true;
34578
34579 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
34580 }
34581
34582 if ($this->allowSslDowngrade) {
34583 $this->url = str_replace('https://', 'http://', $this->url);
34584 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
34585 }
34586
34587 if (!empty($data['providers-url'])) {
34588 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
34589 $this->hasProviders = true;
34590 }
34591
34592 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
34593 $this->hasProviders = true;
34594 }
34595
34596
34597  if (preg_match('{^https?://repo\.packagist\.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
34598 $this->url = 'https://repo.packagist.org';
34599 $this->baseUrl = 'https://repo.packagist.org';
34600 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://repo.packagist.org/p/%package%.json');
34601 $this->providersUrl = null;
34602 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
34603 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
34604 $this->providersUrl = null;
34605 }
34606
34607 return $this->rootData = $data;
34608 }
34609
34610 protected function canonicalizeUrl($url)
34611 {
34612 if ('/' === $url[0]) {
34613 if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) {
34614 return $matches[0] . $url;
34615 }
34616
34617 return $this->url;
34618 }
34619
34620 return $url;
34621 }
34622
34623 protected function loadDataFromServer()
34624 {
34625 $data = $this->loadRootServerFile();
34626
34627 return $this->loadIncludes($data);
34628 }
34629
34630 protected function loadProviderListings($data)
34631 {
34632 if (isset($data['providers'])) {
34633 if (!is_array($this->providerListing)) {
34634 $this->providerListing = array();
34635 }
34636 $this->providerListing = array_merge($this->providerListing, $data['providers']);
34637 }
34638
34639 if ($this->providersUrl && isset($data['provider-includes'])) {
34640 $includes = $data['provider-includes'];
34641 foreach ($includes as $include => $metadata) {
34642 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
34643 $cacheKey = str_replace(array('%hash%','$'), '', $include);
34644 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
34645 $includedData = json_decode($this->cache->read($cacheKey), true);
34646 } else {
34647 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
34648 }
34649
34650 $this->loadProviderListings($includedData);
34651 }
34652 }
34653 }
34654
34655 protected function loadIncludes($data)
34656 {
34657 $packages = array();
34658
34659
34660  if (!isset($data['packages']) && !isset($data['includes'])) {
34661 foreach ($data as $pkg) {
34662 foreach ($pkg['versions'] as $metadata) {
34663 $packages[] = $metadata;
34664 }
34665 }
34666
34667 return $packages;
34668 }
34669
34670 if (isset($data['packages'])) {
34671 foreach ($data['packages'] as $package => $versions) {
34672 foreach ($versions as $version => $metadata) {
34673 $packages[] = $metadata;
34674 }
34675 }
34676 }
34677
34678 if (isset($data['includes'])) {
34679 foreach ($data['includes'] as $include => $metadata) {
34680 if ($this->cache->sha1($include) === $metadata['sha1']) {
34681 $includedData = json_decode($this->cache->read($include), true);
34682 } else {
34683 $includedData = $this->fetchFile($include);
34684 }
34685 $packages = array_merge($packages, $this->loadIncludes($includedData));
34686 }
34687 }
34688
34689 return $packages;
34690 }
34691
34692 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
34693 {
34694 try {
34695 if (!isset($data['notification-url'])) {
34696 $data['notification-url'] = $this->notifyUrl;
34697 }
34698
34699 $package = $this->loader->load($data, $class);
34700 if (isset($this->sourceMirrors[$package->getSourceType()])) {
34701 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
34702 }
34703 $package->setDistMirrors($this->distMirrors);
34704 $this->configurePackageTransportOptions($package);
34705
34706 return $package;
34707 } catch (\Exception $e) {
34708 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);
34709 }
34710 }
34711
34712 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
34713 {
34714 if (null === $cacheKey) {
34715 $cacheKey = $filename;
34716 $filename = $this->baseUrl.'/'.$filename;
34717 }
34718
34719
34720  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
34721 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
34722 }
34723
34724 $retries = 3;
34725 while ($retries--) {
34726 try {
34727 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
34728 if ($this->eventDispatcher) {
34729 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
34730 }
34731
34732 $origin = RemoteFilesystem::getOrigin($filename);
34733 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
34734
34735 $json = $rfs->getContents($origin, $filename, false);
34736 if ($sha256 && $sha256 !== hash('sha256', $json)) {
34737
34738  if ($this->allowSslDowngrade) {
34739 $this->url = str_replace('http://', 'https://', $this->url);
34740 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
34741 $filename = str_replace('http://', 'https://', $filename);
34742 }
34743
34744 if ($retries) {
34745 usleep(100000);
34746
34747 continue;
34748 }
34749
34750
34751  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.');
34752 }
34753
34754 $data = JsonFile::parseJson($json, $filename);
34755 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
34756
34757 if ($cacheKey) {
34758 if ($storeLastModifiedTime) {
34759 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
34760 if ($lastModifiedDate) {
34761 $data['last-modified'] = $lastModifiedDate;
34762 $json = json_encode($data);
34763 }
34764 }
34765 $this->cache->write($cacheKey, $json);
34766 }
34767
34768 break;
34769 } catch (\Exception $e) {
34770 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
34771 throw $e;
34772 }
34773
34774 if ($retries) {
34775 usleep(100000);
34776 continue;
34777 }
34778
34779 if ($e instanceof RepositorySecurityException) {
34780 throw $e;
34781 }
34782
34783 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
34784 if (!$this->degradedMode) {
34785 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
34786 $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>');
34787 }
34788 $this->degradedMode = true;
34789 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
34790
34791 break;
34792 }
34793
34794 throw $e;
34795 }
34796 }
34797
34798 return $data;
34799 }
34800
34801 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
34802 {
34803 $retries = 3;
34804 while ($retries--) {
34805 try {
34806 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
34807 if ($this->eventDispatcher) {
34808 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
34809 }
34810
34811 $origin = RemoteFilesystem::getOrigin($filename);
34812 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
34813 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
34814 $json = $rfs->getContents($origin, $filename, false, $options);
34815 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
34816 return true;
34817 }
34818
34819 $data = JsonFile::parseJson($json, $filename);
34820 RemoteFilesystem::outputWarnings($this->io, $this->url, $data);
34821
34822 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
34823 if ($lastModifiedDate) {
34824 $data['last-modified'] = $lastModifiedDate;
34825 $json = json_encode($data);
34826 }
34827 $this->cache->write($cacheKey, $json);
34828
34829 return $data;
34830 } catch (\Exception $e) {
34831 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
34832 throw $e;
34833 }
34834
34835 if ($retries) {
34836 usleep(100000);
34837 continue;
34838 }
34839
34840 if (!$this->degradedMode) {
34841 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
34842 $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>');
34843 }
34844 $this->degradedMode = true;
34845
34846 return true;
34847 }
34848 }
34849 }
34850
34851
34852
34853
34854
34855
34856 private function initializePartialPackages()
34857 {
34858 $rootData = $this->loadRootServerFile();
34859
34860 $this->partialPackagesByName = array();
34861 foreach ($rootData['packages'] as $package => $versions) {
34862 $package = strtolower($package);
34863 foreach ($versions as $version) {
34864 $this->partialPackagesByName[$package][] = $version;
34865 if (!empty($version['provide']) && is_array($version['provide'])) {
34866 foreach ($version['provide'] as $provided => $providedVersion) {
34867 $this->partialPackagesByName[strtolower($provided)][] = $version;
34868 }
34869 }
34870 if (!empty($version['replace']) && is_array($version['replace'])) {
34871 foreach ($version['replace'] as $provided => $providedVersion) {
34872 $this->partialPackagesByName[strtolower($provided)][] = $version;
34873 }
34874 }
34875 }
34876 }
34877
34878
34879  $this->rootData = true;
34880 }
34881 }
34882 <?php
34883
34884
34885
34886
34887
34888
34889
34890
34891
34892
34893
34894 namespace Composer\Repository;
34895
34896 use Composer\Package\PackageInterface;
34897
34898
34899
34900
34901
34902
34903 class CompositeRepository extends BaseRepository
34904 {
34905
34906
34907
34908
34909 private $repositories;
34910
34911
34912
34913
34914
34915 public function __construct(array $repositories)
34916 {
34917 $this->repositories = array();
34918 foreach ($repositories as $repo) {
34919 $this->addRepository($repo);
34920 }
34921 }
34922
34923
34924
34925
34926
34927
34928 public function getRepositories()
34929 {
34930 return $this->repositories;
34931 }
34932
34933
34934
34935
34936 public function hasPackage(PackageInterface $package)
34937 {
34938 foreach ($this->repositories as $repository) {
34939
34940 if ($repository->hasPackage($package)) {
34941 return true;
34942 }
34943 }
34944
34945 return false;
34946 }
34947
34948
34949
34950
34951 public function findPackage($name, $constraint)
34952 {
34953 foreach ($this->repositories as $repository) {
34954
34955 $package = $repository->findPackage($name, $constraint);
34956 if (null !== $package) {
34957 return $package;
34958 }
34959 }
34960
34961 return null;
34962 }
34963
34964
34965
34966
34967 public function findPackages($name, $constraint = null)
34968 {
34969 $packages = array();
34970 foreach ($this->repositories as $repository) {
34971
34972 $packages[] = $repository->findPackages($name, $constraint);
34973 }
34974
34975 return $packages ? call_user_func_array('array_merge', $packages) : array();
34976 }
34977
34978
34979
34980
34981 public function search($query, $mode = 0, $type = null)
34982 {
34983 $matches = array();
34984 foreach ($this->repositories as $repository) {
34985
34986 $matches[] = $repository->search($query, $mode, $type);
34987 }
34988
34989 return $matches ? call_user_func_array('array_merge', $matches) : array();
34990 }
34991
34992
34993
34994
34995 public function getPackages()
34996 {
34997 $packages = array();
34998 foreach ($this->repositories as $repository) {
34999
35000 $packages[] = $repository->getPackages();
35001 }
35002
35003 return $packages ? call_user_func_array('array_merge', $packages) : array();
35004 }
35005
35006
35007
35008
35009 public function removePackage(PackageInterface $package)
35010 {
35011 foreach ($this->repositories as $repository) {
35012
35013 $repository->removePackage($package);
35014 }
35015 }
35016
35017
35018
35019
35020 public function count()
35021 {
35022 $total = 0;
35023 foreach ($this->repositories as $repository) {
35024
35025 $total += $repository->count();
35026 }
35027
35028 return $total;
35029 }
35030
35031
35032
35033
35034
35035 public function addRepository(RepositoryInterface $repository)
35036 {
35037 if ($repository instanceof self) {
35038 foreach ($repository->getRepositories() as $repo) {
35039 $this->addRepository($repo);
35040 }
35041 } else {
35042 $this->repositories[] = $repository;
35043 }
35044 }
35045 }
35046 <?php
35047
35048
35049
35050
35051
35052
35053
35054
35055
35056
35057
35058 namespace Composer\Repository;
35059
35060
35061
35062
35063
35064
35065 interface ConfigurableRepositoryInterface
35066 {
35067 public function getRepoConfig();
35068 }
35069 <?php
35070
35071
35072
35073
35074
35075
35076
35077
35078
35079
35080
35081 namespace Composer\Repository;
35082
35083 use Composer\Json\JsonFile;
35084 use Composer\Package\Loader\ArrayLoader;
35085 use Composer\Package\Dumper\ArrayDumper;
35086
35087
35088
35089
35090
35091
35092
35093 class FilesystemRepository extends WritableArrayRepository
35094 {
35095 private $file;
35096
35097
35098
35099
35100
35101
35102 public function __construct(JsonFile $repositoryFile)
35103 {
35104 parent::__construct();
35105 $this->file = $repositoryFile;
35106 }
35107
35108
35109
35110
35111 protected function initialize()
35112 {
35113 parent::initialize();
35114
35115 if (!$this->file->exists()) {
35116 return;
35117 }
35118
35119 try {
35120 $packages = $this->file->read();
35121
35122
35123  if (isset($packages['packages'])) {
35124 $packages = $packages['packages'];
35125 }
35126
35127 if (!is_array($packages)) {
35128 throw new \UnexpectedValueException('Could not parse package list from the repository');
35129 }
35130 } catch (\Exception $e) {
35131 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
35132 }
35133
35134 $loader = new ArrayLoader(null, true);
35135 foreach ($packages as $packageData) {
35136 $package = $loader->load($packageData);
35137 $this->addPackage($package);
35138 }
35139 }
35140
35141 public function reload()
35142 {
35143 $this->packages = null;
35144 $this->initialize();
35145 }
35146
35147
35148
35149
35150 public function write()
35151 {
35152 $data = array();
35153 $dumper = new ArrayDumper();
35154
35155 foreach ($this->getCanonicalPackages() as $package) {
35156 $data[] = $dumper->dump($package);
35157 }
35158
35159 usort($data, function ($a, $b) {
35160 return strcmp($a['name'], $b['name']);
35161 });
35162
35163 $this->file->write($data);
35164 }
35165 }
35166 <?php
35167
35168
35169
35170
35171
35172
35173
35174
35175
35176
35177
35178 namespace Composer\Repository;
35179
35180
35181
35182
35183
35184
35185
35186
35187 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
35188 {
35189 }
35190 <?php
35191
35192
35193
35194
35195
35196
35197
35198
35199
35200
35201
35202 namespace Composer\Repository;
35203
35204
35205
35206
35207
35208
35209 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
35210 {
35211 }
35212 <?php
35213
35214
35215
35216
35217
35218
35219
35220
35221
35222
35223
35224 namespace Composer\Repository;
35225
35226
35227
35228
35229
35230
35231
35232
35233 interface InstalledRepositoryInterface extends WritableRepositoryInterface
35234 {
35235 }
35236 <?php
35237
35238
35239
35240
35241
35242
35243
35244
35245
35246
35247
35248 namespace Composer\Repository;
35249
35250
35251
35252
35253
35254
35255 class InvalidRepositoryException extends \Exception
35256 {
35257 }
35258 <?php
35259
35260
35261
35262
35263
35264
35265
35266
35267
35268
35269
35270 namespace Composer\Repository;
35271
35272 use Composer\Package\Loader\ArrayLoader;
35273 use Composer\Package\Loader\ValidatingArrayLoader;
35274
35275
35276
35277
35278
35279
35280 class PackageRepository extends ArrayRepository
35281 {
35282 private $config;
35283
35284
35285
35286
35287
35288
35289 public function __construct(array $config)
35290 {
35291 parent::__construct();
35292 $this->config = $config['package'];
35293
35294
35295  if (!is_numeric(key($this->config))) {
35296 $this->config = array($this->config);
35297 }
35298 }
35299
35300
35301
35302
35303 protected function initialize()
35304 {
35305 parent::initialize();
35306
35307 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
35308 foreach ($this->config as $package) {
35309 try {
35310 $package = $loader->load($package);
35311 } catch (\Exception $e) {
35312 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
35313 }
35314
35315 $this->addPackage($package);
35316 }
35317 }
35318 }
35319 <?php
35320
35321
35322
35323
35324
35325
35326
35327
35328
35329
35330
35331 namespace Composer\Repository;
35332
35333 use Composer\Config;
35334 use Composer\IO\IOInterface;
35335 use Composer\Json\JsonFile;
35336 use Composer\Package\Loader\ArrayLoader;
35337 use Composer\Package\Version\VersionGuesser;
35338 use Composer\Package\Version\VersionParser;
35339 use Composer\Util\Platform;
35340 use Composer\Util\ProcessExecutor;
35341 use Composer\Util\Filesystem;
35342
35343
35344
35345
35346
35347
35348
35349
35350
35351
35352
35353
35354
35355
35356
35357
35358
35359
35360
35361
35362
35363
35364
35365
35366
35367
35368
35369
35370
35371
35372
35373
35374
35375
35376
35377
35378 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
35379 {
35380
35381
35382
35383 private $loader;
35384
35385
35386
35387
35388 private $versionGuesser;
35389
35390
35391
35392
35393 private $url;
35394
35395
35396
35397
35398 private $repoConfig;
35399
35400
35401
35402
35403 private $process;
35404
35405
35406
35407
35408 private $options;
35409
35410
35411
35412
35413
35414
35415
35416
35417 public function __construct(array $repoConfig, IOInterface $io, Config $config)
35418 {
35419 if (!isset($repoConfig['url'])) {
35420 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
35421 }
35422
35423 $this->loader = new ArrayLoader(null, true);
35424 $this->url = Platform::expandPath($repoConfig['url']);
35425 $this->process = new ProcessExecutor($io);
35426 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
35427 $this->repoConfig = $repoConfig;
35428 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
35429 if (!isset($this->options['relative'])) {
35430 $filesystem = new Filesystem();
35431 $this->options['relative'] = !$filesystem->isAbsolutePath($this->url);
35432 }
35433
35434 parent::__construct();
35435 }
35436
35437 public function getRepoConfig()
35438 {
35439 return $this->repoConfig;
35440 }
35441
35442
35443
35444
35445
35446
35447 protected function initialize()
35448 {
35449 parent::initialize();
35450
35451 $urlMatches = $this->getUrlMatches();
35452
35453 if (empty($urlMatches)) {
35454 if (preg_match('{[*{}]}', $this->url)) {
35455 $url = $this->url;
35456 while (preg_match('{[*{}]}', $url)) {
35457 $url = dirname($url);
35458 }
35459
35460  if (is_dir($url)) {
35461 return;
35462 }
35463 }
35464
35465 throw new \RuntimeException('The `url` supplied for the path (' . $this->url . ') repository does not exist');
35466 }
35467
35468 foreach ($urlMatches as $url) {
35469 $path = realpath($url) . DIRECTORY_SEPARATOR;
35470 $composerFilePath = $path.'composer.json';
35471
35472 if (!file_exists($composerFilePath)) {
35473 continue;
35474 }
35475
35476 $json = file_get_contents($composerFilePath);
35477 $package = JsonFile::parseJson($json, $composerFilePath);
35478 $package['dist'] = array(
35479 'type' => 'path',
35480 'url' => $url,
35481 'reference' => sha1($json . serialize($this->options)),
35482 );
35483 $package['transport-options'] = $this->options;
35484
35485
35486  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
35487 if (
35488 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
35489 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
35490 && $ref1 === $ref2
35491 ) {
35492 $package['version'] = $rootVersion;
35493 }
35494 }
35495
35496 $output = '';
35497 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
35498 $package['dist']['reference'] = trim($output);
35499 }
35500
35501 if (!isset($package['version'])) {
35502 $versionData = $this->versionGuesser->guessVersion($package, $path);
35503 if (is_array($versionData) && $versionData['pretty_version']) {
35504
35505  if (!empty($versionData['feature_pretty_version'])) {
35506 $package['version'] = $versionData['feature_pretty_version'];
35507 $this->addPackage($this->loader->load($package));
35508 }
35509
35510 $package['version'] = $versionData['pretty_version'];
35511 } else {
35512 $package['version'] = 'dev-master';
35513 }
35514 }
35515
35516 $package = $this->loader->load($package);
35517 $this->addPackage($package);
35518 }
35519 }
35520
35521
35522
35523
35524
35525
35526 private function getUrlMatches()
35527 {
35528 $flags = GLOB_MARK | GLOB_ONLYDIR;
35529
35530 if (defined('GLOB_BRACE')) {
35531 $flags |= GLOB_BRACE;
35532 } elseif (strpos($this->url, '{') !== false || strpos($this->url, '}') !== false) {
35533 throw new \RuntimeException('The operating system does not support GLOB_BRACE which is required for the url '. $this->url);
35534 }
35535
35536
35537  return array_map(function ($val) {
35538 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
35539 }, glob($this->url, $flags));
35540 }
35541 }
35542 <?php
35543
35544
35545
35546
35547
35548
35549
35550
35551
35552
35553
35554 namespace Composer\Repository\Pear;
35555
35556 use Composer\Util\RemoteFilesystem;
35557
35558
35559
35560
35561
35562
35563
35564
35565 abstract class BaseChannelReader
35566 {
35567
35568
35569
35570 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
35571 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
35572 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
35573 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
35574 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
35575 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
35576
35577
35578 private $rfs;
35579
35580 protected function __construct(RemoteFilesystem $rfs)
35581 {
35582 $this->rfs = $rfs;
35583 }
35584
35585
35586
35587
35588
35589
35590
35591
35592
35593 protected function requestContent($origin, $path)
35594 {
35595 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
35596 $content = $this->rfs->getContents($origin, $url, false);
35597 if (!$content) {
35598 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
35599 }
35600
35601 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
35602 }
35603
35604
35605
35606
35607
35608
35609
35610
35611
35612 protected function requestXml($origin, $path)
35613 {
35614
35615  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
35616
35617 if (false === $xml) {
35618 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
35619 }
35620
35621 return $xml;
35622 }
35623 }
35624 <?php
35625
35626
35627
35628
35629
35630
35631
35632
35633
35634
35635
35636 namespace Composer\Repository\Pear;
35637
35638
35639
35640
35641
35642
35643 class ChannelInfo
35644 {
35645 private $name;
35646 private $alias;
35647 private $packages;
35648
35649
35650
35651
35652
35653
35654 public function __construct($name, $alias, array $packages)
35655 {
35656 $this->name = $name;
35657 $this->alias = $alias;
35658 $this->packages = $packages;
35659 }
35660
35661
35662
35663
35664
35665
35666 public function getName()
35667 {
35668 return $this->name;
35669 }
35670
35671
35672
35673
35674
35675
35676 public function getAlias()
35677 {
35678 return $this->alias;
35679 }
35680
35681
35682
35683
35684
35685
35686 public function getPackages()
35687 {
35688 return $this->packages;
35689 }
35690 }
35691 <?php
35692
35693
35694
35695
35696
35697
35698
35699
35700
35701
35702
35703 namespace Composer\Repository\Pear;
35704
35705 use Composer\Util\RemoteFilesystem;
35706
35707
35708
35709
35710
35711
35712
35713
35714 class ChannelReader extends BaseChannelReader
35715 {
35716
35717 private $readerMap;
35718
35719 public function __construct(RemoteFilesystem $rfs)
35720 {
35721 parent::__construct($rfs);
35722
35723 $rest10reader = new ChannelRest10Reader($rfs);
35724 $rest11reader = new ChannelRest11Reader($rfs);
35725
35726 $this->readerMap = array(
35727 'REST1.3' => $rest11reader,
35728 'REST1.2' => $rest11reader,
35729 'REST1.1' => $rest11reader,
35730 'REST1.0' => $rest10reader,
35731 );
35732 }
35733
35734
35735
35736
35737
35738
35739
35740
35741 public function read($url)
35742 {
35743 $xml = $this->requestXml($url, "/channel.xml");
35744
35745 $channelName = (string) $xml->name;
35746 $channelAlias = (string) $xml->suggestedalias;
35747
35748 $supportedVersions = array_keys($this->readerMap);
35749 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
35750 if (!$selectedRestVersion) {
35751 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
35752 }
35753
35754 $reader = $this->readerMap[$selectedRestVersion['version']];
35755 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
35756
35757 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
35758 }
35759
35760
35761
35762
35763
35764
35765
35766
35767 private function selectRestVersion($channelXml, $supportedVersions)
35768 {
35769 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
35770
35771 foreach ($supportedVersions as $version) {
35772 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
35773 $testResult = $channelXml->xpath($xpathTest);
35774
35775 foreach ($testResult as $result) {
35776
35777  $result = (string) $result;
35778 if (preg_match('{^https://}i', $result)) {
35779 return array('version' => $version, 'baseUrl' => $result);
35780 }
35781 }
35782
35783
35784  if (count($testResult) > 0) {
35785 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
35786 }
35787 }
35788
35789 return null;
35790 }
35791 }
35792 <?php
35793
35794
35795
35796
35797
35798
35799
35800
35801
35802
35803
35804 namespace Composer\Repository\Pear;
35805
35806 use Composer\Downloader\TransportException;
35807
35808
35809
35810
35811
35812
35813
35814
35815
35816
35817
35818
35819 class ChannelRest10Reader extends BaseChannelReader
35820 {
35821 private $dependencyReader;
35822
35823 public function __construct($rfs)
35824 {
35825 parent::__construct($rfs);
35826
35827 $this->dependencyReader = new PackageDependencyParser();
35828 }
35829
35830
35831
35832
35833
35834
35835
35836
35837 public function read($baseUrl)
35838 {
35839 return $this->readPackages($baseUrl);
35840 }
35841
35842
35843
35844
35845
35846
35847
35848
35849 private function readPackages($baseUrl)
35850 {
35851 $result = array();
35852
35853 $xmlPath = '/p/packages.xml';
35854 $xml = $this->requestXml($baseUrl, $xmlPath);
35855 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
35856 foreach ($xml->xpath('ns:p') as $node) {
35857 $packageName = (string) $node;
35858 $packageInfo = $this->readPackage($baseUrl, $packageName);
35859 $result[] = $packageInfo;
35860 }
35861
35862 return $result;
35863 }
35864
35865
35866
35867
35868
35869
35870
35871
35872
35873 private function readPackage($baseUrl, $packageName)
35874 {
35875 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
35876 $xml = $this->requestXml($baseUrl, $xmlPath);
35877 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
35878
35879 $channelName = (string) $xml->c;
35880 $packageName = (string) $xml->n;
35881 $license = (string) $xml->l;
35882 $shortDescription = (string) $xml->s;
35883 $description = (string) $xml->d;
35884
35885 return new PackageInfo(
35886 $channelName,
35887 $packageName,
35888 $license,
35889 $shortDescription,
35890 $description,
35891 $this->readPackageReleases($baseUrl, $packageName)
35892 );
35893 }
35894
35895
35896
35897
35898
35899
35900
35901
35902
35903
35904 private function readPackageReleases($baseUrl, $packageName)
35905 {
35906 $result = array();
35907
35908 try {
35909 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
35910 $xml = $this->requestXml($baseUrl, $xmlPath);
35911 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
35912 foreach ($xml->xpath('ns:r') as $node) {
35913 $releaseVersion = (string) $node->v;
35914 $releaseStability = (string) $node->s;
35915
35916 try {
35917 $result[$releaseVersion] = new ReleaseInfo(
35918 $releaseStability,
35919 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
35920 );
35921 } catch (TransportException $exception) {
35922 if ($exception->getCode() != 404) {
35923 throw $exception;
35924 }
35925 }
35926 }
35927 } catch (TransportException $exception) {
35928 if ($exception->getCode() != 404) {
35929 throw $exception;
35930 }
35931 }
35932
35933 return $result;
35934 }
35935
35936
35937
35938
35939
35940
35941
35942
35943
35944
35945 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
35946 {
35947 $dependencyReader = new PackageDependencyParser();
35948
35949 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
35950 $content = $this->requestContent($baseUrl, $depthPath);
35951 $dependencyArray = unserialize($content);
35952
35953 return $dependencyReader->buildDependencyInfo($dependencyArray);
35954 }
35955 }
35956 <?php
35957
35958
35959
35960
35961
35962
35963
35964
35965
35966
35967
35968 namespace Composer\Repository\Pear;
35969
35970
35971
35972
35973
35974
35975
35976
35977
35978
35979 class ChannelRest11Reader extends BaseChannelReader
35980 {
35981 private $dependencyReader;
35982
35983 public function __construct($rfs)
35984 {
35985 parent::__construct($rfs);
35986
35987 $this->dependencyReader = new PackageDependencyParser();
35988 }
35989
35990
35991
35992
35993
35994
35995
35996
35997 public function read($baseUrl)
35998 {
35999 return $this->readChannelPackages($baseUrl);
36000 }
36001
36002
36003
36004
36005
36006
36007
36008
36009 private function readChannelPackages($baseUrl)
36010 {
36011 $result = array();
36012
36013 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
36014 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
36015 foreach ($xml->xpath('ns:c') as $node) {
36016 $categoryName = (string) $node;
36017 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
36018 $result = array_merge($result, $categoryPackages);
36019 }
36020
36021 return $result;
36022 }
36023
36024
36025
36026
36027
36028
36029
36030
36031
36032 private function readCategoryPackages($baseUrl, $categoryName)
36033 {
36034 $result = array();
36035
36036 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
36037 $xml = $this->requestXml($baseUrl, $categoryPath);
36038 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
36039 foreach ($xml->xpath('ns:pi') as $node) {
36040 $packageInfo = $this->parsePackage($node);
36041 $result[] = $packageInfo;
36042 }
36043
36044 return $result;
36045 }
36046
36047
36048
36049
36050
36051
36052
36053 private function parsePackage($packageInfo)
36054 {
36055 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
36056 $channelName = (string) $packageInfo->p->c;
36057 $packageName = (string) $packageInfo->p->n;
36058 $license = (string) $packageInfo->p->l;
36059 $shortDescription = (string) $packageInfo->p->s;
36060 $description = (string) $packageInfo->p->d;
36061
36062 $dependencies = array();
36063 foreach ($packageInfo->xpath('ns:deps') as $node) {
36064 $dependencyVersion = (string) $node->v;
36065 $dependencyArray = unserialize((string) $node->d);
36066
36067 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
36068
36069 $dependencies[$dependencyVersion] = $dependencyInfo;
36070 }
36071
36072 $releases = array();
36073 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
36074 if ($releasesInfo) {
36075 foreach ($releasesInfo as $node) {
36076 $releaseVersion = (string) $node->v;
36077 $releaseStability = (string) $node->s;
36078 $releases[$releaseVersion] = new ReleaseInfo(
36079 $releaseStability,
36080 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
36081 );
36082 }
36083 }
36084
36085 return new PackageInfo(
36086 $channelName,
36087 $packageName,
36088 $license,
36089 $shortDescription,
36090 $description,
36091 $releases
36092 );
36093 }
36094 }
36095 <?php
36096
36097
36098
36099
36100
36101
36102
36103
36104
36105
36106
36107 namespace Composer\Repository\Pear;
36108
36109
36110
36111
36112
36113
36114 class DependencyConstraint
36115 {
36116 private $type;
36117 private $constraint;
36118 private $channelName;
36119 private $packageName;
36120
36121
36122
36123
36124
36125
36126
36127 public function __construct($type, $constraint, $channelName, $packageName)
36128 {
36129 $this->type = $type;
36130 $this->constraint = $constraint;
36131 $this->channelName = $channelName;
36132 $this->packageName = $packageName;
36133 }
36134
36135 public function getChannelName()
36136 {
36137 return $this->channelName;
36138 }
36139
36140 public function getConstraint()
36141 {
36142 return $this->constraint;
36143 }
36144
36145 public function getPackageName()
36146 {
36147 return $this->packageName;
36148 }
36149
36150 public function getType()
36151 {
36152 return $this->type;
36153 }
36154 }
36155 <?php
36156
36157
36158
36159
36160
36161
36162
36163
36164
36165
36166
36167 namespace Composer\Repository\Pear;
36168
36169
36170
36171
36172
36173
36174 class DependencyInfo
36175 {
36176 private $requires;
36177 private $optionals;
36178
36179
36180
36181
36182
36183 public function __construct($requires, $optionals)
36184 {
36185 $this->requires = $requires;
36186 $this->optionals = $optionals;
36187 }
36188
36189
36190
36191
36192 public function getRequires()
36193 {
36194 return $this->requires;
36195 }
36196
36197
36198
36199
36200 public function getOptionals()
36201 {
36202 return $this->optionals;
36203 }
36204 }
36205 <?php
36206
36207
36208
36209
36210
36211
36212
36213
36214
36215
36216
36217 namespace Composer\Repository\Pear;
36218
36219
36220
36221
36222
36223
36224 class PackageDependencyParser
36225 {
36226
36227
36228
36229
36230
36231
36232 public function buildDependencyInfo($depArray)
36233 {
36234 if (!is_array($depArray)) {
36235 return new DependencyInfo(array(), array());
36236 }
36237 if (!$this->isHash($depArray)) {
36238 return new DependencyInfo($this->buildDependency10Info($depArray), array());
36239 }
36240
36241 return $this->buildDependency20Info($depArray);
36242 }
36243
36244
36245
36246
36247
36248
36249
36250
36251
36252
36253
36254
36255
36256 private function buildDependency10Info($depArray)
36257 {
36258 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
36259
36260 $result = array();
36261
36262 foreach ($depArray as $depItem) {
36263 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
36264
36265  continue;
36266 }
36267
36268 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
36269 ? 'optional'
36270 : 'required';
36271 $depType = 'not' == $depItem['rel']
36272 ? 'conflicts'
36273 : $depType;
36274
36275 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
36276
36277
36278  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
36279 ? '*'
36280 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
36281
36282 switch ($depItem['type']) {
36283 case 'php':
36284 $depChannelName = 'php';
36285 $depPackageName = '';
36286 break;
36287 case 'pkg':
36288 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
36289 $depPackageName = $depItem['name'];
36290 break;
36291 case 'ext':
36292 $depChannelName = 'ext';
36293 $depPackageName = $depItem['name'];
36294 break;
36295 case 'os':
36296 case 'sapi':
36297 $depChannelName = '';
36298 $depPackageName = '';
36299 break;
36300 default:
36301 $depChannelName = '';
36302 $depPackageName = '';
36303 break;
36304 }
36305
36306 if ('' != $depChannelName) {
36307 $result[] = new DependencyConstraint(
36308 $depType,
36309 $depVersionConstraint,
36310 $depChannelName,
36311 $depPackageName
36312 );
36313 }
36314 }
36315
36316 return $result;
36317 }
36318
36319
36320
36321
36322
36323
36324
36325 private function buildDependency20Info($depArray)
36326 {
36327 $result = array();
36328 $optionals = array();
36329 $defaultOptionals = array();
36330 foreach ($depArray as $depType => $depTypeGroup) {
36331 if (!is_array($depTypeGroup)) {
36332 continue;
36333 }
36334 if ('required' == $depType || 'optional' == $depType) {
36335 foreach ($depTypeGroup as $depItemType => $depItem) {
36336 switch ($depItemType) {
36337 case 'php':
36338 $result[] = new DependencyConstraint(
36339 $depType,
36340 $this->parse20VersionConstraint($depItem),
36341 'php',
36342 ''
36343 );
36344 break;
36345 case 'package':
36346 $deps = $this->buildDepPackageConstraints($depItem, $depType);
36347 $result = array_merge($result, $deps);
36348 break;
36349 case 'extension':
36350 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
36351 $result = array_merge($result, $deps);
36352 break;
36353 case 'subpackage':
36354 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
36355 $defaultOptionals += $deps;
36356 break;
36357 case 'os':
36358 case 'pearinstaller':
36359 break;
36360 default:
36361 break;
36362 }
36363 }
36364 } elseif ('group' == $depType) {
36365 if ($this->isHash($depTypeGroup)) {
36366 $depTypeGroup = array($depTypeGroup);
36367 }
36368
36369 foreach ($depTypeGroup as $depItem) {
36370 $groupName = $depItem['attribs']['name'];
36371 if (!isset($optionals[$groupName])) {
36372 $optionals[$groupName] = array();
36373 }
36374
36375 if (isset($depItem['subpackage'])) {
36376 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
36377 } else {
36378 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
36379 }
36380 }
36381 }
36382 }
36383
36384 if (count($defaultOptionals) > 0) {
36385 $optionals['*'] = $defaultOptionals;
36386 }
36387
36388 return new DependencyInfo($result, $optionals);
36389 }
36390
36391
36392
36393
36394
36395
36396
36397
36398 private function buildDepExtensionConstraints($depItem, $depType)
36399 {
36400 if ($this->isHash($depItem)) {
36401 $depItem = array($depItem);
36402 }
36403
36404 $result = array();
36405 foreach ($depItem as $subDepItem) {
36406 $depChannelName = 'ext';
36407 $depPackageName = $subDepItem['name'];
36408 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
36409
36410 $result[] = new DependencyConstraint(
36411 $depType,
36412 $depVersionConstraint,
36413 $depChannelName,
36414 $depPackageName
36415 );
36416 }
36417
36418 return $result;
36419 }
36420
36421
36422
36423
36424
36425
36426
36427
36428 private function buildDepPackageConstraints($depItem, $depType)
36429 {
36430 if ($this->isHash($depItem)) {
36431 $depItem = array($depItem);
36432 }
36433
36434 $result = array();
36435 foreach ($depItem as $subDepItem) {
36436 if (!array_key_exists('channel', $subDepItem)) {
36437 $subDepItem['channel'] = $subDepItem['uri'];
36438 }
36439 $depChannelName = $subDepItem['channel'];
36440 $depPackageName = $subDepItem['name'];
36441 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
36442 if (isset($subDepItem['conflicts'])) {
36443 $depType = 'conflicts';
36444 }
36445
36446 $result[] = new DependencyConstraint(
36447 $depType,
36448 $depVersionConstraint,
36449 $depChannelName,
36450 $depPackageName
36451 );
36452 }
36453
36454 return $result;
36455 }
36456
36457
36458
36459
36460
36461
36462
36463 private function parse20VersionConstraint(array $data)
36464 {
36465 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
36466
36467 $versions = array();
36468 $values = array_intersect_key($data, $dep20toOperatorMap);
36469 if (0 == count($values)) {
36470 return '*';
36471 }
36472 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
36473 $versions[] = '>' . $this->parseVersion($values['min']);
36474 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
36475 $versions[] = '<' . $this->parseVersion($values['max']);
36476 } else {
36477 foreach ($values as $op => $version) {
36478 if ('exclude' == $op && is_array($version)) {
36479 foreach ($version as $versionPart) {
36480 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
36481 }
36482 } else {
36483 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
36484 }
36485 }
36486 }
36487
36488 return implode(',', $versions);
36489 }
36490
36491
36492
36493
36494
36495
36496
36497 private function parseVersion($version)
36498 {
36499 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
36500 $version = $matches[1]
36501 .(!empty($matches[2]) ? $matches[2] : '.0')
36502 .(!empty($matches[3]) ? $matches[3] : '.0')
36503 .(!empty($matches[4]) ? $matches[4] : '.0');
36504
36505 return $version;
36506 }
36507
36508 return null;
36509 }
36510
36511
36512
36513
36514
36515
36516
36517 private function isHash(array $array)
36518 {
36519 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
36520 }
36521 }
36522 <?php
36523
36524
36525
36526
36527
36528
36529
36530
36531
36532
36533
36534 namespace Composer\Repository\Pear;
36535
36536
36537
36538
36539
36540
36541 class PackageInfo
36542 {
36543 private $channelName;
36544 private $packageName;
36545 private $license;
36546 private $shortDescription;
36547 private $description;
36548 private $releases;
36549
36550
36551
36552
36553
36554
36555
36556
36557
36558 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
36559 {
36560 $this->channelName = $channelName;
36561 $this->packageName = $packageName;
36562 $this->license = $license;
36563 $this->shortDescription = $shortDescription;
36564 $this->description = $description;
36565 $this->releases = $releases;
36566 }
36567
36568
36569
36570
36571 public function getChannelName()
36572 {
36573 return $this->channelName;
36574 }
36575
36576
36577
36578
36579 public function getPackageName()
36580 {
36581 return $this->packageName;
36582 }
36583
36584
36585
36586
36587 public function getDescription()
36588 {
36589 return $this->description;
36590 }
36591
36592
36593
36594
36595 public function getShortDescription()
36596 {
36597 return $this->shortDescription;
36598 }
36599
36600
36601
36602
36603 public function getLicense()
36604 {
36605 return $this->license;
36606 }
36607
36608
36609
36610
36611 public function getReleases()
36612 {
36613 return $this->releases;
36614 }
36615 }
36616 <?php
36617
36618
36619
36620
36621
36622
36623
36624
36625
36626
36627
36628 namespace Composer\Repository\Pear;
36629
36630
36631
36632
36633
36634
36635 class ReleaseInfo
36636 {
36637 private $stability;
36638 private $dependencyInfo;
36639
36640
36641
36642
36643
36644 public function __construct($stability, $dependencyInfo)
36645 {
36646 $this->stability = $stability;
36647 $this->dependencyInfo = $dependencyInfo;
36648 }
36649
36650
36651
36652
36653 public function getDependencyInfo()
36654 {
36655 return $this->dependencyInfo;
36656 }
36657
36658
36659
36660
36661 public function getStability()
36662 {
36663 return $this->stability;
36664 }
36665 }
36666 <?php
36667
36668
36669
36670
36671
36672
36673
36674
36675
36676
36677
36678 namespace Composer\Repository;
36679
36680 use Composer\IO\IOInterface;
36681 use Composer\Semver\VersionParser as SemverVersionParser;
36682 use Composer\Package\Version\VersionParser;
36683 use Composer\Repository\Pear\ChannelReader;
36684 use Composer\Package\CompletePackage;
36685 use Composer\Repository\Pear\ChannelInfo;
36686 use Composer\EventDispatcher\EventDispatcher;
36687 use Composer\Package\Link;
36688 use Composer\Semver\Constraint\Constraint;
36689 use Composer\Util\RemoteFilesystem;
36690 use Composer\Config;
36691 use Composer\Factory;
36692
36693
36694
36695
36696
36697
36698
36699
36700
36701
36702 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
36703 {
36704 private $url;
36705 private $io;
36706 private $rfs;
36707 private $versionParser;
36708 private $repoConfig;
36709
36710
36711
36712
36713 private $vendorAlias;
36714
36715 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
36716 {
36717 parent::__construct();
36718 if (!preg_match('{^https?://}', $repoConfig['url'])) {
36719 $repoConfig['url'] = 'http://'.$repoConfig['url'];
36720 }
36721
36722 $urlBits = parse_url($repoConfig['url']);
36723 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
36724 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
36725 }
36726
36727 $this->url = rtrim($repoConfig['url'], '/');
36728 $this->io = $io;
36729 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
36730 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
36731 $this->versionParser = new VersionParser();
36732 $this->repoConfig = $repoConfig;
36733 }
36734
36735 public function getRepoConfig()
36736 {
36737 return $this->repoConfig;
36738 }
36739
36740 protected function initialize()
36741 {
36742 parent::initialize();
36743
36744 $this->io->writeError('Initializing PEAR repository '.$this->url);
36745
36746 $reader = new ChannelReader($this->rfs);
36747 try {
36748 $channelInfo = $reader->read($this->url);
36749 } catch (\Exception $e) {
36750 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
36751
36752 return;
36753 }
36754 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
36755 foreach ($packages as $package) {
36756 $this->addPackage($package);
36757 }
36758 }
36759
36760
36761
36762
36763
36764
36765
36766
36767 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
36768 {
36769 $result = array();
36770 foreach ($channelInfo->getPackages() as $packageDefinition) {
36771 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
36772 try {
36773 $normalizedVersion = $versionParser->normalize($version);
36774 } catch (\UnexpectedValueException $e) {
36775 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
36776 continue;
36777 }
36778
36779 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
36780
36781
36782  
36783  $urlBits = parse_url($this->url);
36784 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
36785 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
36786
36787 $requires = array();
36788 $suggests = array();
36789 $conflicts = array();
36790 $replaces = array();
36791
36792
36793  
36794  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
36795 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
36796 $aliasConstraint = new Constraint('==', $normalizedVersion);
36797 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
36798 }
36799
36800
36801  if (!empty($this->vendorAlias)
36802 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
36803 ) {
36804 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
36805 $aliasConstraint = new Constraint('==', $normalizedVersion);
36806 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
36807 }
36808
36809 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
36810 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
36811 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
36812 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
36813 switch ($dependencyConstraint->getType()) {
36814 case 'required':
36815 $requires[] = $link;
36816 break;
36817 case 'conflicts':
36818 $conflicts[] = $link;
36819 break;
36820 case 'replaces':
36821 $replaces[] = $link;
36822 break;
36823 }
36824 }
36825
36826 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
36827 foreach ($dependencyConstraints as $dependencyConstraint) {
36828 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
36829 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
36830 }
36831 }
36832
36833 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
36834 $package->setType('pear-library');
36835 $package->setDescription($packageDefinition->getDescription());
36836 $package->setLicense(array($packageDefinition->getLicense()));
36837 $package->setDistType('file');
36838 $package->setDistUrl($distUrl);
36839 $package->setAutoload(array('classmap' => array('')));
36840 $package->setIncludePaths(array('/'));
36841 $package->setRequires($requires);
36842 $package->setConflicts($conflicts);
36843 $package->setSuggests($suggests);
36844 $package->setReplaces($replaces);
36845 $result[] = $package;
36846 }
36847 }
36848
36849 return $result;
36850 }
36851
36852 private function buildComposerPackageName($channelName, $packageName)
36853 {
36854 if ('php' === $channelName) {
36855 return "php";
36856 }
36857 if ('ext' === $channelName) {
36858 return "ext-{$packageName}";
36859 }
36860
36861 return "pear-{$channelName}/{$packageName}";
36862 }
36863 }
36864 <?php
36865
36866
36867
36868
36869
36870
36871
36872
36873
36874
36875
36876 namespace Composer\Repository;
36877
36878 use Composer\Composer;
36879 use Composer\Package\CompletePackage;
36880 use Composer\Package\PackageInterface;
36881 use Composer\Package\Version\VersionParser;
36882 use Composer\Plugin\PluginInterface;
36883 use Composer\Util\ProcessExecutor;
36884 use Composer\Util\Silencer;
36885 use Composer\Util\Platform;
36886 use Composer\XdebugHandler\XdebugHandler;
36887 use Symfony\Component\Process\ExecutableFinder;
36888
36889
36890
36891
36892 class PlatformRepository extends ArrayRepository
36893 {
36894 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-(?:plugin|runtime)-api)$}iD';
36895
36896 private $versionParser;
36897
36898
36899
36900
36901
36902
36903
36904
36905 private $overrides = array();
36906
36907 private $process;
36908
36909 public function __construct(array $packages = array(), array $overrides = array(), ProcessExecutor $process = null)
36910 {
36911 $this->process = $process === null ? (new ProcessExecutor()) : $process;
36912 foreach ($overrides as $name => $version) {
36913 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
36914 }
36915 parent::__construct($packages);
36916 }
36917
36918 protected function initialize()
36919 {
36920 parent::initialize();
36921
36922 $this->versionParser = new VersionParser();
36923
36924
36925  
36926  foreach ($this->overrides as $override) {
36927
36928  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
36929 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
36930 }
36931
36932 $this->addOverriddenPackage($override);
36933 }
36934
36935 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
36936 $version = $this->versionParser->normalize($prettyVersion);
36937 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
36938 $composerPluginApi->setDescription('The Composer Plugin API');
36939 $this->addPackage($composerPluginApi);
36940
36941 $prettyVersion = Composer::RUNTIME_API_VERSION;
36942 $version = $this->versionParser->normalize($prettyVersion);
36943 $composerRuntimeApi = new CompletePackage('composer-runtime-api', $version, $prettyVersion);
36944 $composerRuntimeApi->setDescription('The Composer Runtime API');
36945 $this->addPackage($composerRuntimeApi);
36946
36947 try {
36948 $prettyVersion = PHP_VERSION;
36949 $version = $this->versionParser->normalize($prettyVersion);
36950 } catch (\UnexpectedValueException $e) {
36951 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
36952 $version = $this->versionParser->normalize($prettyVersion);
36953 }
36954
36955 $php = new CompletePackage('php', $version, $prettyVersion);
36956 $php->setDescription('The PHP interpreter');
36957 $this->addPackage($php);
36958
36959 if (PHP_DEBUG) {
36960 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
36961 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
36962 $this->addPackage($phpdebug);
36963 }
36964
36965 if (defined('PHP_ZTS') && PHP_ZTS) {
36966 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
36967 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
36968 $this->addPackage($phpzts);
36969 }
36970
36971 if (PHP_INT_SIZE === 8) {
36972 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
36973 $php64->setDescription('The PHP interpreter, 64bit');
36974 $this->addPackage($php64);
36975 }
36976
36977
36978  
36979  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
36980 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
36981 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
36982 $this->addPackage($phpIpv6);
36983 }
36984
36985 $loadedExtensions = get_loaded_extensions();
36986
36987
36988  foreach ($loadedExtensions as $name) {
36989 if (in_array($name, array('standard', 'Core'))) {
36990 continue;
36991 }
36992
36993 $reflExt = new \ReflectionExtension($name);
36994 $prettyVersion = $reflExt->getVersion();
36995 $this->addExtension($name, $prettyVersion);
36996 }
36997
36998
36999  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = XdebugHandler::getSkippedVersion())) {
37000 $this->addExtension('xdebug', $prettyVersion);
37001 }
37002
37003
37004  
37005  
37006  foreach ($loadedExtensions as $name) {
37007 $prettyVersion = null;
37008 $description = 'The '.$name.' PHP library';
37009 switch ($name) {
37010 case 'curl':
37011 $curlVersion = curl_version();
37012 $prettyVersion = $curlVersion['version'];
37013 break;
37014
37015 case 'iconv':
37016 $prettyVersion = ICONV_VERSION;
37017 break;
37018
37019 case 'intl':
37020 $name = 'ICU';
37021 if (defined('INTL_ICU_VERSION')) {
37022 $prettyVersion = INTL_ICU_VERSION;
37023 } else {
37024 $reflector = new \ReflectionExtension('intl');
37025
37026 ob_start();
37027 $reflector->info();
37028 $output = ob_get_clean();
37029
37030 preg_match('/^ICU version => (.*)$/m', $output, $matches);
37031 $prettyVersion = $matches[1];
37032 }
37033
37034 break;
37035
37036 case 'imagick':
37037 $imagick = new \Imagick();
37038 $imageMagickVersion = $imagick->getVersion();
37039
37040  
37041  preg_match('/^ImageMagick ([\d.]+)(?:-(\d+))?/', $imageMagickVersion['versionString'], $matches);
37042 if (isset($matches[2])) {
37043 $prettyVersion = "{$matches[1]}.{$matches[2]}";
37044 } else {
37045 $prettyVersion = $matches[1];
37046 }
37047 break;
37048
37049 case 'libxml':
37050 $prettyVersion = LIBXML_DOTTED_VERSION;
37051 break;
37052
37053 case 'openssl':
37054 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
37055 if (empty($match[2])) {
37056 return $match[1];
37057 }
37058
37059
37060  
37061
37062 if (!preg_match('{^z*[a-z]$}', $match[2])) {
37063
37064  return 0;
37065 }
37066
37067 $len = strlen($match[2]);
37068 $patchVersion = ($len - 1) * 26; 
37069  $patchVersion += ord($match[2][$len - 1]) - 96;
37070
37071 return $match[1].'.'.$patchVersion;
37072 }, OPENSSL_VERSION_TEXT);
37073
37074 $description = OPENSSL_VERSION_TEXT;
37075 break;
37076
37077 case 'pcre':
37078 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
37079 break;
37080
37081 case 'uuid':
37082 $prettyVersion = phpversion('uuid');
37083 break;
37084
37085 case 'xsl':
37086 $prettyVersion = LIBXSLT_DOTTED_VERSION;
37087 break;
37088
37089 default:
37090
37091  continue 2;
37092 }
37093
37094 try {
37095 $version = $this->versionParser->normalize($prettyVersion);
37096 } catch (\UnexpectedValueException $e) {
37097 continue;
37098 }
37099
37100 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
37101 $lib->setDescription($description);
37102 $this->addPackage($lib);
37103 }
37104
37105 $hhvmVersion = defined('HHVM_VERSION') ? HHVM_VERSION : null;
37106 if ($hhvmVersion === null && !Platform::isWindows()) {
37107 $finder = new ExecutableFinder();
37108 $hhvm = $finder->find('hhvm');
37109 if ($hhvm !== null) {
37110 $exitCode = $this->process->execute(
37111 ProcessExecutor::escape($hhvm).
37112 ' --php -d hhvm.jit=0 -r "echo HHVM_VERSION;" 2>/dev/null',
37113 $hhvmVersion
37114 );
37115 if ($exitCode !== 0) {
37116 $hhvmVersion = null;
37117 }
37118 }
37119 }
37120 if ($hhvmVersion) {
37121 try {
37122 $prettyVersion = $hhvmVersion;
37123 $version = $this->versionParser->normalize($prettyVersion);
37124 } catch (\UnexpectedValueException $e) {
37125 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $hhvmVersion);
37126 $version = $this->versionParser->normalize($prettyVersion);
37127 }
37128
37129 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
37130 $hhvm->setDescription('The HHVM Runtime (64bit)');
37131 $this->addPackage($hhvm);
37132 }
37133 }
37134
37135
37136
37137
37138 public function addPackage(PackageInterface $package)
37139 {
37140
37141  if (isset($this->overrides[$package->getName()])) {
37142 $overrider = $this->findPackage($package->getName(), '*');
37143 if ($package->getVersion() === $overrider->getVersion()) {
37144 $actualText = 'same as actual';
37145 } else {
37146 $actualText = 'actual: '.$package->getPrettyVersion();
37147 }
37148 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
37149
37150 return;
37151 }
37152
37153
37154  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
37155 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
37156 if ($package->getVersion() === $overrider->getVersion()) {
37157 $actualText = 'same as actual';
37158 } else {
37159 $actualText = 'actual: '.$package->getPrettyVersion();
37160 }
37161 $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
37162
37163 return;
37164 }
37165
37166 parent::addPackage($package);
37167 }
37168
37169 private function addOverriddenPackage(array $override, $name = null)
37170 {
37171 $version = $this->versionParser->normalize($override['version']);
37172 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
37173 $package->setDescription('Package overridden via config.platform');
37174 $package->setExtra(array('config.platform' => true));
37175 parent::addPackage($package);
37176
37177 return $package;
37178 }
37179
37180
37181
37182
37183
37184
37185
37186 private function addExtension($name, $prettyVersion)
37187 {
37188 $extraDescription = null;
37189
37190 try {
37191 $version = $this->versionParser->normalize($prettyVersion);
37192 } catch (\UnexpectedValueException $e) {
37193 $extraDescription = ' (actual version: '.$prettyVersion.')';
37194 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
37195 $prettyVersion = $match[1];
37196 } else {
37197 $prettyVersion = '0';
37198 }
37199 $version = $this->versionParser->normalize($prettyVersion);
37200 }
37201
37202 $packageName = $this->buildPackageName($name);
37203 $ext = new CompletePackage($packageName, $version, $prettyVersion);
37204 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
37205 $this->addPackage($ext);
37206 }
37207
37208 private function buildPackageName($name)
37209 {
37210 return 'ext-' . str_replace(' ', '-', $name);
37211 }
37212 }
37213 <?php
37214
37215
37216
37217
37218
37219
37220
37221
37222
37223
37224
37225 namespace Composer\Repository;
37226
37227 use Composer\Factory;
37228 use Composer\IO\IOInterface;
37229 use Composer\Config;
37230 use Composer\EventDispatcher\EventDispatcher;
37231 use Composer\Util\RemoteFilesystem;
37232 use Composer\Json\JsonFile;
37233
37234
37235
37236
37237 class RepositoryFactory
37238 {
37239
37240
37241
37242
37243
37244
37245
37246 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
37247 {
37248 if (0 === strpos($repository, 'http')) {
37249 $repoConfig = array('type' => 'composer', 'url' => $repository);
37250 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
37251 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
37252 $data = $json->read();
37253 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
37254 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
37255 } elseif ($allowFilesystem) {
37256 $repoConfig = array('type' => 'filesystem', 'json' => $json);
37257 } else {
37258 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
37259 }
37260 } elseif ('{' === substr($repository, 0, 1)) {
37261
37262  $repoConfig = JsonFile::parseJson($repository);
37263 } else {
37264 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
37265 }
37266
37267 return $repoConfig;
37268 }
37269
37270
37271
37272
37273
37274
37275
37276
37277 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
37278 {
37279 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
37280
37281 return static::createRepo($io, $config, $repoConfig);
37282 }
37283
37284
37285
37286
37287
37288
37289
37290 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
37291 {
37292 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
37293 $repos = static::createRepos($rm, array($repoConfig));
37294
37295 return reset($repos);
37296 }
37297
37298
37299
37300
37301
37302
37303
37304 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
37305 {
37306 if (!$config) {
37307 $config = Factory::createConfig($io);
37308 }
37309 if ($io) {
37310 $io->loadConfiguration($config);
37311 }
37312 if (!$rm) {
37313 if (!$io) {
37314 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
37315 }
37316 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
37317 }
37318
37319 return static::createRepos($rm, $config->getRepositories());
37320 }
37321
37322
37323
37324
37325
37326
37327
37328
37329 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
37330 {
37331 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
37332 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
37333 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
37334 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
37335 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
37336 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
37337 $rm->setRepositoryClass('git-bitbucket', 'Composer\Repository\VcsRepository');
37338 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
37339 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
37340 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
37341 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
37342 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
37343 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
37344 $rm->setRepositoryClass('hg-bitbucket', 'Composer\Repository\VcsRepository');
37345 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
37346 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
37347
37348 return $rm;
37349 }
37350
37351
37352
37353
37354 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
37355 {
37356 $repos = array();
37357
37358 foreach ($repoConfigs as $index => $repo) {
37359 if (is_string($repo)) {
37360 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
37361 }
37362 if (!is_array($repo)) {
37363 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
37364 }
37365 if (!isset($repo['type'])) {
37366 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
37367 }
37368
37369 $name = self::generateRepositoryName($index, $repo, $repos);
37370 if ($repo['type'] === 'filesystem') {
37371 $repos[$name] = new FilesystemRepository($repo['json']);
37372 } else {
37373 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
37374 }
37375 }
37376
37377 return $repos;
37378 }
37379
37380 public static function generateRepositoryName($index, array $repo, array $existingRepos)
37381 {
37382 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
37383 while (isset($existingRepos[$name])) {
37384 $name .= '2';
37385 }
37386
37387 return $name;
37388 }
37389 }
37390 <?php
37391
37392
37393
37394
37395
37396
37397
37398
37399
37400
37401
37402 namespace Composer\Repository;
37403
37404 use Composer\Package\PackageInterface;
37405
37406
37407
37408
37409
37410
37411
37412
37413 interface RepositoryInterface extends \Countable
37414 {
37415 const SEARCH_FULLTEXT = 0;
37416 const SEARCH_NAME = 1;
37417
37418
37419
37420
37421
37422
37423
37424
37425 public function hasPackage(PackageInterface $package);
37426
37427
37428
37429
37430
37431
37432
37433
37434
37435 public function findPackage($name, $constraint);
37436
37437
37438
37439
37440
37441
37442
37443
37444
37445 public function findPackages($name, $constraint = null);
37446
37447
37448
37449
37450
37451
37452 public function getPackages();
37453
37454
37455
37456
37457
37458
37459
37460
37461
37462 public function search($query, $mode = 0);
37463 }
37464 <?php
37465
37466
37467
37468
37469
37470
37471
37472
37473
37474
37475
37476 namespace Composer\Repository;
37477
37478 use Composer\IO\IOInterface;
37479 use Composer\Config;
37480 use Composer\EventDispatcher\EventDispatcher;
37481 use Composer\Package\PackageInterface;
37482 use Composer\Util\RemoteFilesystem;
37483
37484
37485
37486
37487
37488
37489
37490
37491 class RepositoryManager
37492 {
37493 private $localRepository;
37494 private $repositories = array();
37495 private $repositoryClasses = array();
37496 private $io;
37497 private $config;
37498 private $eventDispatcher;
37499 private $rfs;
37500
37501 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
37502 {
37503 $this->io = $io;
37504 $this->config = $config;
37505 $this->eventDispatcher = $eventDispatcher;
37506 $this->rfs = $rfs;
37507 }
37508
37509
37510
37511
37512
37513
37514
37515
37516
37517 public function findPackage($name, $constraint)
37518 {
37519 foreach ($this->repositories as $repository) {
37520
37521 if ($package = $repository->findPackage($name, $constraint)) {
37522 return $package;
37523 }
37524 }
37525
37526 return null;
37527 }
37528
37529
37530
37531
37532
37533
37534
37535
37536
37537 public function findPackages($name, $constraint)
37538 {
37539 $packages = array();
37540
37541 foreach ($this->getRepositories() as $repository) {
37542 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
37543 }
37544
37545 return $packages;
37546 }
37547
37548
37549
37550
37551
37552
37553 public function addRepository(RepositoryInterface $repository)
37554 {
37555 $this->repositories[] = $repository;
37556 }
37557
37558
37559
37560
37561
37562
37563
37564
37565 public function prependRepository(RepositoryInterface $repository)
37566 {
37567 array_unshift($this->repositories, $repository);
37568 }
37569
37570
37571
37572
37573
37574
37575
37576
37577
37578
37579 public function createRepository($type, $config, $name = null)
37580 {
37581 if (!isset($this->repositoryClasses[$type])) {
37582 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
37583 }
37584
37585 if (isset($config['packagist']) && false === $config['packagist']) {
37586 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
37587 }
37588
37589 $class = $this->repositoryClasses[$type];
37590
37591 $reflMethod = new \ReflectionMethod($class, '__construct');
37592 $params = $reflMethod->getParameters();
37593 if (isset($params[4])) {
37594 $paramType = null;
37595 if (\PHP_VERSION_ID >= 70000) {
37596 $reflectionType = $params[4]->getType();
37597 if ($reflectionType) {
37598 $paramType = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string)$reflectionType;
37599 }
37600 } else {
37601 $paramType = $params[4]->getClass() ? $params[4]->getClass()->getName() : null;
37602 }
37603
37604 if ($paramType === 'Composer\Util\RemoteFilesystem') {
37605 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
37606 }
37607 }
37608
37609 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
37610 }
37611
37612
37613
37614
37615
37616
37617
37618 public function setRepositoryClass($type, $class)
37619 {
37620 $this->repositoryClasses[$type] = $class;
37621 }
37622
37623
37624
37625
37626
37627
37628 public function getRepositories()
37629 {
37630 return $this->repositories;
37631 }
37632
37633
37634
37635
37636
37637
37638 public function setLocalRepository(WritableRepositoryInterface $repository)
37639 {
37640 $this->localRepository = $repository;
37641 }
37642
37643
37644
37645
37646
37647
37648 public function getLocalRepository()
37649 {
37650 return $this->localRepository;
37651 }
37652 }
37653 <?php
37654
37655
37656
37657
37658
37659
37660
37661
37662
37663
37664
37665 namespace Composer\Repository;
37666
37667
37668
37669
37670
37671
37672 class RepositorySecurityException extends \Exception
37673 {
37674 }
37675 <?php
37676
37677
37678
37679
37680
37681
37682
37683
37684
37685
37686
37687 namespace Composer\Repository\Vcs;
37688
37689 use Composer\Cache;
37690 use Composer\Downloader\TransportException;
37691 use Composer\Json\JsonFile;
37692 use Composer\Util\Bitbucket;
37693
37694 abstract class BitbucketDriver extends VcsDriver
37695 {
37696
37697 protected $cache;
37698 protected $owner;
37699 protected $repository;
37700 protected $hasIssues;
37701 protected $rootIdentifier;
37702 protected $tags;
37703 protected $branches;
37704 protected $infoCache = array();
37705 protected $branchesUrl = '';
37706 protected $tagsUrl = '';
37707 protected $homeUrl = '';
37708 protected $website = '';
37709 protected $cloneHttpsUrl = '';
37710
37711
37712
37713
37714 protected $fallbackDriver;
37715
37716 protected $vcsType;
37717
37718
37719
37720
37721 public function initialize()
37722 {
37723 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#i', $this->url, $match);
37724 $this->owner = $match[1];
37725 $this->repository = $match[2];
37726 $this->originUrl = 'bitbucket.org';
37727 $this->cache = new Cache(
37728 $this->io,
37729 implode('/', array(
37730 $this->config->get('cache-repo-dir'),
37731 $this->originUrl,
37732 $this->owner,
37733 $this->repository,
37734 ))
37735 );
37736 }
37737
37738
37739
37740
37741 public function getUrl()
37742 {
37743 if ($this->fallbackDriver) {
37744 return $this->fallbackDriver->getUrl();
37745 }
37746
37747 return $this->cloneHttpsUrl;
37748 }
37749
37750
37751
37752
37753
37754
37755
37756 protected function getRepoData()
37757 {
37758 $resource = sprintf(
37759 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
37760 $this->owner,
37761 $this->repository,
37762 http_build_query(
37763 array('fields' => '-project,-owner'),
37764 null,
37765 '&'
37766 )
37767 );
37768
37769 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
37770 if ($this->fallbackDriver) {
37771 return false;
37772 }
37773 $this->parseCloneUrls($repoData['links']['clone']);
37774
37775 $this->hasIssues = !empty($repoData['has_issues']);
37776 $this->branchesUrl = $repoData['links']['branches']['href'];
37777 $this->tagsUrl = $repoData['links']['tags']['href'];
37778 $this->homeUrl = $repoData['links']['html']['href'];
37779 $this->website = $repoData['website'];
37780 $this->vcsType = $repoData['scm'];
37781
37782 return true;
37783 }
37784
37785
37786
37787
37788 public function getComposerInformation($identifier)
37789 {
37790 if ($this->fallbackDriver) {
37791 return $this->fallbackDriver->getComposerInformation($identifier);
37792 }
37793
37794 if (!isset($this->infoCache[$identifier])) {
37795 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
37796 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37797 }
37798
37799 $composer = $this->getBaseComposerInformation($identifier);
37800
37801 if ($composer) {
37802
37803  if (!isset($composer['support']['source'])) {
37804 $label = array_search(
37805 $identifier,
37806 $this->getTags()
37807 ) ?: array_search(
37808 $identifier,
37809 $this->getBranches()
37810 ) ?: $identifier;
37811
37812 if (array_key_exists($label, $tags = $this->getTags())) {
37813 $hash = $tags[$label];
37814 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
37815 $hash = $branches[$label];
37816 }
37817
37818 if (! isset($hash)) {
37819 $composer['support']['source'] = sprintf(
37820 'https://%s/%s/%s/src',
37821 $this->originUrl,
37822 $this->owner,
37823 $this->repository
37824 );
37825 } else {
37826 $composer['support']['source'] = sprintf(
37827 'https://%s/%s/%s/src/%s/?at=%s',
37828 $this->originUrl,
37829 $this->owner,
37830 $this->repository,
37831 $hash,
37832 $label
37833 );
37834 }
37835 }
37836 if (!isset($composer['support']['issues']) && $this->hasIssues) {
37837 $composer['support']['issues'] = sprintf(
37838 'https://%s/%s/%s/issues',
37839 $this->originUrl,
37840 $this->owner,
37841 $this->repository
37842 );
37843 }
37844 if (!isset($composer['homepage'])) {
37845 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
37846 }
37847 }
37848
37849 $this->infoCache[$identifier] = $composer;
37850
37851 if ($this->shouldCache($identifier)) {
37852 $this->cache->write($identifier, json_encode($composer));
37853 }
37854 }
37855
37856 return $this->infoCache[$identifier];
37857 }
37858
37859
37860
37861
37862 public function getFileContent($file, $identifier)
37863 {
37864 if ($this->fallbackDriver) {
37865 return $this->fallbackDriver->getFileContent($file, $identifier);
37866 }
37867
37868 if (strpos($identifier, '/') !== false) {
37869 $branches = $this->getBranches();
37870 if (isset($branches[$identifier])) {
37871 $identifier = $branches[$identifier];
37872 }
37873 }
37874
37875 $resource = sprintf(
37876 'https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s',
37877 $this->owner,
37878 $this->repository,
37879 $identifier,
37880 $file
37881 );
37882
37883 return $this->getContentsWithOAuthCredentials($resource);
37884 }
37885
37886
37887
37888
37889 public function getChangeDate($identifier)
37890 {
37891 if ($this->fallbackDriver) {
37892 return $this->fallbackDriver->getChangeDate($identifier);
37893 }
37894
37895 if (strpos($identifier, '/') !== false) {
37896 $branches = $this->getBranches();
37897 if (isset($branches[$identifier])) {
37898 $identifier = $branches[$identifier];
37899 }
37900 }
37901
37902 $resource = sprintf(
37903 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
37904 $this->owner,
37905 $this->repository,
37906 $identifier
37907 );
37908 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
37909
37910 return new \DateTime($commit['date']);
37911 }
37912
37913
37914
37915
37916 public function getSource($identifier)
37917 {
37918 if ($this->fallbackDriver) {
37919 return $this->fallbackDriver->getSource($identifier);
37920 }
37921
37922 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
37923 }
37924
37925
37926
37927
37928 public function getDist($identifier)
37929 {
37930 if ($this->fallbackDriver) {
37931 return $this->fallbackDriver->getDist($identifier);
37932 }
37933
37934 $url = sprintf(
37935 'https://bitbucket.org/%s/%s/get/%s.zip',
37936 $this->owner,
37937 $this->repository,
37938 $identifier
37939 );
37940
37941 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
37942 }
37943
37944
37945
37946
37947 public function getTags()
37948 {
37949 if ($this->fallbackDriver) {
37950 return $this->fallbackDriver->getTags();
37951 }
37952
37953 if (null === $this->tags) {
37954 $this->tags = array();
37955 $resource = sprintf(
37956 '%s?%s',
37957 $this->tagsUrl,
37958 http_build_query(
37959 array(
37960 'pagelen' => 100,
37961 'fields' => 'values.name,values.target.hash,next',
37962 'sort' => '-target.date',
37963 ),
37964 null,
37965 '&'
37966 )
37967 );
37968 $hasNext = true;
37969 while ($hasNext) {
37970 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
37971 foreach ($tagsData['values'] as $data) {
37972 $this->tags[$data['name']] = $data['target']['hash'];
37973 }
37974 if (empty($tagsData['next'])) {
37975 $hasNext = false;
37976 } else {
37977 $resource = $tagsData['next'];
37978 }
37979 }
37980 if ($this->vcsType === 'hg') {
37981 unset($this->tags['tip']);
37982 }
37983 }
37984
37985 return $this->tags;
37986 }
37987
37988
37989
37990
37991 public function getBranches()
37992 {
37993 if ($this->fallbackDriver) {
37994 return $this->fallbackDriver->getBranches();
37995 }
37996
37997 if (null === $this->branches) {
37998 $this->branches = array();
37999 $resource = sprintf(
38000 '%s?%s',
38001 $this->branchesUrl,
38002 http_build_query(
38003 array(
38004 'pagelen' => 100,
38005 'fields' => 'values.name,values.target.hash,values.heads,next',
38006 'sort' => '-target.date',
38007 ),
38008 null,
38009 '&'
38010 )
38011 );
38012 $hasNext = true;
38013 while ($hasNext) {
38014 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
38015 foreach ($branchData['values'] as $data) {
38016
38017  if ($this->vcsType === 'hg' && empty($data['heads'])) {
38018 continue;
38019 }
38020
38021 $this->branches[$data['name']] = $data['target']['hash'];
38022 }
38023 if (empty($branchData['next'])) {
38024 $hasNext = false;
38025 } else {
38026 $resource = $branchData['next'];
38027 }
38028 }
38029 }
38030
38031 return $this->branches;
38032 }
38033
38034
38035
38036
38037
38038
38039
38040
38041
38042 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
38043 {
38044 try {
38045 return parent::getContents($url);
38046 } catch (TransportException $e) {
38047 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
38048
38049 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
38050 if (!$this->io->hasAuthentication($this->originUrl)
38051 && $bitbucketUtil->authorizeOAuth($this->originUrl)
38052 ) {
38053 return parent::getContents($url);
38054 }
38055
38056 if (!$this->io->isInteractive() && $fetchingRepoData) {
38057 return $this->attemptCloneFallback();
38058 }
38059 }
38060
38061 throw $e;
38062 }
38063 }
38064
38065
38066
38067
38068
38069
38070 abstract protected function generateSshUrl();
38071
38072 protected function attemptCloneFallback()
38073 {
38074 try {
38075 $this->setupFallbackDriver($this->generateSshUrl());
38076 } catch (\RuntimeException $e) {
38077 $this->fallbackDriver = null;
38078
38079 $this->io->writeError(
38080 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
38081 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
38082 );
38083 throw $e;
38084 }
38085 }
38086
38087
38088
38089
38090
38091 abstract protected function setupFallbackDriver($url);
38092
38093
38094
38095
38096
38097 protected function parseCloneUrls(array $cloneLinks)
38098 {
38099 foreach ($cloneLinks as $cloneLink) {
38100 if ($cloneLink['name'] === 'https') {
38101
38102  
38103  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
38104 }
38105 }
38106 }
38107
38108
38109
38110
38111 protected function getMainBranchData()
38112 {
38113 $resource = sprintf(
38114 'https://api.bitbucket.org/2.0/repositories/%s/%s?fields=mainbranch',
38115 $this->owner,
38116 $this->repository
38117 );
38118
38119 $data = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
38120 if (isset($data['mainbranch'])) {
38121 return $data['mainbranch'];
38122 }
38123
38124 return null;
38125 }
38126 }
38127 <?php
38128
38129
38130
38131
38132
38133
38134
38135
38136
38137
38138
38139 namespace Composer\Repository\Vcs;
38140
38141 use Composer\Cache;
38142 use Composer\Config;
38143 use Composer\Util\ProcessExecutor;
38144 use Composer\Util\Filesystem;
38145 use Composer\IO\IOInterface;
38146
38147
38148
38149
38150 class FossilDriver extends VcsDriver
38151 {
38152 protected $tags;
38153 protected $branches;
38154 protected $rootIdentifier;
38155 protected $repoFile;
38156 protected $checkoutDir;
38157 protected $infoCache = array();
38158
38159
38160
38161
38162 public function initialize()
38163 {
38164
38165  $this->checkFossil();
38166
38167
38168  $this->config->prohibitUrlByConfig($this->url, $this->io);
38169
38170
38171  
38172  if (Filesystem::isLocalPath($this->url) && is_dir($this->url)) {
38173 $this->checkoutDir = $this->url;
38174 } else {
38175 if (!Cache::isUsable($this->config->get('cache-repo-dir')) || !Cache::isUsable($this->config->get('cache-vcs-dir'))) {
38176 throw new \RuntimeException('FossilDriver requires a usable cache directory, and it looks like you set it to be disabled');
38177 }
38178
38179 $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url);
38180 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil';
38181 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/';
38182
38183 $this->updateLocalRepo();
38184 }
38185
38186 $this->getTags();
38187 $this->getBranches();
38188 }
38189
38190
38191
38192
38193 protected function checkFossil()
38194 {
38195 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
38196 throw new \RuntimeException("fossil was not found, check that it is installed and in your PATH env.\n\n" . $this->process->getErrorOutput());
38197 }
38198 }
38199
38200
38201
38202
38203 protected function updateLocalRepo()
38204 {
38205 $fs = new Filesystem();
38206 $fs->ensureDirectoryExists($this->checkoutDir);
38207
38208 if (!is_writable(dirname($this->checkoutDir))) {
38209 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
38210 }
38211
38212
38213  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
38214 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
38215 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
38216 }
38217 } else {
38218
38219  $fs->removeDirectory($this->checkoutDir);
38220 $fs->remove($this->repoFile);
38221
38222 $fs->ensureDirectoryExists($this->checkoutDir);
38223
38224 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
38225 $output = $this->process->getErrorOutput();
38226
38227 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
38228 }
38229
38230 if (0 !== $this->process->execute(sprintf('fossil open %s --nested', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
38231 $output = $this->process->getErrorOutput();
38232
38233 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
38234 }
38235 }
38236 }
38237
38238
38239
38240
38241 public function getRootIdentifier()
38242 {
38243 if (null === $this->rootIdentifier) {
38244 $this->rootIdentifier = 'trunk';
38245 }
38246
38247 return $this->rootIdentifier;
38248 }
38249
38250
38251
38252
38253 public function getUrl()
38254 {
38255 return $this->url;
38256 }
38257
38258
38259
38260
38261 public function getSource($identifier)
38262 {
38263 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
38264 }
38265
38266
38267
38268
38269 public function getDist($identifier)
38270 {
38271 return null;
38272 }
38273
38274
38275
38276
38277 public function getFileContent($file, $identifier)
38278 {
38279 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
38280 $this->process->execute($command, $content, $this->checkoutDir);
38281
38282 if (!trim($content)) {
38283 return null;
38284 }
38285
38286 return $content;
38287 }
38288
38289
38290
38291
38292 public function getChangeDate($identifier)
38293 {
38294 $this->process->execute('fossil finfo -b -n 1 composer.json', $output, $this->checkoutDir);
38295 list($ckout, $date, $message) = explode(' ', trim($output), 3);
38296
38297 return new \DateTime($date, new \DateTimeZone('UTC'));
38298 }
38299
38300
38301
38302
38303 public function getTags()
38304 {
38305 if (null === $this->tags) {
38306 $tags = array();
38307
38308 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
38309 foreach ($this->process->splitLines($output) as $tag) {
38310 $tags[$tag] = $tag;
38311 }
38312
38313 $this->tags = $tags;
38314 }
38315
38316 return $this->tags;
38317 }
38318
38319
38320
38321
38322 public function getBranches()
38323 {
38324 if (null === $this->branches) {
38325 $branches = array();
38326 $bookmarks = array();
38327
38328 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
38329 foreach ($this->process->splitLines($output) as $branch) {
38330 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
38331 $branches[$branch] = $branch;
38332 }
38333
38334 $this->branches = $branches;
38335 }
38336
38337 return $this->branches;
38338 }
38339
38340
38341
38342
38343 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38344 {
38345 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
38346 return true;
38347 }
38348
38349 if (preg_match('!/fossil/|\.fossil!', $url)) {
38350 return true;
38351 }
38352
38353
38354  if (Filesystem::isLocalPath($url)) {
38355 $url = Filesystem::getPlatformPath($url);
38356 if (!is_dir($url)) {
38357 return false;
38358 }
38359
38360 $process = new ProcessExecutor($io);
38361
38362  if ($process->execute('fossil info', $output, $url) === 0) {
38363 return true;
38364 }
38365 }
38366
38367 return false;
38368 }
38369 }
38370 <?php
38371
38372
38373
38374
38375
38376
38377
38378
38379
38380
38381
38382 namespace Composer\Repository\Vcs;
38383
38384 use Composer\Config;
38385 use Composer\IO\IOInterface;
38386
38387
38388
38389
38390 class GitBitbucketDriver extends BitbucketDriver
38391 {
38392
38393
38394
38395 public function getRootIdentifier()
38396 {
38397 if ($this->fallbackDriver) {
38398 return $this->fallbackDriver->getRootIdentifier();
38399 }
38400
38401 if (null === $this->rootIdentifier) {
38402 if (! $this->getRepoData()) {
38403 return $this->fallbackDriver->getRootIdentifier();
38404 }
38405
38406 if ($this->vcsType !== 'git') {
38407 throw new \RuntimeException(
38408 $this->url.' does not appear to be a git repository, use '.
38409 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
38410 );
38411 }
38412
38413 $mainBranchData = $this->getMainBranchData();
38414 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
38415 }
38416
38417 return $this->rootIdentifier;
38418 }
38419
38420
38421
38422
38423 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38424 {
38425 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#i', $url)) {
38426 return false;
38427 }
38428
38429 if (!extension_loaded('openssl')) {
38430 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
38431
38432 return false;
38433 }
38434
38435 return true;
38436 }
38437
38438
38439
38440
38441 protected function setupFallbackDriver($url)
38442 {
38443 $this->fallbackDriver = new GitDriver(
38444 array('url' => $url),
38445 $this->io,
38446 $this->config,
38447 $this->process,
38448 $this->remoteFilesystem
38449 );
38450 $this->fallbackDriver->initialize();
38451 }
38452
38453
38454
38455
38456 protected function generateSshUrl()
38457 {
38458 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
38459 }
38460 }
38461 <?php
38462
38463
38464
38465
38466
38467
38468
38469
38470
38471
38472
38473 namespace Composer\Repository\Vcs;
38474
38475 use Composer\Util\ProcessExecutor;
38476 use Composer\Util\Filesystem;
38477 use Composer\Util\Git as GitUtil;
38478 use Composer\IO\IOInterface;
38479 use Composer\Cache;
38480 use Composer\Config;
38481
38482
38483
38484
38485 class GitDriver extends VcsDriver
38486 {
38487 protected $cache;
38488 protected $tags;
38489 protected $branches;
38490 protected $rootIdentifier;
38491 protected $repoDir;
38492 protected $infoCache = array();
38493
38494
38495
38496
38497 public function initialize()
38498 {
38499 if (Filesystem::isLocalPath($this->url)) {
38500 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
38501 $this->repoDir = $this->url;
38502 $cacheUrl = realpath($this->url);
38503 } else {
38504 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
38505 throw new \RuntimeException('GitDriver requires a usable cache directory, and it looks like you set it to be disabled');
38506 }
38507
38508 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
38509
38510 GitUtil::cleanEnv();
38511
38512 $fs = new Filesystem();
38513 $fs->ensureDirectoryExists(dirname($this->repoDir));
38514
38515 if (!is_writable(dirname($this->repoDir))) {
38516 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
38517 }
38518
38519 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
38520 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.');
38521 }
38522
38523 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
38524 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
38525 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
38526 }
38527
38528 $cacheUrl = $this->url;
38529 }
38530
38531 $this->getTags();
38532 $this->getBranches();
38533
38534 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
38535 }
38536
38537
38538
38539
38540 public function getRootIdentifier()
38541 {
38542 if (null === $this->rootIdentifier) {
38543 $this->rootIdentifier = 'master';
38544
38545
38546  $this->process->execute('git branch --no-color', $output, $this->repoDir);
38547 $branches = $this->process->splitLines($output);
38548 if (!in_array('* master', $branches)) {
38549 foreach ($branches as $branch) {
38550 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
38551 $this->rootIdentifier = $match[1];
38552 break;
38553 }
38554 }
38555 }
38556 }
38557
38558 return $this->rootIdentifier;
38559 }
38560
38561
38562
38563
38564 public function getUrl()
38565 {
38566 return $this->url;
38567 }
38568
38569
38570
38571
38572 public function getSource($identifier)
38573 {
38574 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
38575 }
38576
38577
38578
38579
38580 public function getDist($identifier)
38581 {
38582 return null;
38583 }
38584
38585
38586
38587
38588 public function getFileContent($file, $identifier)
38589 {
38590 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
38591 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
38592
38593 if (!trim($content)) {
38594 return null;
38595 }
38596
38597 return $content;
38598 }
38599
38600
38601
38602
38603 public function getChangeDate($identifier)
38604 {
38605 $this->process->execute(sprintf(
38606 'git -c log.showSignature=false log -1 --format=%%at %s',
38607 ProcessExecutor::escape($identifier)
38608 ), $output, $this->repoDir);
38609
38610 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
38611 }
38612
38613
38614
38615
38616 public function getTags()
38617 {
38618 if (null === $this->tags) {
38619 $this->tags = array();
38620
38621 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
38622 foreach ($output = $this->process->splitLines($output) as $tag) {
38623 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
38624 $this->tags[$match[2]] = $match[1];
38625 }
38626 }
38627 }
38628
38629 return $this->tags;
38630 }
38631
38632
38633
38634
38635 public function getBranches()
38636 {
38637 if (null === $this->branches) {
38638 $branches = array();
38639
38640 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
38641 foreach ($this->process->splitLines($output) as $branch) {
38642 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
38643 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
38644 $branches[$match[1]] = $match[2];
38645 }
38646 }
38647 }
38648
38649 $this->branches = $branches;
38650 }
38651
38652 return $this->branches;
38653 }
38654
38655
38656
38657
38658 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
38659 {
38660 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
38661 return true;
38662 }
38663
38664
38665  if (Filesystem::isLocalPath($url)) {
38666 $url = Filesystem::getPlatformPath($url);
38667 if (!is_dir($url)) {
38668 return false;
38669 }
38670
38671 $process = new ProcessExecutor($io);
38672
38673  if ($process->execute('git tag', $output, $url) === 0) {
38674 return true;
38675 }
38676 }
38677
38678 if (!$deep) {
38679 return false;
38680 }
38681
38682 $process = new ProcessExecutor($io);
38683
38684 return $process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0;
38685 }
38686 }
38687 <?php
38688
38689
38690
38691
38692
38693
38694
38695
38696
38697
38698
38699 namespace Composer\Repository\Vcs;
38700
38701 use Composer\Config;
38702 use Composer\Downloader\TransportException;
38703 use Composer\Json\JsonFile;
38704 use Composer\Cache;
38705 use Composer\IO\IOInterface;
38706 use Composer\Util\GitHub;
38707
38708
38709
38710
38711 class GitHubDriver extends VcsDriver
38712 {
38713 protected $cache;
38714 protected $owner;
38715 protected $repository;
38716 protected $tags;
38717 protected $branches;
38718 protected $rootIdentifier;
38719 protected $repoData;
38720 protected $hasIssues;
38721 protected $infoCache = array();
38722 protected $isPrivate = false;
38723 private $isArchived = false;
38724 private $fundingInfo;
38725
38726
38727
38728
38729
38730
38731 protected $gitDriver;
38732
38733
38734
38735
38736 public function initialize()
38737 {
38738 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
38739 $this->owner = $match[3];
38740 $this->repository = $match[4];
38741 $this->originUrl = strtolower(!empty($match[1]) ? $match[1] : $match[2]);
38742 if ($this->originUrl === 'www.github.com') {
38743 $this->originUrl = 'github.com';
38744 }
38745 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
38746
38747 if ( $this->config->get('use-github-api') === false || (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api'] ) ){
38748 $this->setupGitDriver($this->url);
38749
38750 return;
38751 }
38752
38753 $this->fetchRootIdentifier();
38754 }
38755
38756 public function getRepositoryUrl()
38757 {
38758 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
38759 }
38760
38761
38762
38763
38764 public function getRootIdentifier()
38765 {
38766 if ($this->gitDriver) {
38767 return $this->gitDriver->getRootIdentifier();
38768 }
38769
38770 return $this->rootIdentifier;
38771 }
38772
38773
38774
38775
38776 public function getUrl()
38777 {
38778 if ($this->gitDriver) {
38779 return $this->gitDriver->getUrl();
38780 }
38781
38782 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
38783 }
38784
38785
38786
38787
38788 protected function getApiUrl()
38789 {
38790 if ('github.com' === $this->originUrl) {
38791 $apiUrl = 'api.github.com';
38792 } else {
38793 $apiUrl = $this->originUrl . '/api/v3';
38794 }
38795
38796 return 'https://' . $apiUrl;
38797 }
38798
38799
38800
38801
38802 public function getSource($identifier)
38803 {
38804 if ($this->gitDriver) {
38805 return $this->gitDriver->getSource($identifier);
38806 }
38807 if ($this->isPrivate) {
38808
38809  
38810  $url = $this->generateSshUrl();
38811 } else {
38812 $url = $this->getUrl();
38813 }
38814
38815 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
38816 }
38817
38818
38819
38820
38821 public function getDist($identifier)
38822 {
38823 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
38824
38825 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
38826 }
38827
38828
38829
38830
38831 public function getComposerInformation($identifier)
38832 {
38833 if ($this->gitDriver) {
38834 return $this->gitDriver->getComposerInformation($identifier);
38835 }
38836
38837 if (!isset($this->infoCache[$identifier])) {
38838 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
38839 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
38840 }
38841
38842 $composer = $this->getBaseComposerInformation($identifier);
38843
38844 if ($composer) {
38845
38846  if (!isset($composer['support']['source'])) {
38847 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
38848 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
38849 }
38850 if (!isset($composer['support']['issues']) && $this->hasIssues) {
38851 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
38852 }
38853 if (!isset($composer['abandoned']) && $this->isArchived) {
38854 $composer['abandoned'] = true;
38855 }
38856 if (!isset($composer['funding']) && $funding = $this->getFundingInfo()) {
38857 $composer['funding'] = $funding;
38858 }
38859 }
38860
38861 if ($this->shouldCache($identifier)) {
38862 $this->cache->write($identifier, json_encode($composer));
38863 }
38864
38865 $this->infoCache[$identifier] = $composer;
38866 }
38867
38868 return $this->infoCache[$identifier];
38869 }
38870
38871 private function getFundingInfo()
38872 {
38873 if (null !== $this->fundingInfo) {
38874 return $this->fundingInfo;
38875 }
38876
38877 if ($this->originUrl !== 'github.com') {
38878 return $this->fundingInfo = false;
38879 }
38880
38881 foreach (array($this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/.github/FUNDING.yml', $this->getApiUrl() . '/repos/'.$this->owner.'/.github/contents/FUNDING.yml') as $file) {
38882
38883 try {
38884 $result = $this->remoteFilesystem->getContents($this->originUrl, $file, false, array(
38885 'retry-auth-failure' => false,
38886 ));
38887 $response = json_decode($result, true);
38888 } catch (TransportException $e) {
38889 continue;
38890 }
38891 if (empty($response['content']) || $response['encoding'] !== 'base64' || !($funding = base64_decode($response['content']))) {
38892 continue;
38893 }
38894 break;
38895 }
38896 if (empty($funding)) {
38897 return $this->fundingInfo = false;
38898 }
38899
38900 $result = array();
38901 $key = null;
38902 foreach (preg_split('{\r?\n}', $funding) as $line) {
38903 $line = preg_replace('{#.*}', '', $line);
38904 $line = trim($line);
38905 if (preg_match('{^(\w+)\s*:\s*(.+)$}', $line, $match)) {
38906 if (preg_match('{^\[.*\]$}', $match[2])) {
38907 foreach (array_map('trim', preg_split('{[\'"]?\s*,\s*[\'"]?}', substr($match[2], 1, -1))) as $item) {
38908 $result[] = array('type' => $match[1], 'url' => trim($item, '"\' '));
38909 }
38910 } else {
38911 $result[] = array('type' => $match[1], 'url' => trim($match[2], '"\' '));
38912 }
38913 $key = null;
38914 } elseif (preg_match('{^(\w+)\s*:$}', $line, $match)) {
38915 $key = $match[1];
38916 } elseif ($key && preg_match('{^-\s*(.+)$}', $line, $match)) {
38917 $result[] = array('type' => $key, 'url' => trim($match[1], '"\' '));
38918 }
38919 }
38920
38921 foreach ($result as $key => $item) {
38922 switch ($item['type']) {
38923 case 'tidelift':
38924 $result[$key]['url'] = 'https://tidelift.com/funding/github/' . $item['url'];
38925 break;
38926 case 'github':
38927 $result[$key]['url'] = 'https://github.com/' . basename($item['url']);
38928 break;
38929 case 'patreon':
38930 $result[$key]['url'] = 'https://www.patreon.com/' . basename($item['url']);
38931 break;
38932 case 'otechie':
38933 $result[$key]['url'] = 'https://otechie.com/' . basename($item['url']);
38934 break;
38935 case 'open_collective':
38936 $result[$key]['url'] = 'https://opencollective.com/' . basename($item['url']);
38937 break;
38938 case 'liberapay':
38939 $result[$key]['url'] = 'https://liberapay.com/' . basename($item['url']);
38940 break;
38941 case 'ko_fi':
38942 $result[$key]['url'] = 'https://ko-fi.com/' . basename($item['url']);
38943 break;
38944 case 'issuehunt':
38945 $result[$key]['url'] = 'https://issuehunt.io/r/' . $item['url'];
38946 break;
38947 case 'community_bridge':
38948 $result[$key]['url'] = 'https://funding.communitybridge.org/projects/' . basename($item['url']);
38949 break;
38950 }
38951 }
38952
38953 return $this->fundingInfo = $result;
38954 }
38955
38956
38957
38958
38959 public function getFileContent($file, $identifier)
38960 {
38961 if ($this->gitDriver) {
38962 return $this->gitDriver->getFileContent($file, $identifier);
38963 }
38964
38965 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
38966 $resource = JsonFile::parseJson($this->getContents($resource));
38967 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
38968 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
38969 }
38970
38971 return $content;
38972 }
38973
38974
38975
38976
38977 public function getChangeDate($identifier)
38978 {
38979 if ($this->gitDriver) {
38980 return $this->gitDriver->getChangeDate($identifier);
38981 }
38982
38983 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
38984 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
38985
38986 return new \DateTime($commit['commit']['committer']['date']);
38987 }
38988
38989
38990
38991
38992 public function getTags()
38993 {
38994 if ($this->gitDriver) {
38995 return $this->gitDriver->getTags();
38996 }
38997 if (null === $this->tags) {
38998 $this->tags = array();
38999 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
39000
39001 do {
39002 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
39003 foreach ($tagsData as $tag) {
39004 $this->tags[$tag['name']] = $tag['commit']['sha'];
39005 }
39006
39007 $resource = $this->getNextPage();
39008 } while ($resource);
39009 }
39010
39011 return $this->tags;
39012 }
39013
39014
39015
39016
39017 public function getBranches()
39018 {
39019 if ($this->gitDriver) {
39020 return $this->gitDriver->getBranches();
39021 }
39022 if (null === $this->branches) {
39023 $this->branches = array();
39024 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
39025
39026 $branchBlacklist = array('gh-pages');
39027
39028 do {
39029 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
39030 foreach ($branchData as $branch) {
39031 $name = substr($branch['ref'], 11);
39032 if (!in_array($name, $branchBlacklist)) {
39033 $this->branches[$name] = $branch['object']['sha'];
39034 }
39035 }
39036
39037 $resource = $this->getNextPage();
39038 } while ($resource);
39039 }
39040
39041 return $this->branches;
39042 }
39043
39044
39045
39046
39047 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39048 {
39049 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
39050 return false;
39051 }
39052
39053 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
39054 if (!in_array(strtolower(preg_replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) {
39055 return false;
39056 }
39057
39058 if (!extension_loaded('openssl')) {
39059 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
39060
39061 return false;
39062 }
39063
39064 return true;
39065 }
39066
39067
39068
39069
39070
39071
39072 public function getRepoData()
39073 {
39074 $this->fetchRootIdentifier();
39075
39076 return $this->repoData;
39077 }
39078
39079
39080
39081
39082
39083
39084 protected function generateSshUrl()
39085 {
39086 if (false !== strpos($this->originUrl, ':')) {
39087 return 'ssh://git@' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
39088 }
39089
39090 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
39091 }
39092
39093
39094
39095
39096 protected function getContents($url, $fetchingRepoData = false)
39097 {
39098 try {
39099 return parent::getContents($url);
39100 } catch (TransportException $e) {
39101 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
39102
39103 switch ($e->getCode()) {
39104 case 401:
39105 case 404:
39106
39107  if (!$fetchingRepoData) {
39108 throw $e;
39109 }
39110
39111 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
39112 return parent::getContents($url);
39113 }
39114
39115 if (!$this->io->isInteractive()) {
39116 return $this->attemptCloneFallback();
39117 }
39118
39119 $scopesIssued = array();
39120 $scopesNeeded = array();
39121 if ($headers = $e->getHeaders()) {
39122 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
39123 $scopesIssued = explode(' ', $scopes);
39124 }
39125 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
39126 $scopesNeeded = explode(' ', $scopes);
39127 }
39128 }
39129 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
39130
39131  
39132  if (!$headers || !count($scopesNeeded) || count($scopesFailed)) {
39133 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
39134 }
39135
39136 return parent::getContents($url);
39137
39138 case 403:
39139 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
39140 return parent::getContents($url);
39141 }
39142
39143 if (!$this->io->isInteractive() && $fetchingRepoData) {
39144 return $this->attemptCloneFallback();
39145 }
39146
39147 $rateLimited = $gitHubUtil->isRateLimited($e->getHeaders());
39148
39149 if (!$this->io->hasAuthentication($this->originUrl)) {
39150 if (!$this->io->isInteractive()) {
39151 $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>');
39152 throw $e;
39153 }
39154
39155 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
39156
39157 return parent::getContents($url);
39158 }
39159
39160 if ($rateLimited) {
39161 $rateLimit = $gitHubUtil->getRateLimit($e->getHeaders());
39162 $this->io->writeError(sprintf(
39163 '<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>',
39164 $rateLimit['limit'],
39165 $rateLimit['reset']
39166 ));
39167 }
39168
39169 throw $e;
39170
39171 default:
39172 throw $e;
39173 }
39174 }
39175 }
39176
39177
39178
39179
39180
39181
39182 protected function fetchRootIdentifier()
39183 {
39184 if ($this->repoData) {
39185 return;
39186 }
39187
39188 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
39189
39190 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
39191 if (null === $this->repoData && null !== $this->gitDriver) {
39192 return;
39193 }
39194
39195 $this->owner = $this->repoData['owner']['login'];
39196 $this->repository = $this->repoData['name'];
39197
39198 $this->isPrivate = !empty($this->repoData['private']);
39199 if (isset($this->repoData['default_branch'])) {
39200 $this->rootIdentifier = $this->repoData['default_branch'];
39201 } elseif (isset($this->repoData['master_branch'])) {
39202 $this->rootIdentifier = $this->repoData['master_branch'];
39203 } else {
39204 $this->rootIdentifier = 'master';
39205 }
39206 $this->hasIssues = !empty($this->repoData['has_issues']);
39207 $this->isArchived = !empty($this->repoData['archived']);
39208 }
39209
39210 protected function attemptCloneFallback()
39211 {
39212 $this->isPrivate = true;
39213
39214 try {
39215
39216  
39217  
39218  
39219  $this->setupGitDriver($this->generateSshUrl());
39220
39221 return;
39222 } catch (\RuntimeException $e) {
39223 $this->gitDriver = null;
39224
39225 $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>');
39226 throw $e;
39227 }
39228 }
39229
39230 protected function setupGitDriver($url)
39231 {
39232 $this->gitDriver = new GitDriver(
39233 array('url' => $url),
39234 $this->io,
39235 $this->config,
39236 $this->process,
39237 $this->remoteFilesystem
39238 );
39239 $this->gitDriver->initialize();
39240 }
39241
39242 protected function getNextPage()
39243 {
39244 $headers = $this->remoteFilesystem->getLastHeaders();
39245 foreach ($headers as $header) {
39246 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
39247 $links = explode(',', $match[1]);
39248 foreach ($links as $link) {
39249 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
39250 return $match[1];
39251 }
39252 }
39253 }
39254 }
39255 }
39256 }
39257 <?php
39258
39259
39260
39261
39262
39263
39264
39265
39266
39267
39268
39269 namespace Composer\Repository\Vcs;
39270
39271 use Composer\Config;
39272 use Composer\Cache;
39273 use Composer\IO\IOInterface;
39274 use Composer\Json\JsonFile;
39275 use Composer\Downloader\TransportException;
39276 use Composer\Util\RemoteFilesystem;
39277 use Composer\Util\GitLab;
39278
39279
39280
39281
39282
39283
39284
39285 class GitLabDriver extends VcsDriver
39286 {
39287 private $scheme;
39288 private $namespace;
39289 private $repository;
39290
39291
39292
39293
39294 private $project;
39295
39296
39297
39298
39299 private $commits = array();
39300
39301
39302
39303
39304 private $tags;
39305
39306
39307
39308
39309 private $branches;
39310
39311
39312
39313
39314
39315
39316 protected $gitDriver;
39317
39318
39319
39320
39321
39322
39323 private $isPrivate = true;
39324
39325
39326
39327
39328 private $hasNonstandardOrigin = false;
39329
39330 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)(?::(?P<port>[0-9]+))?/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
39331
39332
39333
39334
39335
39336
39337
39338
39339 public function initialize()
39340 {
39341 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
39342 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
39343 }
39344
39345 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
39346 $configuredDomains = $this->config->get('gitlab-domains');
39347 $urlParts = explode('/', $match['parts']);
39348
39349 $this->scheme = !empty($match['scheme'])
39350 ? $match['scheme']
39351 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
39352 ;
39353 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts, $match['port']);
39354
39355 if (false !== strpos($this->originUrl, ':') || false !== strpos($this->originUrl, '/')) {
39356 $this->hasNonstandardOrigin = true;
39357 }
39358
39359 $this->namespace = implode('/', $urlParts);
39360 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
39361
39362 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
39363
39364 $this->fetchProject();
39365 }
39366
39367
39368
39369
39370
39371
39372
39373 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
39374 {
39375 $this->remoteFilesystem = $remoteFilesystem;
39376 }
39377
39378
39379
39380
39381 public function getComposerInformation($identifier)
39382 {
39383 if ($this->gitDriver) {
39384 return $this->gitDriver->getComposerInformation($identifier);
39385 }
39386
39387 if (!isset($this->infoCache[$identifier])) {
39388 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
39389 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
39390 }
39391
39392 $composer = $this->getBaseComposerInformation($identifier);
39393
39394 if ($composer) {
39395
39396  if (!isset($composer['support']['issues']) && isset($this->project['_links']['issues'])) {
39397 $composer['support']['issues'] = $this->project['_links']['issues'];
39398 }
39399 if (!isset($composer['abandoned']) && !empty($this->project['archived'])) {
39400 $composer['abandoned'] = true;
39401 }
39402 }
39403
39404 if ($this->shouldCache($identifier)) {
39405 $this->cache->write($identifier, json_encode($composer));
39406 }
39407
39408 $this->infoCache[$identifier] = $composer;
39409 }
39410
39411 return $this->infoCache[$identifier];
39412 }
39413
39414
39415
39416
39417 public function getFileContent($file, $identifier)
39418 {
39419 if ($this->gitDriver) {
39420 return $this->gitDriver->getFileContent($file, $identifier);
39421 }
39422
39423
39424  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
39425 $branches = $this->getBranches();
39426 if (isset($branches[$identifier])) {
39427 $identifier = $branches[$identifier];
39428 }
39429 }
39430
39431 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
39432
39433 try {
39434 $content = $this->getContents($resource);
39435 } catch (TransportException $e) {
39436 if ($e->getCode() !== 404) {
39437 throw $e;
39438 }
39439
39440 return null;
39441 }
39442
39443 return $content;
39444 }
39445
39446
39447
39448
39449 public function getChangeDate($identifier)
39450 {
39451 if ($this->gitDriver) {
39452 return $this->gitDriver->getChangeDate($identifier);
39453 }
39454
39455 if (isset($this->commits[$identifier])) {
39456 return new \DateTime($this->commits[$identifier]['committed_date']);
39457 }
39458
39459 return new \DateTime();
39460 }
39461
39462
39463
39464
39465 public function getRepositoryUrl()
39466 {
39467 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
39468 }
39469
39470
39471
39472
39473 public function getUrl()
39474 {
39475 if ($this->gitDriver) {
39476 return $this->gitDriver->getUrl();
39477 }
39478
39479 return $this->project['web_url'];
39480 }
39481
39482
39483
39484
39485 public function getDist($identifier)
39486 {
39487 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
39488
39489 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
39490 }
39491
39492
39493
39494
39495 public function getSource($identifier)
39496 {
39497 if ($this->gitDriver) {
39498 return $this->gitDriver->getSource($identifier);
39499 }
39500
39501 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
39502 }
39503
39504
39505
39506
39507 public function getRootIdentifier()
39508 {
39509 if ($this->gitDriver) {
39510 return $this->gitDriver->getRootIdentifier();
39511 }
39512
39513 return $this->project['default_branch'];
39514 }
39515
39516
39517
39518
39519 public function getBranches()
39520 {
39521 if ($this->gitDriver) {
39522 return $this->gitDriver->getBranches();
39523 }
39524
39525 if (!$this->branches) {
39526 $this->branches = $this->getReferences('branches');
39527 }
39528
39529 return $this->branches;
39530 }
39531
39532
39533
39534
39535 public function getTags()
39536 {
39537 if ($this->gitDriver) {
39538 return $this->gitDriver->getTags();
39539 }
39540
39541 if (!$this->tags) {
39542 $this->tags = $this->getReferences('tags');
39543 }
39544
39545 return $this->tags;
39546 }
39547
39548
39549
39550
39551 public function getApiUrl()
39552 {
39553 return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
39554 }
39555
39556
39557
39558
39559
39560
39561
39562 private function urlEncodeAll($string)
39563 {
39564 $encoded = '';
39565 for ($i = 0; isset($string[$i]); $i++) {
39566 $character = $string[$i];
39567 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
39568 $character = '%' . sprintf('%02X', ord($character));
39569 }
39570 $encoded .= $character;
39571 }
39572
39573 return $encoded;
39574 }
39575
39576
39577
39578
39579
39580
39581 protected function getReferences($type)
39582 {
39583 $perPage = 100;
39584 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
39585
39586 $references = array();
39587 do {
39588 $data = JsonFile::parseJson($this->getContents($resource), $resource);
39589
39590 foreach ($data as $datum) {
39591 $references[$datum['name']] = $datum['commit']['id'];
39592
39593
39594  
39595  $this->commits[$datum['commit']['id']] = $datum['commit'];
39596 }
39597
39598 if (count($data) >= $perPage) {
39599 $resource = $this->getNextPage();
39600 } else {
39601 $resource = false;
39602 }
39603 } while ($resource);
39604
39605 return $references;
39606 }
39607
39608 protected function fetchProject()
39609 {
39610
39611  $resource = $this->getApiUrl();
39612 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
39613 if (isset($this->project['visibility'])) {
39614 $this->isPrivate = $this->project['visibility'] !== 'public';
39615 } else {
39616
39617  $this->isPrivate = false;
39618 }
39619 }
39620
39621 protected function attemptCloneFallback()
39622 {
39623 try {
39624 if ($this->isPrivate === false) {
39625 $url = $this->generatePublicUrl();
39626 } else {
39627 $url = $this->generateSshUrl();
39628 }
39629
39630
39631  
39632  
39633  $this->setupGitDriver($url);
39634
39635 return;
39636 } catch (\RuntimeException $e) {
39637 $this->gitDriver = null;
39638
39639 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
39640 throw $e;
39641 }
39642 }
39643
39644
39645
39646
39647
39648
39649 protected function generateSshUrl()
39650 {
39651 if ($this->hasNonstandardOrigin) {
39652 return 'ssh://git@'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository.'.git';
39653 }
39654
39655 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
39656 }
39657
39658 protected function generatePublicUrl()
39659 {
39660 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
39661 }
39662
39663 protected function setupGitDriver($url)
39664 {
39665 $this->gitDriver = new GitDriver(
39666 array('url' => $url),
39667 $this->io,
39668 $this->config,
39669 $this->process,
39670 $this->remoteFilesystem
39671 );
39672 $this->gitDriver->initialize();
39673 }
39674
39675
39676
39677
39678 protected function getContents($url, $fetchingRepoData = false)
39679 {
39680 try {
39681 $res = parent::getContents($url);
39682
39683 if ($fetchingRepoData) {
39684 $json = JsonFile::parseJson($res, $url);
39685
39686
39687  
39688  
39689  if (!isset($json['default_branch']) && isset($json['permissions'])) {
39690 $this->isPrivate = $json['visibility'] !== 'public';
39691
39692 $moreThanGuestAccess = false;
39693
39694  
39695  
39696  foreach ($json['permissions'] as $permission) {
39697 if ($permission && $permission['access_level'] > 10) {
39698 $moreThanGuestAccess = true;
39699 }
39700 }
39701
39702 if (!$moreThanGuestAccess) {
39703 $this->io->writeError('<warning>GitLab token with Guest only access detected</warning>');
39704
39705 return $this->attemptCloneFallback(); 
39706 }
39707 }
39708
39709
39710  if (!isset($json['default_branch'])) {
39711 if (!empty($json['id'])) {
39712 $this->isPrivate = false;
39713 }
39714
39715 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
39716 }
39717 }
39718
39719 return $res;
39720 } catch (TransportException $e) {
39721 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
39722
39723 switch ($e->getCode()) {
39724 case 401:
39725 case 404:
39726
39727  if (!$fetchingRepoData) {
39728 throw $e;
39729 }
39730
39731 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
39732 return parent::getContents($url);
39733 }
39734
39735 if (!$this->io->isInteractive()) {
39736 return $this->attemptCloneFallback();
39737 }
39738 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
39739 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
39740
39741 return parent::getContents($url);
39742
39743 case 403:
39744 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
39745 return parent::getContents($url);
39746 }
39747
39748 if (!$this->io->isInteractive() && $fetchingRepoData) {
39749 return $this->attemptCloneFallback();
39750 }
39751
39752 throw $e;
39753
39754 default:
39755 throw $e;
39756 }
39757 }
39758 }
39759
39760
39761
39762
39763
39764
39765
39766 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39767 {
39768 if (!preg_match(self::URL_REGEX, $url, $match)) {
39769 return false;
39770 }
39771
39772 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
39773 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
39774 $urlParts = explode('/', $match['parts']);
39775
39776 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts, $match['port'])) {
39777 return false;
39778 }
39779
39780 if ('https' === $scheme && !extension_loaded('openssl')) {
39781 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
39782
39783 return false;
39784 }
39785
39786 return true;
39787 }
39788
39789 private function getNextPage()
39790 {
39791 $headers = $this->remoteFilesystem->getLastHeaders();
39792 foreach ($headers as $header) {
39793 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
39794 $links = explode(',', $match[1]);
39795 foreach ($links as $link) {
39796 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
39797 return $match[1];
39798 }
39799 }
39800 }
39801 }
39802 }
39803
39804
39805
39806
39807
39808
39809
39810 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts, $portNumber)
39811 {
39812 $guessedDomain = strtolower($guessedDomain);
39813
39814 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array($guessedDomain.':'.$portNumber, $configuredDomains))) {
39815 if ($portNumber) {
39816 return $guessedDomain.':'.$portNumber;
39817 }
39818 return $guessedDomain;
39819 }
39820
39821 if ($portNumber) {
39822 $guessedDomain .= ':'.$portNumber;
39823 }
39824
39825 while (null !== ($part = array_shift($urlParts))) {
39826 $guessedDomain .= '/' . $part;
39827
39828 if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array(preg_replace('{:\d+}', '', $guessedDomain), $configuredDomains))) {
39829 return $guessedDomain;
39830 }
39831 }
39832
39833 return false;
39834 }
39835 }
39836 <?php
39837
39838
39839
39840
39841
39842
39843
39844
39845
39846
39847
39848 namespace Composer\Repository\Vcs;
39849
39850 use Composer\Config;
39851 use Composer\IO\IOInterface;
39852
39853
39854
39855
39856 class HgBitbucketDriver extends BitbucketDriver
39857 {
39858
39859
39860
39861 public function getRootIdentifier()
39862 {
39863 if ($this->fallbackDriver) {
39864 return $this->fallbackDriver->getRootIdentifier();
39865 }
39866
39867 if (null === $this->rootIdentifier) {
39868 if (! $this->getRepoData()) {
39869 return $this->fallbackDriver->getRootIdentifier();
39870 }
39871
39872 if ($this->vcsType !== 'hg') {
39873 throw new \RuntimeException(
39874 $this->url.' does not appear to be a mercurial repository, use '.
39875 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
39876 );
39877 }
39878
39879 $mainBranchData = $this->getMainBranchData();
39880 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
39881 }
39882
39883 return $this->rootIdentifier;
39884 }
39885
39886
39887
39888
39889 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
39890 {
39891 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#i', $url)) {
39892 return false;
39893 }
39894
39895 if (!extension_loaded('openssl')) {
39896 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
39897
39898 return false;
39899 }
39900
39901 return true;
39902 }
39903
39904
39905
39906
39907 protected function setupFallbackDriver($url)
39908 {
39909 $this->fallbackDriver = new HgDriver(
39910 array('url' => $url),
39911 $this->io,
39912 $this->config,
39913 $this->process,
39914 $this->remoteFilesystem
39915 );
39916 $this->fallbackDriver->initialize();
39917 }
39918
39919
39920
39921
39922 protected function generateSshUrl()
39923 {
39924 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
39925 }
39926 }
39927 <?php
39928
39929
39930
39931
39932
39933
39934
39935
39936
39937
39938
39939 namespace Composer\Repository\Vcs;
39940
39941 use Composer\Config;
39942 use Composer\Cache;
39943 use Composer\Util\Hg as HgUtils;
39944 use Composer\Util\ProcessExecutor;
39945 use Composer\Util\Filesystem;
39946 use Composer\IO\IOInterface;
39947
39948
39949
39950
39951 class HgDriver extends VcsDriver
39952 {
39953 protected $tags;
39954 protected $branches;
39955 protected $rootIdentifier;
39956 protected $repoDir;
39957 protected $infoCache = array();
39958
39959
39960
39961
39962 public function initialize()
39963 {
39964 if (Filesystem::isLocalPath($this->url)) {
39965 $this->repoDir = $this->url;
39966 } else {
39967 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
39968 throw new \RuntimeException('HgDriver requires a usable cache directory, and it looks like you set it to be disabled');
39969 }
39970
39971 $cacheDir = $this->config->get('cache-vcs-dir');
39972 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
39973
39974 $fs = new Filesystem();
39975 $fs->ensureDirectoryExists($cacheDir);
39976
39977 if (!is_writable(dirname($this->repoDir))) {
39978 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
39979 }
39980
39981
39982  $this->config->prohibitUrlByConfig($this->url, $this->io);
39983
39984 $hgUtils = new HgUtils($this->io, $this->config, $this->process);
39985
39986
39987  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
39988 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
39989 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
39990 }
39991 } else {
39992
39993  $fs->removeDirectory($this->repoDir);
39994
39995 $repoDir = $this->repoDir;
39996 $command = function ($url) use ($repoDir) {
39997 return sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
39998 };
39999
40000 $hgUtils->runCommand($command, $this->url, null);
40001 }
40002 }
40003
40004 $this->getTags();
40005 $this->getBranches();
40006 }
40007
40008
40009
40010
40011 public function getRootIdentifier()
40012 {
40013 if (null === $this->rootIdentifier) {
40014 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
40015 $output = $this->process->splitLines($output);
40016 $this->rootIdentifier = $output[0];
40017 }
40018
40019 return $this->rootIdentifier;
40020 }
40021
40022
40023
40024
40025 public function getUrl()
40026 {
40027 return $this->url;
40028 }
40029
40030
40031
40032
40033 public function getSource($identifier)
40034 {
40035 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
40036 }
40037
40038
40039
40040
40041 public function getDist($identifier)
40042 {
40043 return null;
40044 }
40045
40046
40047
40048
40049 public function getFileContent($file, $identifier)
40050 {
40051 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
40052 $this->process->execute($resource, $content, $this->repoDir);
40053
40054 if (!trim($content)) {
40055 return;
40056 }
40057
40058 return $content;
40059 }
40060
40061
40062
40063
40064 public function getChangeDate($identifier)
40065 {
40066 $this->process->execute(
40067 sprintf(
40068 'hg log --template "{date|rfc3339date}" -r %s',
40069 ProcessExecutor::escape($identifier)
40070 ),
40071 $output,
40072 $this->repoDir
40073 );
40074
40075 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
40076 }
40077
40078
40079
40080
40081 public function getTags()
40082 {
40083 if (null === $this->tags) {
40084 $tags = array();
40085
40086 $this->process->execute('hg tags', $output, $this->repoDir);
40087 foreach ($this->process->splitLines($output) as $tag) {
40088 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
40089 $tags[$match[1]] = $match[2];
40090 }
40091 }
40092 unset($tags['tip']);
40093
40094 $this->tags = $tags;
40095 }
40096
40097 return $this->tags;
40098 }
40099
40100
40101
40102
40103 public function getBranches()
40104 {
40105 if (null === $this->branches) {
40106 $branches = array();
40107 $bookmarks = array();
40108
40109 $this->process->execute('hg branches', $output, $this->repoDir);
40110 foreach ($this->process->splitLines($output) as $branch) {
40111 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
40112 $branches[$match[1]] = $match[2];
40113 }
40114 }
40115
40116 $this->process->execute('hg bookmarks', $output, $this->repoDir);
40117 foreach ($this->process->splitLines($output) as $branch) {
40118 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
40119 $bookmarks[$match[1]] = $match[2];
40120 }
40121 }
40122
40123
40124  $this->branches = array_merge($bookmarks, $branches);
40125 }
40126
40127 return $this->branches;
40128 }
40129
40130
40131
40132
40133 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
40134 {
40135 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
40136 return true;
40137 }
40138
40139
40140  if (Filesystem::isLocalPath($url)) {
40141 $url = Filesystem::getPlatformPath($url);
40142 if (!is_dir($url)) {
40143 return false;
40144 }
40145
40146 $process = new ProcessExecutor($io);
40147
40148  if ($process->execute('hg summary', $output, $url) === 0) {
40149 return true;
40150 }
40151 }
40152
40153 if (!$deep) {
40154 return false;
40155 }
40156
40157 $processExecutor = new ProcessExecutor($io);
40158 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
40159
40160 return $exit === 0;
40161 }
40162 }
40163 <?php
40164
40165
40166
40167
40168
40169
40170
40171
40172
40173
40174
40175 namespace Composer\Repository\Vcs;
40176
40177 use Composer\Config;
40178 use Composer\Cache;
40179 use Composer\IO\IOInterface;
40180 use Composer\Util\ProcessExecutor;
40181 use Composer\Util\Perforce;
40182
40183
40184
40185
40186 class PerforceDriver extends VcsDriver
40187 {
40188 protected $depot;
40189 protected $branch;
40190
40191 protected $perforce;
40192
40193
40194
40195
40196 public function initialize()
40197 {
40198 $this->depot = $this->repoConfig['depot'];
40199 $this->branch = '';
40200 if (!empty($this->repoConfig['branch'])) {
40201 $this->branch = $this->repoConfig['branch'];
40202 }
40203
40204 $this->initPerforce($this->repoConfig);
40205 $this->perforce->p4Login();
40206 $this->perforce->checkStream();
40207
40208 $this->perforce->writeP4ClientSpec();
40209 $this->perforce->connectClient();
40210
40211 return true;
40212 }
40213
40214 private function initPerforce($repoConfig)
40215 {
40216 if (!empty($this->perforce)) {
40217 return;
40218 }
40219
40220 if (!Cache::isUsable($this->config->get('cache-vcs-dir'))) {
40221 throw new \RuntimeException('PerforceDriver requires a usable cache directory, and it looks like you set it to be disabled');
40222 }
40223
40224 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
40225 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
40226 }
40227
40228
40229
40230
40231 public function getFileContent($file, $identifier)
40232 {
40233 return $this->perforce->getFileContent($file, $identifier);
40234 }
40235
40236
40237
40238
40239 public function getChangeDate($identifier)
40240 {
40241 return null;
40242 }
40243
40244
40245
40246
40247 public function getRootIdentifier()
40248 {
40249 return $this->branch;
40250 }
40251
40252
40253
40254
40255 public function getBranches()
40256 {
40257 return $this->perforce->getBranches();
40258 }
40259
40260
40261
40262
40263 public function getTags()
40264 {
40265 return $this->perforce->getTags();
40266 }
40267
40268
40269
40270
40271 public function getDist($identifier)
40272 {
40273 return null;
40274 }
40275
40276
40277
40278
40279 public function getSource($identifier)
40280 {
40281 $source = array(
40282 'type' => 'perforce',
40283 'url' => $this->repoConfig['url'],
40284 'reference' => $identifier,
40285 'p4user' => $this->perforce->getUser(),
40286 );
40287
40288 return $source;
40289 }
40290
40291
40292
40293
40294 public function getUrl()
40295 {
40296 return $this->url;
40297 }
40298
40299
40300
40301
40302 public function hasComposerFile($identifier)
40303 {
40304 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
40305 $composerInfoIdentifier = $identifier;
40306
40307 return !empty($composerInfo);
40308 }
40309
40310
40311
40312
40313 public function getContents($url)
40314 {
40315 return false;
40316 }
40317
40318
40319
40320
40321 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
40322 {
40323 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
40324 return Perforce::checkServerExists($url, new ProcessExecutor($io));
40325 }
40326
40327 return false;
40328 }
40329
40330
40331
40332
40333 public function cleanup()
40334 {
40335 $this->perforce->cleanupClientSpec();
40336 $this->perforce = null;
40337 }
40338
40339 public function getDepot()
40340 {
40341 return $this->depot;
40342 }
40343
40344 public function getBranch()
40345 {
40346 return $this->branch;
40347 }
40348 }
40349 <?php
40350
40351
40352
40353
40354
40355
40356
40357
40358
40359
40360
40361 namespace Composer\Repository\Vcs;
40362
40363 use Composer\Cache;
40364 use Composer\Config;
40365 use Composer\Json\JsonFile;
40366 use Composer\Util\ProcessExecutor;
40367 use Composer\Util\Filesystem;
40368 use Composer\Util\Svn as SvnUtil;
40369 use Composer\IO\IOInterface;
40370 use Composer\Downloader\TransportException;
40371
40372
40373
40374
40375
40376 class SvnDriver extends VcsDriver
40377 {
40378
40379
40380
40381 protected $cache;
40382 protected $baseUrl;
40383 protected $tags;
40384 protected $branches;
40385 protected $rootIdentifier;
40386 protected $infoCache = array();
40387
40388 protected $trunkPath = 'trunk';
40389 protected $branchesPath = 'branches';
40390 protected $tagsPath = 'tags';
40391 protected $packagePath = '';
40392 protected $cacheCredentials = true;
40393
40394
40395
40396
40397 private $util;
40398
40399
40400
40401
40402 public function initialize()
40403 {
40404 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
40405
40406 SvnUtil::cleanEnv();
40407
40408 if (isset($this->repoConfig['trunk-path'])) {
40409 $this->trunkPath = $this->repoConfig['trunk-path'];
40410 }
40411 if (isset($this->repoConfig['branches-path'])) {
40412 $this->branchesPath = $this->repoConfig['branches-path'];
40413 }
40414 if (isset($this->repoConfig['tags-path'])) {
40415 $this->tagsPath = $this->repoConfig['tags-path'];
40416 }
40417 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
40418 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
40419 }
40420 if (isset($this->repoConfig['package-path'])) {
40421 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
40422 }
40423
40424 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
40425 $this->baseUrl = substr($this->url, 0, $pos);
40426 }
40427
40428 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
40429
40430 $this->getBranches();
40431 $this->getTags();
40432 }
40433
40434
40435
40436
40437 public function getRootIdentifier()
40438 {
40439 return $this->rootIdentifier ?: $this->trunkPath;
40440 }
40441
40442
40443
40444
40445 public function getUrl()
40446 {
40447 return $this->url;
40448 }
40449
40450
40451
40452
40453 public function getSource($identifier)
40454 {
40455 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
40456 }
40457
40458
40459
40460
40461 public function getDist($identifier)
40462 {
40463 return null;
40464 }
40465
40466
40467
40468
40469 protected function shouldCache($identifier)
40470 {
40471 return $this->cache && preg_match('{@\d+$}', $identifier);
40472 }
40473
40474
40475
40476
40477 public function getComposerInformation($identifier)
40478 {
40479 if (!isset($this->infoCache[$identifier])) {
40480 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier.'.json')) {
40481 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
40482 }
40483
40484 try {
40485 $composer = $this->getBaseComposerInformation($identifier);
40486 } catch (TransportException $e) {
40487 $message = $e->getMessage();
40488 if (stripos($message, 'path not found') === false && stripos($message, 'svn: warning: W160013') === false) {
40489 throw $e;
40490 }
40491
40492  $composer = '';
40493 }
40494
40495 if ($this->shouldCache($identifier)) {
40496 $this->cache->write($identifier.'.json', json_encode($composer));
40497 }
40498
40499 $this->infoCache[$identifier] = $composer;
40500 }
40501
40502 return $this->infoCache[$identifier];
40503 }
40504
40505
40506
40507
40508
40509 public function getFileContent($file, $identifier)
40510 {
40511 $identifier = '/' . trim($identifier, '/') . '/';
40512
40513 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
40514 if (!empty($match[2])) {
40515 $path = $match[1];
40516 $rev = $match[2];
40517 } else {
40518 $path = $identifier;
40519 $rev = '';
40520 }
40521
40522 try {
40523 $resource = $path.$file;
40524 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
40525 if (!trim($output)) {
40526 return null;
40527 }
40528 } catch (\RuntimeException $e) {
40529 throw new TransportException($e->getMessage());
40530 }
40531
40532 return $output;
40533 }
40534
40535
40536
40537
40538 public function getChangeDate($identifier)
40539 {
40540 $identifier = '/' . trim($identifier, '/') . '/';
40541
40542 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
40543 if (!empty($match[2])) {
40544 $path = $match[1];
40545 $rev = $match[2];
40546 } else {
40547 $path = $identifier;
40548 $rev = '';
40549 }
40550
40551 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
40552 foreach ($this->process->splitLines($output) as $line) {
40553 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
40554 return new \DateTime($match[1], new \DateTimeZone('UTC'));
40555 }
40556 }
40557
40558 return null;
40559 }
40560
40561
40562
40563
40564 public function getTags()
40565 {
40566 if (null === $this->tags) {
40567 $this->tags = array();
40568
40569 if ($this->tagsPath !== false) {
40570 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
40571 if ($output) {
40572 foreach ($this->process->splitLines($output) as $line) {
40573 $line = trim($line);
40574 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
40575 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
40576 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
40577 '/' . $this->tagsPath . '/' . $match[2],
40578 $match[1]
40579 );
40580 }
40581 }
40582 }
40583 }
40584 }
40585 }
40586
40587 return $this->tags;
40588 }
40589
40590
40591
40592
40593 public function getBranches()
40594 {
40595 if (null === $this->branches) {
40596 $this->branches = array();
40597
40598 if (false === $this->trunkPath) {
40599 $trunkParent = $this->baseUrl . '/';
40600 } else {
40601 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
40602 }
40603
40604 $output = $this->execute('svn ls --verbose', $trunkParent);
40605 if ($output) {
40606 foreach ($this->process->splitLines($output) as $line) {
40607 $line = trim($line);
40608 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
40609 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
40610 $this->branches['trunk'] = $this->buildIdentifier(
40611 '/' . $this->trunkPath,
40612 $match[1]
40613 );
40614 $this->rootIdentifier = $this->branches['trunk'];
40615 break;
40616 }
40617 }
40618 }
40619 }
40620 unset($output);
40621
40622 if ($this->branchesPath !== false) {
40623 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
40624 if ($output) {
40625 foreach ($this->process->splitLines(trim($output)) as $line) {
40626 $line = trim($line);
40627 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
40628 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
40629 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
40630 '/' . $this->branchesPath . '/' . $match[2],
40631 $match[1]
40632 );
40633 }
40634 }
40635 }
40636 }
40637 }
40638 }
40639
40640 return $this->branches;
40641 }
40642
40643
40644
40645
40646 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
40647 {
40648 $url = self::normalizeUrl($url);
40649 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
40650 return true;
40651 }
40652
40653
40654  if (!$deep && !Filesystem::isLocalPath($url)) {
40655 return false;
40656 }
40657
40658 $processExecutor = new ProcessExecutor($io);
40659
40660 $exit = $processExecutor->execute(
40661 "svn info --non-interactive ".ProcessExecutor::escape($url),
40662 $ignoredOutput
40663 );
40664
40665 if ($exit === 0) {
40666
40667  return true;
40668 }
40669
40670
40671  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
40672
40673  
40674  return true;
40675 }
40676
40677
40678  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
40679
40680  
40681  return true;
40682 }
40683
40684 return false;
40685 }
40686
40687
40688
40689
40690
40691
40692
40693
40694 protected static function normalizeUrl($url)
40695 {
40696 $fs = new Filesystem();
40697 if ($fs->isAbsolutePath($url)) {
40698 return 'file://' . strtr($url, '\\', '/');
40699 }
40700
40701 return $url;
40702 }
40703
40704
40705
40706
40707
40708
40709
40710
40711
40712
40713 protected function execute($command, $url)
40714 {
40715 if (null === $this->util) {
40716 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
40717 $this->util->setCacheCredentials($this->cacheCredentials);
40718 }
40719
40720 try {
40721 return $this->util->execute($command, $url);
40722 } catch (\RuntimeException $e) {
40723 if (null === $this->util->binaryVersion()) {
40724 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());
40725 }
40726
40727 throw new \RuntimeException(
40728 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
40729 );
40730 }
40731 }
40732
40733
40734
40735
40736
40737
40738
40739
40740
40741 protected function buildIdentifier($baseDir, $revision)
40742 {
40743 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
40744 }
40745 }
40746 <?php
40747
40748
40749
40750
40751
40752
40753
40754
40755
40756
40757
40758 namespace Composer\Repository\Vcs;
40759
40760 use Composer\Cache;
40761 use Composer\Downloader\TransportException;
40762 use Composer\Config;
40763 use Composer\Factory;
40764 use Composer\IO\IOInterface;
40765 use Composer\Json\JsonFile;
40766 use Composer\Util\ProcessExecutor;
40767 use Composer\Util\RemoteFilesystem;
40768 use Composer\Util\Filesystem;
40769
40770
40771
40772
40773
40774
40775 abstract class VcsDriver implements VcsDriverInterface
40776 {
40777
40778 protected $url;
40779
40780 protected $originUrl;
40781
40782 protected $repoConfig;
40783
40784 protected $io;
40785
40786 protected $config;
40787
40788 protected $process;
40789
40790 protected $remoteFilesystem;
40791
40792 protected $infoCache = array();
40793
40794 protected $cache;
40795
40796
40797
40798
40799
40800
40801
40802
40803
40804
40805 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40806 {
40807 if (Filesystem::isLocalPath($repoConfig['url'])) {
40808 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
40809 }
40810
40811 $this->url = $repoConfig['url'];
40812 $this->originUrl = $repoConfig['url'];
40813 $this->repoConfig = $repoConfig;
40814 $this->io = $io;
40815 $this->config = $config;
40816 $this->process = $process ?: new ProcessExecutor($io);
40817 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40818 }
40819
40820
40821
40822
40823
40824
40825
40826 protected function shouldCache($identifier)
40827 {
40828 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
40829 }
40830
40831
40832
40833
40834 public function getComposerInformation($identifier)
40835 {
40836 if (!isset($this->infoCache[$identifier])) {
40837 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
40838 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
40839 }
40840
40841 $composer = $this->getBaseComposerInformation($identifier);
40842
40843 if ($this->shouldCache($identifier)) {
40844 $this->cache->write($identifier, json_encode($composer));
40845 }
40846
40847 $this->infoCache[$identifier] = $composer;
40848 }
40849
40850 return $this->infoCache[$identifier];
40851 }
40852
40853 protected function getBaseComposerInformation($identifier)
40854 {
40855 $composerFileContent = $this->getFileContent('composer.json', $identifier);
40856
40857 if (!$composerFileContent) {
40858 return null;
40859 }
40860
40861 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
40862
40863 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
40864 $composer['time'] = $changeDate->format(DATE_RFC3339);
40865 }
40866
40867 return $composer;
40868 }
40869
40870
40871
40872
40873 public function hasComposerFile($identifier)
40874 {
40875 try {
40876 return (bool) $this->getComposerInformation($identifier);
40877 } catch (TransportException $e) {
40878 }
40879
40880 return false;
40881 }
40882
40883
40884
40885
40886
40887
40888
40889
40890 protected function getScheme()
40891 {
40892 if (extension_loaded('openssl')) {
40893 return 'https';
40894 }
40895
40896 return 'http';
40897 }
40898
40899
40900
40901
40902
40903
40904
40905
40906 protected function getContents($url)
40907 {
40908 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
40909
40910 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
40911 }
40912
40913
40914
40915
40916 public function cleanup()
40917 {
40918 return;
40919 }
40920 }
40921 <?php
40922
40923
40924
40925
40926
40927
40928
40929
40930
40931
40932
40933 namespace Composer\Repository\Vcs;
40934
40935 use Composer\Config;
40936 use Composer\IO\IOInterface;
40937
40938
40939
40940
40941 interface VcsDriverInterface
40942 {
40943
40944
40945
40946 public function initialize();
40947
40948
40949
40950
40951
40952
40953
40954 public function getComposerInformation($identifier);
40955
40956
40957
40958
40959
40960
40961
40962
40963 public function getFileContent($file, $identifier);
40964
40965
40966
40967
40968
40969
40970
40971 public function getChangeDate($identifier);
40972
40973
40974
40975
40976
40977
40978 public function getRootIdentifier();
40979
40980
40981
40982
40983
40984
40985 public function getBranches();
40986
40987
40988
40989
40990
40991
40992 public function getTags();
40993
40994
40995
40996
40997
40998 public function getDist($identifier);
40999
41000
41001
41002
41003
41004 public function getSource($identifier);
41005
41006
41007
41008
41009
41010
41011 public function getUrl();
41012
41013
41014
41015
41016
41017
41018
41019
41020 public function hasComposerFile($identifier);
41021
41022
41023
41024
41025 public function cleanup();
41026
41027
41028
41029
41030
41031
41032
41033
41034
41035
41036 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
41037 }
41038 <?php
41039
41040
41041
41042
41043
41044
41045
41046
41047
41048
41049
41050 namespace Composer\Repository;
41051
41052 use Composer\Downloader\TransportException;
41053 use Composer\Repository\Vcs\VcsDriverInterface;
41054 use Composer\Package\Version\VersionParser;
41055 use Composer\Package\Loader\ArrayLoader;
41056 use Composer\Package\Loader\ValidatingArrayLoader;
41057 use Composer\Package\Loader\InvalidPackageException;
41058 use Composer\Package\Loader\LoaderInterface;
41059 use Composer\EventDispatcher\EventDispatcher;
41060 use Composer\Semver\Constraint\Constraint;
41061 use Composer\IO\IOInterface;
41062 use Composer\Config;
41063
41064
41065
41066
41067 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
41068 {
41069 protected $url;
41070 protected $packageName;
41071 protected $isVerbose;
41072 protected $isVeryVerbose;
41073 protected $io;
41074 protected $config;
41075 protected $versionParser;
41076 protected $type;
41077 protected $loader;
41078 protected $repoConfig;
41079 protected $branchErrorOccurred = false;
41080 private $drivers;
41081
41082 private $driver;
41083
41084 private $versionCache;
41085 private $emptyReferences = array();
41086 private $versionTransportExceptions = array();
41087
41088 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null, VersionCacheInterface $versionCache = null)
41089 {
41090 parent::__construct();
41091 $this->drivers = $drivers ?: array(
41092 'github' => 'Composer\Repository\Vcs\GitHubDriver',
41093 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
41094 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
41095 'git' => 'Composer\Repository\Vcs\GitDriver',
41096 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
41097 'hg' => 'Composer\Repository\Vcs\HgDriver',
41098 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
41099 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
41100
41101  'svn' => 'Composer\Repository\Vcs\SvnDriver',
41102 );
41103
41104 $this->url = $repoConfig['url'];
41105 $this->io = $io;
41106 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
41107 $this->isVerbose = $io->isVerbose();
41108 $this->isVeryVerbose = $io->isVeryVerbose();
41109 $this->config = $config;
41110 $this->repoConfig = $repoConfig;
41111 $this->versionCache = $versionCache;
41112 }
41113
41114 public function getRepoConfig()
41115 {
41116 return $this->repoConfig;
41117 }
41118
41119 public function setLoader(LoaderInterface $loader)
41120 {
41121 $this->loader = $loader;
41122 }
41123
41124 public function getDriver()
41125 {
41126 if ($this->driver) {
41127 return $this->driver;
41128 }
41129
41130 if (isset($this->drivers[$this->type])) {
41131 $class = $this->drivers[$this->type];
41132 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
41133 $this->driver->initialize();
41134
41135 return $this->driver;
41136 }
41137
41138 foreach ($this->drivers as $driver) {
41139 if ($driver::supports($this->io, $this->config, $this->url)) {
41140 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
41141 $this->driver->initialize();
41142
41143 return $this->driver;
41144 }
41145 }
41146
41147 foreach ($this->drivers as $driver) {
41148 if ($driver::supports($this->io, $this->config, $this->url, true)) {
41149 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
41150 $this->driver->initialize();
41151
41152 return $this->driver;
41153 }
41154 }
41155 }
41156
41157 public function hadInvalidBranches()
41158 {
41159 return $this->branchErrorOccurred;
41160 }
41161
41162 public function getEmptyReferences()
41163 {
41164 return $this->emptyReferences;
41165 }
41166
41167 public function getVersionTransportExceptions()
41168 {
41169 return $this->versionTransportExceptions;
41170 }
41171
41172 protected function initialize()
41173 {
41174 parent::initialize();
41175
41176 $isVerbose = $this->isVerbose;
41177 $isVeryVerbose = $this->isVeryVerbose;
41178
41179 $driver = $this->getDriver();
41180 if (!$driver) {
41181 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
41182 }
41183
41184 $this->versionParser = new VersionParser;
41185 if (!$this->loader) {
41186 $this->loader = new ArrayLoader($this->versionParser);
41187 }
41188
41189 try {
41190 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
41191 $data = $driver->getComposerInformation($driver->getRootIdentifier());
41192 $this->packageName = !empty($data['name']) ? $data['name'] : null;
41193 }
41194 } catch (\Exception $e) {
41195 if ($isVeryVerbose) {
41196 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
41197 }
41198 }
41199
41200 foreach ($driver->getTags() as $tag => $identifier) {
41201 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
41202 if ($isVeryVerbose) {
41203 $this->io->writeError($msg);
41204 } elseif ($isVerbose) {
41205 $this->io->overwriteError($msg, false);
41206 }
41207
41208
41209  $tag = str_replace('release-', '', $tag);
41210
41211 $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $isVerbose, $isVeryVerbose);
41212 if ($cachedPackage) {
41213 $this->addPackage($cachedPackage);
41214
41215 continue;
41216 } elseif ($cachedPackage === false) {
41217 $this->emptyReferences[] = $identifier;
41218
41219 continue;
41220 }
41221
41222 if (!$parsedTag = $this->validateTag($tag)) {
41223 if ($isVeryVerbose) {
41224 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
41225 }
41226 continue;
41227 }
41228
41229 try {
41230 if (!$data = $driver->getComposerInformation($identifier)) {
41231 if ($isVeryVerbose) {
41232 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
41233 }
41234 $this->emptyReferences[] = $identifier;
41235 continue;
41236 }
41237
41238
41239  if (isset($data['version'])) {
41240 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
41241 } else {
41242
41243  $data['version'] = $tag;
41244 $data['version_normalized'] = $parsedTag;
41245 }
41246
41247
41248  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
41249 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
41250
41251
41252  if ($data['version_normalized'] !== $parsedTag) {
41253 if ($isVeryVerbose) {
41254 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
41255 }
41256 continue;
41257 }
41258
41259 $tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
41260 if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
41261 if ($isVeryVerbose) {
41262 $this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
41263 }
41264 continue;
41265 }
41266
41267 if ($isVeryVerbose) {
41268 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
41269 }
41270
41271 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
41272 } catch (\Exception $e) {
41273 if ($e instanceof TransportException) {
41274 $this->versionTransportExceptions['tags'][$tag] = $e;
41275 if ($e->getCode() === 404) {
41276 $this->emptyReferences[] = $identifier;
41277 }
41278 }
41279 if ($isVeryVerbose) {
41280 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found (' . $e->getCode() . ' HTTP status code)' : $e->getMessage()).'</warning>');
41281 }
41282 continue;
41283 }
41284 }
41285
41286 if (!$isVeryVerbose) {
41287 $this->io->overwriteError('', false);
41288 }
41289
41290 $branches = $driver->getBranches();
41291 foreach ($branches as $branch => $identifier) {
41292 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
41293 if ($isVeryVerbose) {
41294 $this->io->writeError($msg);
41295 } elseif ($isVerbose) {
41296 $this->io->overwriteError($msg, false);
41297 }
41298
41299 if ($branch === 'trunk' && isset($branches['master'])) {
41300 if ($isVeryVerbose) {
41301 $this->io->writeError('<warning>Skipped branch '.$branch.', can not parse both master and trunk branches as they both resolve to 9999999-dev internally</warning>');
41302 }
41303 continue;
41304 }
41305
41306 if (!$parsedBranch = $this->validateBranch($branch)) {
41307 if ($isVeryVerbose) {
41308 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
41309 }
41310 continue;
41311 }
41312
41313
41314  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
41315 $version = 'dev-' . $branch;
41316 } else {
41317 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
41318 $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
41319 }
41320
41321 $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose);
41322 if ($cachedPackage) {
41323 $this->addPackage($cachedPackage);
41324
41325 continue;
41326 } elseif ($cachedPackage === false) {
41327 $this->emptyReferences[] = $identifier;
41328
41329 continue;
41330 }
41331
41332 try {
41333 if (!$data = $driver->getComposerInformation($identifier)) {
41334 if ($isVeryVerbose) {
41335 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
41336 }
41337 $this->emptyReferences[] = $identifier;
41338 continue;
41339 }
41340
41341
41342  $data['version'] = $version;
41343 $data['version_normalized'] = $parsedBranch;
41344
41345 if ($isVeryVerbose) {
41346 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
41347 }
41348
41349 $packageData = $this->preProcess($driver, $data, $identifier);
41350 $package = $this->loader->load($packageData);
41351 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
41352 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
41353 }
41354 $this->addPackage($package);
41355 } catch (TransportException $e) {
41356 $this->versionTransportExceptions['branches'][$branch] = $e;
41357 if ($e->getCode() === 404) {
41358 $this->emptyReferences[] = $identifier;
41359 }
41360 if ($isVeryVerbose) {
41361 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found (' . $e->getCode() . ' HTTP status code)</warning>');
41362 }
41363 continue;
41364 } catch (\Exception $e) {
41365 if (!$isVeryVerbose) {
41366 $this->io->writeError('');
41367 }
41368 $this->branchErrorOccurred = true;
41369 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
41370 $this->io->writeError('');
41371 continue;
41372 }
41373 }
41374 $driver->cleanup();
41375
41376 if (!$isVeryVerbose) {
41377 $this->io->overwriteError('', false);
41378 }
41379
41380 if (!$this->getPackages()) {
41381 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
41382 }
41383 }
41384
41385 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
41386 {
41387
41388  $dataPackageName = isset($data['name']) ? $data['name'] : null;
41389 $data['name'] = $this->packageName ?: $dataPackageName;
41390
41391 if (!isset($data['dist'])) {
41392 $data['dist'] = $driver->getDist($identifier);
41393 }
41394 if (!isset($data['source'])) {
41395 $data['source'] = $driver->getSource($identifier);
41396 }
41397
41398 return $data;
41399 }
41400
41401 private function validateBranch($branch)
41402 {
41403 try {
41404 $normalizedBranch = $this->versionParser->normalizeBranch($branch);
41405
41406
41407  $this->versionParser->parseConstraints($normalizedBranch);
41408
41409 return $normalizedBranch;
41410 } catch (\Exception $e) {
41411 }
41412
41413 return false;
41414 }
41415
41416 private function validateTag($version)
41417 {
41418 try {
41419 return $this->versionParser->normalize($version);
41420 } catch (\Exception $e) {
41421 }
41422
41423 return false;
41424 }
41425
41426 private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose)
41427 {
41428 if (!$this->versionCache) {
41429 return;
41430 }
41431
41432 $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
41433 if ($cachedPackage === false) {
41434 if ($isVeryVerbose) {
41435 $this->io->writeError('<warning>Skipped '.$version.', no composer file (cached from ref '.$identifier.')</warning>');
41436 }
41437
41438 return false;
41439 }
41440
41441 if ($cachedPackage) {
41442 $msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
41443 if ($isVeryVerbose) {
41444 $this->io->writeError($msg);
41445 } elseif ($isVerbose) {
41446 $this->io->overwriteError($msg, false);
41447 }
41448
41449 if ($existingPackage = $this->findPackage($cachedPackage['name'], new Constraint('=', $cachedPackage['version_normalized']))) {
41450 if ($isVeryVerbose) {
41451 $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>');
41452 }
41453 $cachedPackage = null;
41454 }
41455 }
41456
41457 if ($cachedPackage) {
41458 return $this->loader->load($cachedPackage);
41459 }
41460
41461 return null;
41462 }
41463 }
41464 <?php
41465
41466
41467
41468
41469
41470
41471
41472
41473
41474
41475
41476 namespace Composer\Repository;
41477
41478 interface VersionCacheInterface
41479 {
41480
41481
41482
41483
41484
41485 public function getVersionPackage($version, $identifier);
41486 }
41487 <?php
41488
41489
41490
41491
41492
41493
41494
41495
41496
41497
41498
41499 namespace Composer\Repository;
41500
41501 use Composer\Package\AliasPackage;
41502
41503
41504
41505
41506
41507
41508 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
41509 {
41510
41511
41512
41513 public function write()
41514 {
41515 }
41516
41517
41518
41519
41520 public function reload()
41521 {
41522 }
41523
41524
41525
41526
41527 public function getCanonicalPackages()
41528 {
41529 $packages = $this->getPackages();
41530
41531
41532  $packagesByName = array();
41533 foreach ($packages as $package) {
41534 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
41535 $packagesByName[$package->getName()] = $package;
41536 }
41537 }
41538
41539 $canonicalPackages = array();
41540
41541
41542  foreach ($packagesByName as $package) {
41543 while ($package instanceof AliasPackage) {
41544 $package = $package->getAliasOf();
41545 }
41546
41547 $canonicalPackages[] = $package;
41548 }
41549
41550 return $canonicalPackages;
41551 }
41552 }
41553 <?php
41554
41555
41556
41557
41558
41559
41560
41561
41562
41563
41564
41565 namespace Composer\Repository;
41566
41567 use Composer\Package\PackageInterface;
41568
41569
41570
41571
41572
41573
41574 interface WritableRepositoryInterface extends RepositoryInterface
41575 {
41576
41577
41578
41579 public function write();
41580
41581
41582
41583
41584
41585
41586 public function addPackage(PackageInterface $package);
41587
41588
41589
41590
41591
41592
41593 public function removePackage(PackageInterface $package);
41594
41595
41596
41597
41598
41599
41600 public function getCanonicalPackages();
41601
41602
41603
41604
41605 public function reload();
41606 }
41607 <?php
41608
41609
41610
41611
41612
41613
41614
41615
41616
41617
41618
41619 namespace Composer\Script;
41620
41621
41622
41623
41624
41625
41626 class CommandEvent extends Event
41627 {
41628 }
41629 <?php
41630
41631
41632
41633
41634
41635
41636
41637
41638
41639
41640
41641 namespace Composer\Script;
41642
41643 use Composer\Composer;
41644 use Composer\IO\IOInterface;
41645 use Composer\EventDispatcher\Event as BaseEvent;
41646
41647
41648
41649
41650
41651
41652
41653 class Event extends BaseEvent
41654 {
41655
41656
41657
41658 private $composer;
41659
41660
41661
41662
41663 private $io;
41664
41665
41666
41667
41668 private $devMode;
41669
41670
41671
41672
41673 private $originatingEvent;
41674
41675
41676
41677
41678
41679
41680
41681
41682
41683
41684
41685 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
41686 {
41687 parent::__construct($name, $args, $flags);
41688 $this->composer = $composer;
41689 $this->io = $io;
41690 $this->devMode = $devMode;
41691 $this->originatingEvent = null;
41692 }
41693
41694
41695
41696
41697
41698
41699 public function getComposer()
41700 {
41701 return $this->composer;
41702 }
41703
41704
41705
41706
41707
41708
41709 public function getIO()
41710 {
41711 return $this->io;
41712 }
41713
41714
41715
41716
41717
41718
41719 public function isDevMode()
41720 {
41721 return $this->devMode;
41722 }
41723
41724
41725
41726
41727
41728
41729 public function getOriginatingEvent()
41730 {
41731 return $this->originatingEvent;
41732 }
41733
41734
41735
41736
41737
41738
41739
41740 public function setOriginatingEvent(BaseEvent $event)
41741 {
41742 $this->originatingEvent = $this->calculateOriginatingEvent($event);
41743
41744 return $this;
41745 }
41746
41747
41748
41749
41750
41751
41752
41753 private function calculateOriginatingEvent(BaseEvent $event)
41754 {
41755 if ($event instanceof Event && $event->getOriginatingEvent()) {
41756 return $this->calculateOriginatingEvent($event->getOriginatingEvent());
41757 }
41758
41759 return $event;
41760 }
41761 }
41762 <?php
41763
41764
41765
41766
41767
41768
41769
41770
41771
41772
41773
41774 namespace Composer\Script;
41775
41776 use Composer\Installer\PackageEvent as BasePackageEvent;
41777
41778
41779
41780
41781
41782
41783 class PackageEvent extends BasePackageEvent
41784 {
41785 }
41786 <?php
41787
41788
41789
41790
41791
41792
41793
41794
41795
41796
41797
41798 namespace Composer\Script;
41799
41800
41801
41802
41803
41804
41805
41806 class ScriptEvents
41807 {
41808
41809
41810
41811
41812
41813
41814
41815 const PRE_INSTALL_CMD = 'pre-install-cmd';
41816
41817
41818
41819
41820
41821
41822
41823
41824 const POST_INSTALL_CMD = 'post-install-cmd';
41825
41826
41827
41828
41829
41830
41831
41832
41833 const PRE_UPDATE_CMD = 'pre-update-cmd';
41834
41835
41836
41837
41838
41839
41840
41841
41842 const POST_UPDATE_CMD = 'post-update-cmd';
41843
41844
41845
41846
41847
41848
41849
41850
41851 const PRE_STATUS_CMD = 'pre-status-cmd';
41852
41853
41854
41855
41856
41857
41858
41859
41860 const POST_STATUS_CMD = 'post-status-cmd';
41861
41862
41863
41864
41865
41866
41867
41868
41869 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
41870
41871
41872
41873
41874
41875
41876
41877
41878 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
41879
41880
41881
41882
41883
41884
41885
41886
41887 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
41888
41889
41890
41891
41892
41893
41894
41895
41896
41897 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
41898
41899
41900
41901
41902
41903
41904
41905
41906 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
41907
41908
41909
41910
41911
41912
41913
41914
41915 const POST_ARCHIVE_CMD = 'post-archive-cmd';
41916
41917
41918
41919
41920
41921
41922
41923
41924
41925
41926
41927 const PRE_PACKAGE_INSTALL = 'pre-package-install';
41928
41929
41930
41931
41932
41933
41934
41935
41936
41937 const POST_PACKAGE_INSTALL = 'post-package-install';
41938
41939
41940
41941
41942
41943
41944
41945
41946
41947 const PRE_PACKAGE_UPDATE = 'pre-package-update';
41948
41949
41950
41951
41952
41953
41954
41955
41956
41957 const POST_PACKAGE_UPDATE = 'post-package-update';
41958
41959
41960
41961
41962
41963
41964
41965
41966
41967 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
41968
41969
41970
41971
41972
41973
41974
41975
41976
41977 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
41978 }
41979 <?php
41980
41981
41982
41983
41984
41985
41986
41987
41988
41989
41990
41991 namespace Composer\SelfUpdate;
41992
41993
41994
41995
41996 class Keys
41997 {
41998 public static function fingerprint($path)
41999 {
42000 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
42001
42002 return implode(' ', array(
42003 substr($hash, 0, 8),
42004 substr($hash, 8, 8),
42005 substr($hash, 16, 8),
42006 substr($hash, 24, 8),
42007 '', 
42008  substr($hash, 32, 8),
42009 substr($hash, 40, 8),
42010 substr($hash, 48, 8),
42011 substr($hash, 56, 8),
42012 ));
42013 }
42014 }
42015 <?php
42016
42017
42018
42019
42020
42021
42022
42023
42024
42025
42026
42027 namespace Composer\SelfUpdate;
42028
42029 use Composer\Util\RemoteFilesystem;
42030 use Composer\Config;
42031 use Composer\Json\JsonFile;
42032
42033
42034
42035
42036 class Versions
42037 {
42038 public static $channels = array('stable', 'preview', 'snapshot', '1', '2');
42039
42040 private $rfs;
42041 private $config;
42042 private $channel;
42043
42044 public function __construct(Config $config, RemoteFilesystem $rfs)
42045 {
42046 $this->rfs = $rfs;
42047 $this->config = $config;
42048 }
42049
42050 public function getChannel()
42051 {
42052 if ($this->channel) {
42053 return $this->channel;
42054 }
42055
42056 $channelFile = $this->config->get('home').'/update-channel';
42057 if (file_exists($channelFile)) {
42058 $channel = trim(file_get_contents($channelFile));
42059 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
42060 return $this->channel = $channel;
42061 }
42062 }
42063
42064 return $this->channel = 'stable';
42065 }
42066
42067 public function setChannel($channel)
42068 {
42069 if (!in_array($channel, self::$channels, true)) {
42070 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: ' . implode(', ', self::$channels));
42071 }
42072
42073 $channelFile = $this->config->get('home').'/update-channel';
42074 $this->channel = $channel;
42075 file_put_contents($channelFile, (is_numeric($channel) ? 'stable' : $channel).PHP_EOL);
42076 }
42077
42078 public function getLatest($channel = null)
42079 {
42080 $protocol = extension_loaded('openssl') ? 'https' : 'http';
42081 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
42082
42083 foreach ($versions[$channel ?: $this->getChannel()] as $version) {
42084 if ($version['min-php'] <= PHP_VERSION_ID) {
42085 return $version;
42086 }
42087 }
42088
42089 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
42090 }
42091 }
42092 <?php
42093
42094
42095
42096
42097
42098
42099
42100
42101
42102
42103
42104 namespace Composer\Util;
42105
42106 use Composer\Config;
42107 use Composer\IO\IOInterface;
42108
42109
42110
42111
42112 class AuthHelper
42113 {
42114 protected $io;
42115 protected $config;
42116
42117 public function __construct(IOInterface $io, Config $config)
42118 {
42119 $this->io = $io;
42120 $this->config = $config;
42121 }
42122
42123 public function storeAuth($originUrl, $storeAuth)
42124 {
42125 $store = false;
42126 $configSource = $this->config->getAuthConfigSource();
42127 if ($storeAuth === true) {
42128 $store = $configSource;
42129 } elseif ($storeAuth === 'prompt') {
42130 $answer = $this->io->askAndValidate(
42131 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
42132 function ($value) {
42133 $input = strtolower(substr(trim($value), 0, 1));
42134 if (in_array($input, array('y','n'))) {
42135 return $input;
42136 }
42137 throw new \RuntimeException('Please answer (y)es or (n)o');
42138 },
42139 null,
42140 'y'
42141 );
42142
42143 if ($answer === 'y') {
42144 $store = $configSource;
42145 }
42146 }
42147 if ($store) {
42148 $store->addConfigSetting(
42149 'http-basic.'.$originUrl,
42150 $this->io->getAuthentication($originUrl)
42151 );
42152 }
42153 }
42154 }
42155 <?php
42156
42157
42158
42159
42160
42161
42162
42163
42164
42165
42166
42167 namespace Composer\Util;
42168
42169 use Composer\Factory;
42170 use Composer\IO\IOInterface;
42171 use Composer\Config;
42172 use Composer\Downloader\TransportException;
42173
42174
42175
42176
42177 class Bitbucket
42178 {
42179 private $io;
42180 private $config;
42181 private $process;
42182 private $remoteFilesystem;
42183 private $token = array();
42184 private $time;
42185
42186 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
42187
42188
42189
42190
42191
42192
42193
42194
42195
42196
42197 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
42198 {
42199 $this->io = $io;
42200 $this->config = $config;
42201 $this->process = $process ?: new ProcessExecutor($io);
42202 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
42203 $this->time = $time;
42204 }
42205
42206
42207
42208
42209 public function getToken()
42210 {
42211 if (!isset($this->token['access_token'])) {
42212 return '';
42213 }
42214
42215 return $this->token['access_token'];
42216 }
42217
42218
42219
42220
42221
42222
42223
42224 public function authorizeOAuth($originUrl)
42225 {
42226 if ($originUrl !== 'bitbucket.org') {
42227 return false;
42228 }
42229
42230
42231  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
42232 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
42233
42234 return true;
42235 }
42236
42237 return false;
42238 }
42239
42240
42241
42242
42243
42244 private function requestAccessToken($originUrl)
42245 {
42246 try {
42247 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
42248 'retry-auth-failure' => false,
42249 'http' => array(
42250 'method' => 'POST',
42251 'content' => 'grant_type=client_credentials',
42252 ),
42253 ));
42254
42255 $this->token = json_decode($json, true);
42256 } catch (TransportException $e) {
42257 if ($e->getCode() === 400) {
42258 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
42259 $this->io->writeError('This can have two reasons:');
42260 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
42261 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
42262
42263 return false;
42264 } elseif (in_array($e->getCode(), array(403, 401))) {
42265 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
42266 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
42267
42268 return false;
42269 }
42270
42271 throw $e;
42272 }
42273
42274 return true;
42275 }
42276
42277
42278
42279
42280
42281
42282
42283
42284
42285
42286 public function authorizeOAuthInteractively($originUrl, $message = null)
42287 {
42288 if ($message) {
42289 $this->io->writeError($message);
42290 }
42291
42292 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
42293 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
42294 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
42295 $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)');
42296
42297 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
42298
42299 if (!$consumerKey) {
42300 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
42301 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
42302
42303 return false;
42304 }
42305
42306 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
42307
42308 if (!$consumerSecret) {
42309 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
42310 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
42311
42312 return false;
42313 }
42314
42315 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
42316
42317 if (!$this->requestAccessToken($originUrl)) {
42318 return false;
42319 }
42320
42321
42322  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
42323
42324
42325  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
42326
42327 $this->io->writeError('<info>Consumer stored successfully.</info>');
42328
42329 return true;
42330 }
42331
42332
42333
42334
42335
42336
42337
42338
42339
42340 public function requestToken($originUrl, $consumerKey, $consumerSecret)
42341 {
42342 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
42343 return $this->token['access_token'];
42344 }
42345
42346 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
42347 if (!$this->requestAccessToken($originUrl)) {
42348 return '';
42349 }
42350
42351 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
42352
42353 return $this->token['access_token'];
42354 }
42355
42356
42357
42358
42359
42360
42361
42362 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
42363 {
42364 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
42365
42366 $time = null === $this->time ? time() : $this->time;
42367 $consumer = array(
42368 "consumer-key" => $consumerKey,
42369 "consumer-secret" => $consumerSecret,
42370 "access-token" => $this->token['access_token'],
42371 "access-token-expiration" => $time + $this->token['expires_in'],
42372 );
42373
42374 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
42375 }
42376
42377
42378
42379
42380
42381 private function getTokenFromConfig($originUrl)
42382 {
42383 $authConfig = $this->config->get('bitbucket-oauth');
42384
42385 if (
42386 !isset($authConfig[$originUrl]['access-token'])
42387 || !isset($authConfig[$originUrl]['access-token-expiration'])
42388 || time() > $authConfig[$originUrl]['access-token-expiration']
42389 ) {
42390 return false;
42391 }
42392
42393 $this->token = array(
42394 'access_token' => $authConfig[$originUrl]['access-token'],
42395 );
42396
42397 return true;
42398 }
42399 }
42400 <?php
42401
42402
42403
42404
42405
42406
42407
42408
42409
42410
42411
42412 namespace Composer\Util;
42413
42414
42415
42416
42417
42418
42419 class ComposerMirror
42420 {
42421 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
42422 {
42423 if ($reference) {
42424 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
42425 }
42426 $version = strpos($version, '/') === false ? $version : md5($version);
42427
42428 return str_replace(
42429 array('%package%', '%version%', '%reference%', '%type%'),
42430 array($packageName, $version, $reference, $type),
42431 $mirrorUrl
42432 );
42433 }
42434
42435 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
42436 {
42437 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
42438 $url = 'gh-'.$match[1].'/'.$match[2];
42439 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
42440 $url = 'bb-'.$match[1].'/'.$match[2];
42441 } else {
42442 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
42443 }
42444
42445 return str_replace(
42446 array('%package%', '%normalizedUrl%', '%type%'),
42447 array($packageName, $url, $type),
42448 $mirrorUrl
42449 );
42450 }
42451
42452 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
42453 {
42454 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
42455 }
42456 }
42457 <?php
42458
42459
42460
42461
42462
42463
42464
42465
42466
42467
42468
42469 namespace Composer\Util;
42470
42471 use Composer\Package\Loader\ArrayLoader;
42472 use Composer\Package\Loader\ValidatingArrayLoader;
42473 use Composer\Package\Loader\InvalidPackageException;
42474 use Composer\Json\JsonValidationException;
42475 use Composer\IO\IOInterface;
42476 use Composer\Json\JsonFile;
42477 use Composer\Spdx\SpdxLicenses;
42478
42479
42480
42481
42482
42483
42484
42485 class ConfigValidator
42486 {
42487 private $io;
42488
42489 public function __construct(IOInterface $io)
42490 {
42491 $this->io = $io;
42492 }
42493
42494
42495
42496
42497
42498
42499
42500
42501
42502 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
42503 {
42504 $errors = array();
42505 $publishErrors = array();
42506 $warnings = array();
42507
42508
42509  $laxValid = false;
42510 try {
42511 $json = new JsonFile($file, null, $this->io);
42512 $manifest = $json->read();
42513
42514 $json->validateSchema(JsonFile::LAX_SCHEMA);
42515 $laxValid = true;
42516 $json->validateSchema();
42517 } catch (JsonValidationException $e) {
42518 foreach ($e->getErrors() as $message) {
42519 if ($laxValid) {
42520 $publishErrors[] = $message;
42521 } else {
42522 $errors[] = $message;
42523 }
42524 }
42525 } catch (\Exception $e) {
42526 $errors[] = $e->getMessage();
42527
42528 return array($errors, $publishErrors, $warnings);
42529 }
42530
42531
42532  if (empty($manifest['license'])) {
42533 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
42534 } else {
42535 $licenses = (array) $manifest['license'];
42536
42537
42538  foreach ($licenses as $key => $license) {
42539 if ('proprietary' === $license) {
42540 unset($licenses[$key]);
42541 }
42542 }
42543
42544 $licenseValidator = new SpdxLicenses();
42545 foreach ($licenses as $license) {
42546 $spdxLicense = $licenseValidator->getLicenseByIdentifier($license);
42547 if ($spdxLicense && $spdxLicense[3]) {
42548 if (preg_match('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) {
42549 $warnings[] = sprintf(
42550 'License "%s" is a deprecated SPDX license identifier, use "'.str_replace('+', '', $license).'-or-later" instead',
42551 $license
42552 );
42553 } elseif (preg_match('{^[AL]?GPL-[123](\.[01])?$}i', $license)) {
42554 $warnings[] = sprintf(
42555 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead',
42556 $license
42557 );
42558 } else {
42559 $warnings[] = sprintf(
42560 'License "%s" is a deprecated SPDX license identifier, see https://spdx.org/licenses/',
42561 $license
42562 );
42563 }
42564 }
42565 }
42566 }
42567
42568 if (isset($manifest['version'])) {
42569 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
42570 }
42571
42572 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
42573 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
42574 $suggestName = strtolower($suggestName);
42575
42576 $publishErrors[] = sprintf(
42577 '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.',
42578 $manifest['name'],
42579 $suggestName
42580 );
42581 }
42582
42583 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
42584 $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.";
42585 }
42586
42587
42588  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
42589 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
42590
42591 if (!empty($requireOverrides)) {
42592 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
42593 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
42594 }
42595 }
42596
42597
42598  $require = isset($manifest['require']) ? $manifest['require'] : array();
42599 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
42600 $packages = array_merge($require, $requireDev);
42601 foreach ($packages as $package => $version) {
42602 if (preg_match('/#/', $version) === 1) {
42603 $warnings[] = sprintf(
42604 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
42605 $package
42606 );
42607 }
42608 }
42609
42610
42611  $scriptsDescriptions = isset($manifest['scripts-descriptions']) ? $manifest['scripts-descriptions'] : array();
42612 $scripts = isset($manifest['scripts']) ? $manifest['scripts'] : array();
42613 foreach ($scriptsDescriptions as $scriptName => $scriptDescription) {
42614 if (!array_key_exists($scriptName, $scripts)) {
42615 $warnings[] = sprintf(
42616 'Description for non-existent script "%s" found in "scripts-descriptions"',
42617 $scriptName
42618 );
42619 }
42620 }
42621
42622
42623  if (isset($manifest['autoload']['psr-0'][''])) {
42624 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
42625 }
42626 if (isset($manifest['autoload']['psr-4'][''])) {
42627 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
42628 }
42629
42630 try {
42631 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
42632 if (!isset($manifest['version'])) {
42633 $manifest['version'] = '1.0.0';
42634 }
42635 if (!isset($manifest['name'])) {
42636 $manifest['name'] = 'dummy/dummy';
42637 }
42638 $loader->load($manifest);
42639 } catch (InvalidPackageException $e) {
42640 $errors = array_merge($errors, $e->getErrors());
42641 }
42642
42643 $warnings = array_merge($warnings, $loader->getWarnings());
42644
42645 return array($errors, $publishErrors, $warnings);
42646 }
42647 }
42648 <?php
42649
42650
42651
42652
42653
42654
42655
42656
42657
42658
42659
42660 namespace Composer\Util;
42661
42662 use Composer\IO\IOInterface;
42663
42664
42665
42666
42667
42668
42669 class ErrorHandler
42670 {
42671 private static $io;
42672
42673
42674
42675
42676
42677
42678
42679
42680
42681
42682
42683
42684
42685 public static function handle($level, $message, $file, $line)
42686 {
42687
42688  if (!(error_reporting() & $level)) {
42689 return;
42690 }
42691
42692 if (filter_var(ini_get('xdebug.scream'), FILTER_VALIDATE_BOOLEAN)) {
42693 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
42694 "\na legitimately suppressed error that you were not supposed to see.";
42695 }
42696
42697 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
42698 throw new \ErrorException($message, 0, $level, $file, $line);
42699 }
42700
42701 if (self::$io) {
42702 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
42703 if (self::$io->isVerbose()) {
42704 self::$io->writeError('<warning>Stack trace:</warning>');
42705 self::$io->writeError(array_filter(array_map(function ($a) {
42706 if (isset($a['line'], $a['file'])) {
42707 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
42708 }
42709
42710 return null;
42711 }, array_slice(debug_backtrace(), 2))));
42712 }
42713 }
42714
42715 return true;
42716 }
42717
42718
42719
42720
42721
42722
42723 public static function register(IOInterface $io = null)
42724 {
42725 set_error_handler(array(__CLASS__, 'handle'));
42726 error_reporting(E_ALL | E_STRICT);
42727 self::$io = $io;
42728 }
42729 }
42730 <?php
42731
42732
42733
42734
42735
42736
42737
42738
42739
42740
42741
42742 namespace Composer\Util;
42743
42744 use RecursiveDirectoryIterator;
42745 use RecursiveIteratorIterator;
42746 use Symfony\Component\Filesystem\Exception\IOException;
42747 use Symfony\Component\Finder\Finder;
42748
42749
42750
42751
42752
42753 class Filesystem
42754 {
42755 private $processExecutor;
42756
42757 public function __construct(ProcessExecutor $executor = null)
42758 {
42759 $this->processExecutor = $executor ?: new ProcessExecutor();
42760 }
42761
42762 public function remove($file)
42763 {
42764 if (is_dir($file)) {
42765 return $this->removeDirectory($file);
42766 }
42767
42768 if (file_exists($file)) {
42769 return $this->unlink($file);
42770 }
42771
42772 return false;
42773 }
42774
42775
42776
42777
42778
42779
42780
42781 public function isDirEmpty($dir)
42782 {
42783 $finder = Finder::create()
42784 ->ignoreVCS(false)
42785 ->ignoreDotFiles(false)
42786 ->depth(0)
42787 ->in($dir);
42788
42789 return count($finder) === 0;
42790 }
42791
42792 public function emptyDirectory($dir, $ensureDirectoryExists = true)
42793 {
42794 if (file_exists($dir) && is_link($dir)) {
42795 $this->unlink($dir);
42796 }
42797
42798 if ($ensureDirectoryExists) {
42799 $this->ensureDirectoryExists($dir);
42800 }
42801
42802 if (is_dir($dir)) {
42803 $finder = Finder::create()
42804 ->ignoreVCS(false)
42805 ->ignoreDotFiles(false)
42806 ->depth(0)
42807 ->in($dir);
42808
42809 foreach ($finder as $path) {
42810 $this->remove((string) $path);
42811 }
42812 }
42813 }
42814
42815
42816
42817
42818
42819
42820
42821
42822
42823
42824
42825 public function removeDirectory($directory)
42826 {
42827 if ($this->isSymlinkedDirectory($directory)) {
42828 return $this->unlinkSymlinkedDirectory($directory);
42829 }
42830
42831 if ($this->isJunction($directory)) {
42832 return $this->removeJunction($directory);
42833 }
42834
42835 if (is_link($directory)) {
42836 return unlink($directory);
42837 }
42838
42839 if (!file_exists($directory) || !is_dir($directory)) {
42840 return true;
42841 }
42842
42843 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
42844 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
42845 }
42846
42847 if (!function_exists('proc_open')) {
42848 return $this->removeDirectoryPhp($directory);
42849 }
42850
42851 if (Platform::isWindows()) {
42852 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
42853 } else {
42854 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
42855 }
42856
42857 $result = $this->getProcess()->execute($cmd, $output) === 0;
42858
42859
42860  clearstatcache();
42861
42862 if ($result && !file_exists($directory)) {
42863 return true;
42864 }
42865
42866 return $this->removeDirectoryPhp($directory);
42867 }
42868
42869
42870
42871
42872
42873
42874
42875
42876
42877
42878
42879 public function removeDirectoryPhp($directory)
42880 {
42881 try {
42882 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
42883 } catch (\UnexpectedValueException $e) {
42884
42885  
42886  clearstatcache();
42887 usleep(100000);
42888 if (!is_dir($directory)) {
42889 return true;
42890 }
42891 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
42892 }
42893 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
42894
42895 foreach ($ri as $file) {
42896 if ($file->isDir()) {
42897 $this->rmdir($file->getPathname());
42898 } else {
42899 $this->unlink($file->getPathname());
42900 }
42901 }
42902
42903 return $this->rmdir($directory);
42904 }
42905
42906 public function ensureDirectoryExists($directory)
42907 {
42908 if (!is_dir($directory)) {
42909 if (file_exists($directory)) {
42910 throw new \RuntimeException(
42911 $directory.' exists and is not a directory.'
42912 );
42913 }
42914 if (!@mkdir($directory, 0777, true)) {
42915 throw new \RuntimeException(
42916 $directory.' does not exist and could not be created.'
42917 );
42918 }
42919 }
42920 }
42921
42922
42923
42924
42925
42926
42927
42928
42929 public function unlink($path)
42930 {
42931 $unlinked = @$this->unlinkImplementation($path);
42932 if (!$unlinked) {
42933
42934  if (Platform::isWindows()) {
42935 usleep(350000);
42936 $unlinked = @$this->unlinkImplementation($path);
42937 }
42938
42939 if (!$unlinked) {
42940 $error = error_get_last();
42941 $message = 'Could not delete '.$path.': ' . @$error['message'];
42942 if (Platform::isWindows()) {
42943 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
42944 }
42945
42946 throw new \RuntimeException($message);
42947 }
42948 }
42949
42950 return true;
42951 }
42952
42953
42954
42955
42956
42957
42958
42959
42960 public function rmdir($path)
42961 {
42962 $deleted = @rmdir($path);
42963 if (!$deleted) {
42964
42965  if (Platform::isWindows()) {
42966 usleep(350000);
42967 $deleted = @rmdir($path);
42968 }
42969
42970 if (!$deleted) {
42971 $error = error_get_last();
42972 $message = 'Could not delete '.$path.': ' . @$error['message'];
42973 if (Platform::isWindows()) {
42974 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
42975 }
42976
42977 throw new \RuntimeException($message);
42978 }
42979 }
42980
42981 return true;
42982 }
42983
42984
42985
42986
42987
42988
42989
42990
42991
42992
42993 public function copyThenRemove($source, $target)
42994 {
42995 $this->copy($source, $target);
42996 if (!is_dir($source)) {
42997 $this->unlink($source);
42998
42999 return;
43000 }
43001
43002 $this->removeDirectoryPhp($source);
43003 }
43004
43005
43006
43007
43008
43009
43010
43011
43012 public function copy($source, $target)
43013 {
43014 if (!is_dir($source)) {
43015 return copy($source, $target);
43016 }
43017
43018 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
43019 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
43020 $this->ensureDirectoryExists($target);
43021
43022 $result = true;
43023 foreach ($ri as $file) {
43024 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
43025 if ($file->isDir()) {
43026 $this->ensureDirectoryExists($targetPath);
43027 } else {
43028 $result = $result && copy($file->getPathname(), $targetPath);
43029 }
43030 }
43031
43032 return $result;
43033 }
43034
43035 public function rename($source, $target)
43036 {
43037 if (true === @rename($source, $target)) {
43038 return;
43039 }
43040
43041 if (!function_exists('proc_open')) {
43042 $this->copyThenRemove($source, $target);
43043
43044 return;
43045 }
43046
43047 if (Platform::isWindows()) {
43048
43049  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
43050 $result = $this->processExecutor->execute($command, $output);
43051
43052
43053  clearstatcache();
43054
43055 if (0 === $result) {
43056 $this->remove($source);
43057
43058 return;
43059 }
43060 } else {
43061
43062  
43063  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
43064 $result = $this->processExecutor->execute($command, $output);
43065
43066
43067  clearstatcache();
43068
43069 if (0 === $result) {
43070 return;
43071 }
43072 }
43073
43074 $this->copyThenRemove($source, $target);
43075 }
43076
43077
43078
43079
43080
43081
43082
43083
43084
43085
43086 public function findShortestPath($from, $to, $directories = false)
43087 {
43088 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
43089 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
43090 }
43091
43092 $from = lcfirst($this->normalizePath($from));
43093 $to = lcfirst($this->normalizePath($to));
43094
43095 if ($directories) {
43096 $from = rtrim($from, '/') . '/dummy_file';
43097 }
43098
43099 if (dirname($from) === dirname($to)) {
43100 return './'.basename($to);
43101 }
43102
43103 $commonPath = $to;
43104 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
43105 $commonPath = strtr(dirname($commonPath), '\\', '/');
43106 }
43107
43108 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
43109 return $to;
43110 }
43111
43112 $commonPath = rtrim($commonPath, '/') . '/';
43113 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
43114 $commonPathCode = str_repeat('../', $sourcePathDepth);
43115
43116 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
43117 }
43118
43119
43120
43121
43122
43123
43124
43125
43126
43127
43128
43129 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
43130 {
43131 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
43132 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
43133 }
43134
43135 $from = lcfirst($this->normalizePath($from));
43136 $to = lcfirst($this->normalizePath($to));
43137
43138 if ($from === $to) {
43139 return $directories ? '__DIR__' : '__FILE__';
43140 }
43141
43142 $commonPath = $to;
43143 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
43144 $commonPath = strtr(dirname($commonPath), '\\', '/');
43145 }
43146
43147 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
43148 return var_export($to, true);
43149 }
43150
43151 $commonPath = rtrim($commonPath, '/') . '/';
43152 if (strpos($to, $from.'/') === 0) {
43153 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
43154 }
43155 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
43156 if ($staticCode) {
43157 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
43158 } else {
43159 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
43160 }
43161 $relTarget = substr($to, strlen($commonPath));
43162
43163 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
43164 }
43165
43166
43167
43168
43169
43170
43171
43172 public function isAbsolutePath($path)
43173 {
43174 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':' || substr($path, 0, 2) === '\\\\';
43175 }
43176
43177
43178
43179
43180
43181
43182
43183
43184
43185 public function size($path)
43186 {
43187 if (!file_exists($path)) {
43188 throw new \RuntimeException("$path does not exist.");
43189 }
43190 if (is_dir($path)) {
43191 return $this->directorySize($path);
43192 }
43193
43194 return filesize($path);
43195 }
43196
43197
43198
43199
43200
43201
43202
43203
43204 public function normalizePath($path)
43205 {
43206 $parts = array();
43207 $path = strtr($path, '\\', '/');
43208 $prefix = '';
43209 $absolute = false;
43210
43211
43212  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
43213 $prefix = $match[1];
43214 $path = substr($path, strlen($prefix));
43215 }
43216
43217 if (substr($path, 0, 1) === '/') {
43218 $absolute = true;
43219 $path = substr($path, 1);
43220 }
43221
43222 $up = false;
43223 foreach (explode('/', $path) as $chunk) {
43224 if ('..' === $chunk && ($absolute || $up)) {
43225 array_pop($parts);
43226 $up = !(empty($parts) || '..' === end($parts));
43227 } elseif ('.' !== $chunk && '' !== $chunk) {
43228 $parts[] = $chunk;
43229 $up = '..' !== $chunk;
43230 }
43231 }
43232
43233 return $prefix.($absolute ? '/' : '').implode('/', $parts);
43234 }
43235
43236
43237
43238
43239
43240
43241
43242 public static function isLocalPath($path)
43243 {
43244 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
43245 }
43246
43247 public static function getPlatformPath($path)
43248 {
43249 if (Platform::isWindows()) {
43250 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
43251 }
43252
43253 return preg_replace('{^file://}i', '', $path);
43254 }
43255
43256 protected function directorySize($directory)
43257 {
43258 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
43259 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
43260
43261 $size = 0;
43262 foreach ($ri as $file) {
43263 if ($file->isFile()) {
43264 $size += $file->getSize();
43265 }
43266 }
43267
43268 return $size;
43269 }
43270
43271 protected function getProcess()
43272 {
43273 return $this->processExecutor;
43274 }
43275
43276
43277
43278
43279
43280
43281
43282
43283
43284
43285 private function unlinkImplementation($path)
43286 {
43287 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
43288 return rmdir($path);
43289 }
43290
43291 return unlink($path);
43292 }
43293
43294
43295
43296
43297
43298
43299
43300
43301 public function relativeSymlink($target, $link)
43302 {
43303 $cwd = getcwd();
43304
43305 $relativePath = $this->findShortestPath($link, $target);
43306 chdir(dirname($link));
43307 $result = @symlink($relativePath, $link);
43308
43309 chdir($cwd);
43310
43311 return $result;
43312 }
43313
43314
43315
43316
43317
43318
43319
43320
43321 public function isSymlinkedDirectory($directory)
43322 {
43323 if (!is_dir($directory)) {
43324 return false;
43325 }
43326
43327 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
43328
43329 return is_link($resolved);
43330 }
43331
43332
43333
43334
43335
43336
43337 private function unlinkSymlinkedDirectory($directory)
43338 {
43339 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
43340
43341 return $this->unlink($resolved);
43342 }
43343
43344
43345
43346
43347
43348
43349
43350
43351 private function resolveSymlinkedDirectorySymlink($pathname)
43352 {
43353 if (!is_dir($pathname)) {
43354 return $pathname;
43355 }
43356
43357 $resolved = rtrim($pathname, '/');
43358
43359 if (!strlen($resolved)) {
43360 return $pathname;
43361 }
43362
43363 return $resolved;
43364 }
43365
43366
43367
43368
43369
43370
43371
43372 public function junction($target, $junction)
43373 {
43374 if (!Platform::isWindows()) {
43375 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
43376 }
43377 if (!is_dir($target)) {
43378 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
43379 }
43380 $cmd = sprintf(
43381 'mklink /J %s %s',
43382 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
43383 ProcessExecutor::escape(realpath($target))
43384 );
43385 if ($this->getProcess()->execute($cmd, $output) !== 0) {
43386 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
43387 }
43388 clearstatcache(true, $junction);
43389 }
43390
43391
43392
43393
43394
43395
43396
43397
43398
43399
43400
43401
43402
43403
43404
43405
43406
43407
43408
43409
43410
43411 public function isJunction($junction)
43412 {
43413 if (!Platform::isWindows()) {
43414 return false;
43415 }
43416
43417
43418  clearstatcache(true, $junction);
43419
43420 if (!is_dir($junction) || is_link($junction)) {
43421 return false;
43422 }
43423
43424 $stat = lstat($junction);
43425
43426
43427  return $stat ? 0x4000 !== ($stat['mode'] & 0xF000) : false;
43428 }
43429
43430
43431
43432
43433
43434
43435
43436 public function removeJunction($junction)
43437 {
43438 if (!Platform::isWindows()) {
43439 return false;
43440 }
43441 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
43442 if (!$this->isJunction($junction)) {
43443 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
43444 }
43445
43446 return $this->rmdir($junction);
43447 }
43448 }
43449 <?php
43450
43451
43452
43453
43454
43455
43456
43457
43458
43459
43460
43461 namespace Composer\Util;
43462
43463 use Composer\Config;
43464 use Composer\IO\IOInterface;
43465
43466
43467
43468
43469 class Git
43470 {
43471 private static $version;
43472
43473
43474 protected $io;
43475
43476 protected $config;
43477
43478 protected $process;
43479
43480 protected $filesystem;
43481
43482 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
43483 {
43484 $this->io = $io;
43485 $this->config = $config;
43486 $this->process = $process;
43487 $this->filesystem = $fs;
43488 }
43489
43490 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
43491 {
43492
43493  $this->config->prohibitUrlByConfig($url, $this->io);
43494
43495 if ($initialClone) {
43496 $origCwd = $cwd;
43497 $cwd = null;
43498 }
43499
43500 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
43501 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.');
43502 }
43503
43504 if (!$initialClone) {
43505
43506  $this->process->execute('git remote -v', $output, $cwd);
43507 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) {
43508 $this->io->setAuthentication($match[3], rawurldecode($match[1]), rawurldecode($match[2]));
43509 }
43510 }
43511
43512 $protocols = $this->config->get('github-protocols');
43513 if (!is_array($protocols)) {
43514 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
43515 }
43516
43517  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
43518 $messages = array();
43519 foreach ($protocols as $protocol) {
43520 if ('ssh' === $protocol) {
43521 $protoUrl = "git@" . $match[1] . ":" . $match[2];
43522 } else {
43523 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
43524 }
43525
43526 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
43527 return;
43528 }
43529 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
43530 if ($initialClone) {
43531 $this->filesystem->removeDirectory($origCwd);
43532 }
43533 }
43534
43535
43536  if (!$this->io->hasAuthentication($match[1]) && !$this->io->isInteractive()) {
43537 $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
43538 }
43539 }
43540
43541
43542  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
43543
43544 $command = call_user_func($commandCallable, $url);
43545
43546 $auth = null;
43547 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
43548 $errorMsg = $this->process->getErrorOutput();
43549
43550  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)
43551 || preg_match('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)
43552 ) {
43553 if (!$this->io->hasAuthentication($match[1])) {
43554 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
43555 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
43556
43557 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
43558 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
43559 }
43560 }
43561
43562 if ($this->io->hasAuthentication($match[1])) {
43563 $auth = $this->io->getAuthentication($match[1]);
43564 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
43565 $command = call_user_func($commandCallable, $authUrl);
43566 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43567 return;
43568 }
43569
43570 $errorMsg = $this->process->getErrorOutput();
43571 }
43572 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
43573  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
43574
43575 if (!$this->io->hasAuthentication($match[1])) {
43576 $message = 'Enter your Bitbucket credentials to access private repos';
43577
43578 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
43579 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
43580 $accessToken = $bitbucketUtil->getToken();
43581 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
43582 }
43583 } else { 
43584  $auth = $this->io->getAuthentication($match[1]);
43585
43586
43587  if ($auth['username'] !== 'x-token-auth') {
43588 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
43589 if (! empty($accessToken)) {
43590 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
43591 }
43592 }
43593 }
43594
43595 if ($this->io->hasAuthentication($match[1])) {
43596 $auth = $this->io->getAuthentication($match[1]);
43597 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
43598
43599 $command = call_user_func($commandCallable, $authUrl);
43600 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43601 return;
43602 }
43603
43604 $errorMsg = $this->process->getErrorOutput();
43605 } else { 
43606  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
43607 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
43608 $command = call_user_func($commandCallable, $sshUrl);
43609 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43610 return;
43611 }
43612
43613 $errorMsg = $this->process->getErrorOutput();
43614 }
43615 } elseif (
43616 preg_match('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?\.git)$}i', $url, $match)
43617 || preg_match('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}', $url, $match)
43618 ) {
43619 if ($match[1] === 'git') {
43620 $match[1] = 'https';
43621 }
43622
43623 if (!$this->io->hasAuthentication($match[2])) {
43624 $gitLabUtil = new GitLab($this->io, $this->config, $this->process);
43625 $message = 'Cloning failed, enter your GitLab credentials to access private repos';
43626
43627 if (!$gitLabUtil->authorizeOAuth($match[2]) && $this->io->isInteractive()) {
43628 $gitLabUtil->authorizeOAuthInteractively($match[1], $match[2], $message);
43629 }
43630 }
43631
43632 if ($this->io->hasAuthentication($match[2])) {
43633 $auth = $this->io->getAuthentication($match[2]);
43634 if ($auth['password'] === 'private-token' || $auth['password'] === 'oauth2' || $auth['password'] === 'gitlab-ci-token') {
43635 $authUrl = $match[1] . '://' . rawurlencode($auth['password']) . ':' . rawurlencode($auth['username']) . '@' . $match[2] . '/' . $match[3]; 
43636  } else {
43637 $authUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . '/' . $match[3];
43638 }
43639
43640 $command = call_user_func($commandCallable, $authUrl);
43641 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43642 return;
43643 }
43644
43645 $errorMsg = $this->process->getErrorOutput();
43646 }
43647 } elseif ($this->isAuthenticationFailure($url, $match)) { 
43648  if (strpos($match[2], '@')) {
43649 list($authParts, $match[2]) = explode('@', $match[2], 2);
43650 }
43651
43652 $storeAuth = false;
43653 if ($this->io->hasAuthentication($match[2])) {
43654 $auth = $this->io->getAuthentication($match[2]);
43655 } elseif ($this->io->isInteractive()) {
43656 $defaultUsername = null;
43657 if (isset($authParts) && $authParts) {
43658 if (false !== strpos($authParts, ':')) {
43659 list($defaultUsername, ) = explode(':', $authParts, 2);
43660 } else {
43661 $defaultUsername = $authParts;
43662 }
43663 }
43664
43665 $this->io->writeError('    Authentication required (<info>' . $match[2] . '</info>):');
43666 $auth = array(
43667 'username' => $this->io->ask('      Username: ', $defaultUsername),
43668 'password' => $this->io->askAndHideAnswer('      Password: '),
43669 );
43670 $storeAuth = $this->config->get('store-auths');
43671 }
43672
43673 if ($auth) {
43674 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
43675
43676 $command = call_user_func($commandCallable, $authUrl);
43677 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
43678 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
43679 $authHelper = new AuthHelper($this->io, $this->config);
43680 $authHelper->storeAuth($match[2], $storeAuth);
43681
43682 return;
43683 }
43684
43685 $errorMsg = $this->process->getErrorOutput();
43686 }
43687 }
43688
43689 if ($initialClone) {
43690 $this->filesystem->removeDirectory($origCwd);
43691 }
43692
43693 $this->throwException('Failed to execute ' . $command . "\n\n" . $errorMsg, $url);
43694 }
43695 }
43696
43697 public function syncMirror($url, $dir)
43698 {
43699
43700  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
43701 try {
43702 $commandCallable = function ($url) {
43703 $sanitizedUrl = preg_replace('{://([^@]+?):(.+?)@}', '://', $url);
43704
43705 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));
43706 };
43707 $this->runCommand($commandCallable, $url, $dir);
43708 } catch (\Exception $e) {
43709 $this->io->writeError('<error>Sync mirror failed: ' . $e->getMessage() . '</error>', true, IOInterface::DEBUG);
43710
43711 return false;
43712 }
43713
43714 return true;
43715 }
43716
43717
43718  $this->filesystem->removeDirectory($dir);
43719
43720 $commandCallable = function ($url) use ($dir) {
43721 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
43722 };
43723
43724 $this->runCommand($commandCallable, $url, $dir, true);
43725
43726 return true;
43727 }
43728
43729 public function fetchRefOrSyncMirror($url, $dir, $ref)
43730 {
43731 if ($this->checkRefIsInMirror($url, $dir, $ref)) {
43732 return true;
43733 }
43734
43735 if ($this->syncMirror($url, $dir)) {
43736 return $this->checkRefIsInMirror($url, $dir, $ref);
43737 }
43738
43739 return false;
43740 }
43741
43742 private function checkRefIsInMirror($url, $dir, $ref)
43743 {
43744 if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
43745 $escapedRef = ProcessExecutor::escape($ref.'^{commit}');
43746 $exitCode = $this->process->execute(sprintf('git rev-parse --quiet --verify %s', $escapedRef), $ignoredOutput, $dir);
43747 if ($exitCode === 0) {
43748 return true;
43749 }
43750 }
43751
43752 return false;
43753 }
43754
43755 private function isAuthenticationFailure($url, &$match)
43756 {
43757 if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
43758 return false;
43759 }
43760
43761 $authFailures = array(
43762 'fatal: Authentication failed',
43763 'remote error: Invalid username or password.',
43764 'error: 401 Unauthorized',
43765 'fatal: unable to access',
43766 'fatal: could not read Username',
43767 );
43768
43769 $errorOutput = $this->process->getErrorOutput();
43770 foreach ($authFailures as $authFailure) {
43771 if (strpos($errorOutput, $authFailure) !== false) {
43772 return true;
43773 }
43774 }
43775
43776 return false;
43777 }
43778
43779 public static function cleanEnv()
43780 {
43781 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
43782 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');
43783 }
43784
43785
43786  if (getenv('GIT_ASKPASS') !== 'echo') {
43787 putenv('GIT_ASKPASS=echo');
43788 unset($_SERVER['GIT_ASKPASS']);
43789 }
43790
43791
43792  if (getenv('GIT_DIR')) {
43793 putenv('GIT_DIR');
43794 unset($_SERVER['GIT_DIR']);
43795 }
43796 if (getenv('GIT_WORK_TREE')) {
43797 putenv('GIT_WORK_TREE');
43798 unset($_SERVER['GIT_WORK_TREE']);
43799 }
43800
43801
43802  if (getenv('LANGUAGE') !== 'C') {
43803 putenv('LANGUAGE=C');
43804 }
43805
43806
43807  putenv("DYLD_LIBRARY_PATH");
43808 unset($_SERVER['DYLD_LIBRARY_PATH']);
43809 }
43810
43811 public static function getGitHubDomainsRegex(Config $config)
43812 {
43813 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
43814 }
43815
43816 public static function getGitLabDomainsRegex(Config $config)
43817 {
43818 return '(' . implode('|', array_map('preg_quote', $config->get('gitlab-domains'))) . ')';
43819 }
43820
43821 public static function sanitizeUrl($message)
43822 {
43823 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
43824 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
43825 return '://***:***@';
43826 }
43827
43828 return '://' . $m[1] . ':***@';
43829 }, $message);
43830 }
43831
43832 private function throwException($message, $url)
43833 {
43834
43835  clearstatcache();
43836
43837 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
43838 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()));
43839 }
43840
43841 throw new \RuntimeException(self::sanitizeUrl($message));
43842 }
43843
43844
43845
43846
43847
43848
43849 public function getVersion()
43850 {
43851 if (isset(self::$version)) {
43852 return self::$version;
43853 }
43854 if (0 !== $this->process->execute('git --version', $output)) {
43855 return;
43856 }
43857 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
43858 return self::$version = $matches[1];
43859 }
43860 }
43861 }
43862 <?php
43863
43864
43865
43866
43867
43868
43869
43870
43871
43872
43873
43874 namespace Composer\Util;
43875
43876 use Composer\Factory;
43877 use Composer\IO\IOInterface;
43878 use Composer\Config;
43879 use Composer\Downloader\TransportException;
43880
43881
43882
43883
43884 class GitHub
43885 {
43886 protected $io;
43887 protected $config;
43888 protected $process;
43889 protected $remoteFilesystem;
43890
43891
43892
43893
43894
43895
43896
43897
43898
43899 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
43900 {
43901 $this->io = $io;
43902 $this->config = $config;
43903 $this->process = $process ?: new ProcessExecutor($io);
43904 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
43905 }
43906
43907
43908
43909
43910
43911
43912
43913 public function authorizeOAuth($originUrl)
43914 {
43915 if (!in_array($originUrl, $this->config->get('github-domains'))) {
43916 return false;
43917 }
43918
43919
43920  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
43921 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
43922
43923 return true;
43924 }
43925
43926 return false;
43927 }
43928
43929
43930
43931
43932
43933
43934
43935
43936
43937
43938 public function authorizeOAuthInteractively($originUrl, $message = null)
43939 {
43940 if ($message) {
43941 $this->io->writeError($message);
43942 }
43943
43944 $note = 'Composer';
43945 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
43946 $note .= ' on ' . trim($output);
43947 }
43948 $note .= ' ' . date('Y-m-d Hi');
43949
43950 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
43951 $this->io->writeError(sprintf('Head to %s', $url));
43952 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
43953
43954 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
43955
43956 if (!$token) {
43957 $this->io->writeError('<warning>No token given, aborting.</warning>');
43958 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
43959
43960 return false;
43961 }
43962
43963 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
43964
43965 try {
43966 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
43967
43968 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
43969 'retry-auth-failure' => false,
43970 ));
43971 } catch (TransportException $e) {
43972 if (in_array($e->getCode(), array(403, 401))) {
43973 $this->io->writeError('<error>Invalid token provided.</error>');
43974 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
43975
43976 return false;
43977 }
43978
43979 throw $e;
43980 }
43981
43982
43983  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
43984 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
43985
43986 $this->io->writeError('<info>Token stored successfully.</info>');
43987
43988 return true;
43989 }
43990
43991
43992
43993
43994
43995
43996
43997
43998 public function getRateLimit(array $headers)
43999 {
44000 $rateLimit = array(
44001 'limit' => '?',
44002 'reset' => '?',
44003 );
44004
44005 foreach ($headers as $header) {
44006 $header = trim($header);
44007 if (false === strpos($header, 'X-RateLimit-')) {
44008 continue;
44009 }
44010 list($type, $value) = explode(':', $header, 2);
44011 switch ($type) {
44012 case 'X-RateLimit-Limit':
44013 $rateLimit['limit'] = (int) trim($value);
44014 break;
44015 case 'X-RateLimit-Reset':
44016 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
44017 break;
44018 }
44019 }
44020
44021 return $rateLimit;
44022 }
44023
44024
44025
44026
44027
44028
44029
44030
44031 public function isRateLimited(array $headers)
44032 {
44033 foreach ($headers as $header) {
44034 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
44035 return true;
44036 }
44037 }
44038
44039 return false;
44040 }
44041 }
44042 <?php
44043
44044
44045
44046
44047
44048
44049
44050
44051
44052
44053
44054 namespace Composer\Util;
44055
44056 use Composer\IO\IOInterface;
44057 use Composer\Config;
44058 use Composer\Factory;
44059 use Composer\Downloader\TransportException;
44060 use Composer\Json\JsonFile;
44061
44062
44063
44064
44065 class GitLab
44066 {
44067 protected $io;
44068 protected $config;
44069 protected $process;
44070 protected $remoteFilesystem;
44071
44072
44073
44074
44075
44076
44077
44078
44079
44080 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
44081 {
44082 $this->io = $io;
44083 $this->config = $config;
44084 $this->process = $process ?: new ProcessExecutor($io);
44085 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
44086 }
44087
44088
44089
44090
44091
44092
44093
44094
44095 public function authorizeOAuth($originUrl)
44096 {
44097
44098  $bcOriginUrl = preg_replace('{:\d+}', '', $originUrl);
44099
44100 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true) && !in_array($bcOriginUrl, $this->config->get('gitlab-domains'), true)) {
44101 return false;
44102 }
44103
44104
44105  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
44106 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
44107
44108 return true;
44109 }
44110
44111
44112  $authTokens = $this->config->get('gitlab-token');
44113
44114 if (isset($authTokens[$originUrl])) {
44115 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
44116
44117 return true;
44118 }
44119
44120 if (isset($authTokens[$bcOriginUrl])) {
44121 $this->io->setAuthentication($originUrl, $authTokens[$bcOriginUrl], 'private-token');
44122
44123 return true;
44124 }
44125
44126 return false;
44127 }
44128
44129
44130
44131
44132
44133
44134
44135
44136
44137
44138
44139
44140
44141 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
44142 {
44143 if ($message) {
44144 $this->io->writeError($message);
44145 }
44146
44147 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
44148 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
44149
44150 $attemptCounter = 0;
44151
44152 while ($attemptCounter++ < 5) {
44153 try {
44154 $response = $this->createToken($scheme, $originUrl);
44155 } catch (TransportException $e) {
44156
44157  
44158  if (in_array($e->getCode(), array(403, 401))) {
44159 if (401 === $e->getCode()) {
44160 $this->io->writeError('Bad credentials.');
44161 } else {
44162 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
44163 }
44164
44165 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
44166 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
44167
44168 continue;
44169 }
44170
44171 throw $e;
44172 }
44173
44174 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
44175
44176
44177  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
44178
44179 return true;
44180 }
44181
44182 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
44183 }
44184
44185 private function createToken($scheme, $originUrl)
44186 {
44187 $username = $this->io->ask('Username: ');
44188 $password = $this->io->askAndHideAnswer('Password: ');
44189
44190 $headers = array('Content-Type: application/x-www-form-urlencoded');
44191
44192 $apiUrl = $originUrl;
44193 $data = http_build_query(array(
44194 'username' => $username,
44195 'password' => $password,
44196 'grant_type' => 'password',
44197 ), null, '&');
44198 $options = array(
44199 'retry-auth-failure' => false,
44200 'http' => array(
44201 'method' => 'POST',
44202 'header' => $headers,
44203 'content' => $data,
44204 ),
44205 );
44206
44207 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
44208
44209 $this->io->writeError('Token successfully created');
44210
44211 return JsonFile::parseJson($json);
44212 }
44213 }
44214 <?php
44215
44216
44217
44218
44219
44220
44221
44222
44223
44224
44225
44226 namespace Composer\Util;
44227
44228 use Composer\Config;
44229 use Composer\IO\IOInterface;
44230
44231
44232
44233
44234 class Hg
44235 {
44236
44237
44238
44239 private $io;
44240
44241
44242
44243
44244 private $config;
44245
44246
44247
44248
44249 private $process;
44250
44251 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process)
44252 {
44253 $this->io = $io;
44254 $this->config = $config;
44255 $this->process = $process;
44256 }
44257
44258 public function runCommand($commandCallable, $url, $cwd)
44259 {
44260 $this->config->prohibitUrlByConfig($url, $this->io);
44261
44262
44263  $command = call_user_func($commandCallable, $url);
44264
44265 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44266 return;
44267 }
44268
44269
44270  if (preg_match('{^(https?)://((.+)(?:\:(.+))?@)?([^/]+)(/.*)?}mi', $url, $match) && $this->io->hasAuthentication($match[5])) {
44271 $auth = $this->io->getAuthentication($match[5]);
44272 $authenticatedUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[5] . (!empty($match[6]) ? $match[6] : null);
44273
44274 $command = call_user_func($commandCallable, $authenticatedUrl);
44275
44276 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
44277 return;
44278 }
44279
44280 $error = $this->process->getErrorOutput();
44281 } else {
44282 $error = 'The given URL (' . $url . ') does not match the required format (http(s)://(username:password@)example.com/path-to-repository)';
44283 }
44284
44285 $this->throwException('Failed to clone ' . $url . ', ' . "\n\n" . $error, $url);
44286 }
44287
44288 public static function sanitizeUrl($message)
44289 {
44290 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
44291 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
44292 return '://***:***@';
44293 }
44294
44295 return '://' . $m[1] . ':***@';
44296 }, $message);
44297 }
44298
44299 private function throwException($message, $url)
44300 {
44301 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
44302 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()));
44303 }
44304
44305 throw new \RuntimeException(self::sanitizeUrl($message));
44306 }
44307 }
44308 <?php
44309
44310
44311
44312
44313
44314
44315
44316
44317
44318
44319
44320 namespace Composer\Util;
44321
44322 use Composer\XdebugHandler\XdebugHandler;
44323
44324
44325
44326
44327
44328
44329
44330
44331 class IniHelper
44332 {
44333
44334
44335
44336
44337
44338
44339
44340
44341 public static function getAll()
44342 {
44343 return XdebugHandler::getAllIniFiles();
44344 }
44345
44346
44347
44348
44349
44350
44351 public static function getMessage()
44352 {
44353 $paths = self::getAll();
44354
44355 if (empty($paths[0])) {
44356 array_shift($paths);
44357 }
44358
44359 $ini = array_shift($paths);
44360
44361 if (empty($ini)) {
44362 return 'A php.ini file does not exist. You will have to create one.';
44363 }
44364
44365 if (!empty($paths)) {
44366 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
44367 }
44368
44369 return 'The php.ini used by your command-line PHP is: '.$ini;
44370 }
44371 }
44372 <?php
44373
44374
44375
44376
44377
44378
44379
44380
44381
44382
44383
44384 namespace Composer\Util;
44385
44386 use stdClass;
44387
44388
44389
44390
44391 class NoProxyPattern
44392 {
44393
44394
44395
44396 protected $hostNames = array();
44397
44398
44399
44400
44401 protected $rules = array();
44402
44403
44404
44405
44406 protected $noproxy;
44407
44408
44409
44410
44411 public function __construct($pattern)
44412 {
44413 $this->hostNames = preg_split('{[\s,]+}', $pattern, null, PREG_SPLIT_NO_EMPTY);
44414 $this->noproxy = empty($this->hostNames) || '*' === $this->hostNames[0];
44415 }
44416
44417
44418
44419
44420
44421
44422
44423
44424 public function test($url)
44425 {
44426 if ($this->noproxy) {
44427 return true;
44428 }
44429
44430 if (!$urlData = $this->getUrlData($url)) {
44431 return false;
44432 }
44433
44434 foreach ($this->hostNames as $index => $hostName) {
44435 if ($this->match($index, $hostName, $urlData)) {
44436 return true;
44437 }
44438 }
44439
44440 return false;
44441 }
44442
44443
44444
44445
44446
44447
44448
44449
44450 protected function getUrlData($url)
44451 {
44452 if (!$host = parse_url($url, PHP_URL_HOST)) {
44453 return false;
44454 }
44455
44456 $port = parse_url($url, PHP_URL_PORT);
44457
44458 if (empty($port)) {
44459 switch (parse_url($url, PHP_URL_SCHEME)) {
44460 case 'http':
44461 $port = 80;
44462 break;
44463 case 'https':
44464 $port = 443;
44465 break;
44466 }
44467 }
44468
44469 $hostName = $host . ($port ? ':' . $port : '');
44470 list($host, $port, $err) = $this->splitHostPort($hostName);
44471
44472 if ($err || !$this->ipCheckData($host, $ipdata)) {
44473 return false;
44474 }
44475
44476 return $this->makeData($host, $port, $ipdata);
44477 }
44478
44479
44480
44481
44482
44483
44484
44485
44486
44487
44488 protected function match($index, $hostName, $url)
44489 {
44490 if (!$rule = $this->getRule($index, $hostName)) {
44491
44492  return false;
44493 }
44494
44495 if ($rule->ipdata) {
44496
44497  if (!$url->ipdata) {
44498 return false;
44499 }
44500
44501 if ($rule->ipdata->netmask) {
44502 return $this->matchRange($rule->ipdata, $url->ipdata);
44503 }
44504
44505 $match = $rule->ipdata->ip === $url->ipdata->ip;
44506 } else {
44507
44508  $haystack = substr($url->name, - strlen($rule->name));
44509 $match = stripos($haystack, $rule->name) === 0;
44510 }
44511
44512 if ($match && $rule->port) {
44513 $match = $rule->port === $url->port;
44514 }
44515
44516 return $match;
44517 }
44518
44519
44520
44521
44522
44523
44524
44525
44526
44527 protected function matchRange(stdClass $network, stdClass $target)
44528 {
44529 $net = unpack('C*', $network->ip);
44530 $mask = unpack('C*', $network->netmask);
44531 $ip = unpack('C*', $target->ip);
44532
44533 for ($i = 1; $i < 17; ++$i) {
44534 if (($net[$i] & $mask[$i]) !== ($ip[$i] & $mask[$i])) {
44535 return false;
44536 }
44537 }
44538
44539 return true;
44540 }
44541
44542
44543
44544
44545
44546
44547
44548
44549
44550 private function getRule($index, $hostName)
44551 {
44552 if (array_key_exists($index, $this->rules)) {
44553 return $this->rules[$index];
44554 }
44555
44556 $this->rules[$index] = null;
44557 list($host, $port, $err) = $this->splitHostPort($hostName);
44558
44559 if ($err || !$this->ipCheckData($host, $ipdata, true)) {
44560 return null;
44561 }
44562
44563 $this->rules[$index] = $this->makeData($host, $port, $ipdata);
44564
44565 return $this->rules[$index];
44566 }
44567
44568
44569
44570
44571
44572
44573
44574
44575
44576
44577 private function ipCheckData($host, &$ipdata, $allowPrefix = false)
44578 {
44579 $ipdata = null;
44580 $netmask = null;
44581 $prefix = null;
44582 $modified = false;
44583
44584
44585  if (strpos($host, '/') !== false) {
44586 list($host, $prefix) = explode('/', $host);
44587
44588 if (!$allowPrefix || !$this->validateInt($prefix, 0, 128)) {
44589 return false;
44590 }
44591 $prefix = (int) $prefix;
44592 $modified = true;
44593 }
44594
44595
44596  if (!filter_var($host, FILTER_VALIDATE_IP)) {
44597 return !$modified;
44598 }
44599
44600 list($ip, $size) = $this->ipGetAddr($host);
44601
44602 if ($prefix !== null) {
44603
44604  if ($prefix > $size * 8) {
44605 return false;
44606 }
44607
44608 list($ip, $netmask) = $this->ipGetNetwork($ip, $size, $prefix);
44609 }
44610
44611 $ipdata = $this->makeIpData($ip, $size, $netmask);
44612
44613 return true;
44614 }
44615
44616
44617
44618
44619
44620
44621
44622
44623
44624
44625
44626 private function ipGetAddr($host)
44627 {
44628 $ip = inet_pton($host);
44629 $size = strlen($ip);
44630 $mapped = $this->ipMapTo6($ip, $size);
44631
44632 return array($mapped, $size);
44633 }
44634
44635
44636
44637
44638
44639
44640
44641
44642
44643 private function ipGetMask($prefix, $size)
44644 {
44645 $mask = '';
44646
44647 if ($ones = floor($prefix / 8)) {
44648 $mask = str_repeat(chr(255), $ones);
44649 }
44650
44651 if ($remainder = $prefix % 8) {
44652 $mask .= chr(0xff ^ (0xff >> $remainder));
44653 }
44654
44655 $mask = str_pad($mask, $size, chr(0));
44656
44657 return $this->ipMapTo6($mask, $size);
44658 }
44659
44660
44661
44662
44663
44664
44665
44666
44667
44668
44669 private function ipGetNetwork($rangeIp, $size, $prefix)
44670 {
44671 $netmask = $this->ipGetMask($prefix, $size);
44672
44673
44674  $mask = unpack('C*', $netmask);
44675 $ip = unpack('C*', $rangeIp);
44676 $net = '';
44677
44678 for ($i = 1; $i < 17; ++$i) {
44679 $net .= chr($ip[$i] & $mask[$i]);
44680 }
44681
44682 return array($net, $netmask);
44683 }
44684
44685
44686
44687
44688
44689
44690
44691
44692
44693 private function ipMapTo6($binary, $size)
44694 {
44695 if ($size === 4) {
44696 $prefix = str_repeat(chr(0), 10) . str_repeat(chr(255), 2);
44697 $binary = $prefix . $binary;
44698 }
44699
44700 return $binary;
44701 }
44702
44703
44704
44705
44706
44707
44708
44709
44710
44711
44712 private function makeData($host, $port, $ipdata)
44713 {
44714 return (object) array(
44715 'host' => $host,
44716 'name' => '.' . ltrim($host, '.'),
44717 'port' => $port,
44718 'ipdata' => $ipdata,
44719 );
44720 }
44721
44722
44723
44724
44725
44726
44727
44728
44729
44730
44731 private function makeIpData($ip, $size, $netmask)
44732 {
44733 return (object) array(
44734 'ip' => $ip,
44735 'size' => $size,
44736 'netmask' => $netmask,
44737 );
44738 }
44739
44740
44741
44742
44743
44744
44745
44746
44747 private function splitHostPort($hostName)
44748 {
44749
44750  $error = array('', '', true);
44751 $port = 0;
44752 $ip6 = '';
44753
44754
44755  if ($hostName[0] === '[') {
44756 $index = strpos($hostName, ']');
44757
44758
44759  if (false === $index || $index < 3) {
44760 return $error;
44761 }
44762
44763 $ip6 = substr($hostName, 1, $index - 1);
44764 $hostName = substr($hostName, $index + 1);
44765
44766 if (strpbrk($hostName, '[]') !== false
44767 || substr_count($hostName, ':') > 1) {
44768 return $error;
44769 }
44770 }
44771
44772 if (substr_count($hostName, ':') === 1) {
44773 $index = strpos($hostName, ':');
44774 $port = substr($hostName, $index + 1);
44775 $hostName = substr($hostName, 0, $index);
44776
44777 if (!$this->validateInt($port, 1, 65535)) {
44778 return $error;
44779 }
44780
44781 $port = (int) $port;
44782 }
44783
44784 $host = $ip6 . $hostName;
44785
44786 return array($host, $port, false);
44787 }
44788
44789
44790
44791
44792
44793
44794
44795
44796 private function validateInt($int, $min, $max)
44797 {
44798 $options = array(
44799 'options' => array(
44800 'min_range' => $min,
44801 'max_range' => $max)
44802 );
44803
44804 return false !== filter_var($int, FILTER_VALIDATE_INT, $options);
44805 }
44806 }
44807 <?php
44808
44809
44810 namespace Composer\Util;
44811
44812 use Composer\Package\Link;
44813 use Composer\Package\PackageInterface;
44814
44815 class PackageSorter
44816 {
44817
44818
44819
44820
44821
44822
44823
44824
44825 public static function sortPackages(array $packages) {
44826 $usageList = array();
44827
44828 foreach ($packages as $package) { 
44829 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { 
44830 $target = $link->getTarget();
44831 $usageList[$target][] = $package->getName();
44832 }
44833 }
44834 $computing = array();
44835 $computed = array();
44836 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
44837
44838  if (isset($computed[$name])) {
44839 return $computed[$name];
44840 }
44841
44842
44843  if (isset($computing[$name])) {
44844 return 0;
44845 }
44846
44847 $computing[$name] = true;
44848 $weight = 0;
44849
44850 if (isset($usageList[$name])) {
44851 foreach ($usageList[$name] as $user) {
44852 $weight -= 1 - $computeImportance($user);
44853 }
44854 }
44855
44856 unset($computing[$name]);
44857 $computed[$name] = $weight;
44858
44859 return $weight;
44860 };
44861
44862 $weightList = array();
44863
44864 foreach ($packages as $name => $package) {
44865 $weight = $computeImportance($name);
44866 $weightList[$name] = $weight;
44867 }
44868
44869 $stable_sort = function (&$array) {
44870 static $transform, $restore;
44871
44872 $i = 0;
44873
44874 if (!$transform) {
44875 $transform = function (&$v, $k) use (&$i) {
44876 $v = array($v, ++$i, $k, $v);
44877 };
44878
44879 $restore = function (&$v) {
44880 $v = $v[3];
44881 };
44882 }
44883
44884 array_walk($array, $transform);
44885 asort($array);
44886 array_walk($array, $restore);
44887 };
44888
44889 $stable_sort($weightList);
44890
44891 $sortedPackages = array();
44892
44893 foreach (array_keys($weightList) as $name) {
44894 $sortedPackages[] = $packages[$name];
44895 }
44896 return $sortedPackages;
44897 }
44898 }
44899 <?php
44900
44901
44902
44903
44904
44905
44906
44907
44908
44909
44910
44911 namespace Composer\Util;
44912
44913 use Composer\IO\IOInterface;
44914 use Symfony\Component\Process\Process;
44915
44916
44917
44918
44919 class Perforce
44920 {
44921 protected $path;
44922 protected $p4Depot;
44923 protected $p4Client;
44924 protected $p4User;
44925 protected $p4Password;
44926 protected $p4Port;
44927 protected $p4Stream;
44928 protected $p4ClientSpec;
44929 protected $p4DepotType;
44930 protected $p4Branch;
44931 protected $process;
44932 protected $uniquePerforceClientName;
44933 protected $windowsFlag;
44934 protected $commandResult;
44935
44936 protected $io;
44937
44938 protected $filesystem;
44939
44940 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
44941 {
44942 $this->windowsFlag = $isWindows;
44943 $this->p4Port = $port;
44944 $this->initializePath($path);
44945 $this->process = $process;
44946 $this->initialize($repoConfig);
44947 $this->io = $io;
44948 }
44949
44950 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
44951 {
44952 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
44953 }
44954
44955 public static function checkServerExists($url, ProcessExecutor $processExecutor)
44956 {
44957 $output = null;
44958
44959 return 0 === $processExecutor->execute('p4 -p ' . ProcessExecutor::escape($url) . ' info -s', $output);
44960 }
44961
44962 public function initialize($repoConfig)
44963 {
44964 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
44965 if (!$repoConfig) {
44966 return;
44967 }
44968 if (isset($repoConfig['unique_perforce_client_name'])) {
44969 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
44970 }
44971
44972 if (isset($repoConfig['depot'])) {
44973 $this->p4Depot = $repoConfig['depot'];
44974 }
44975 if (isset($repoConfig['branch'])) {
44976 $this->p4Branch = $repoConfig['branch'];
44977 }
44978 if (isset($repoConfig['p4user'])) {
44979 $this->p4User = $repoConfig['p4user'];
44980 } else {
44981 $this->p4User = $this->getP4variable('P4USER');
44982 }
44983 if (isset($repoConfig['p4password'])) {
44984 $this->p4Password = $repoConfig['p4password'];
44985 }
44986 }
44987
44988 public function initializeDepotAndBranch($depot, $branch)
44989 {
44990 if (isset($depot)) {
44991 $this->p4Depot = $depot;
44992 }
44993 if (isset($branch)) {
44994 $this->p4Branch = $branch;
44995 }
44996 }
44997
44998 public function generateUniquePerforceClientName()
44999 {
45000 return gethostname() . "_" . time();
45001 }
45002
45003 public function cleanupClientSpec()
45004 {
45005 $client = $this->getClient();
45006 $task = 'client -d ' . ProcessExecutor::escape($client);
45007 $useP4Client = false;
45008 $command = $this->generateP4Command($task, $useP4Client);
45009 $this->executeCommand($command);
45010 $clientSpec = $this->getP4ClientSpec();
45011 $fileSystem = $this->getFilesystem();
45012 $fileSystem->remove($clientSpec);
45013 }
45014
45015 protected function executeCommand($command)
45016 {
45017 $this->commandResult = '';
45018
45019 return $this->process->execute($command, $this->commandResult);
45020 }
45021
45022 public function getClient()
45023 {
45024 if (!isset($this->p4Client)) {
45025 $cleanStreamName = str_replace(array('//', '/', '@'), array('', '_', ''), $this->getStream());
45026 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
45027 }
45028
45029 return $this->p4Client;
45030 }
45031
45032 protected function getPath()
45033 {
45034 return $this->path;
45035 }
45036
45037 public function initializePath($path)
45038 {
45039 $this->path = $path;
45040 $fs = $this->getFilesystem();
45041 $fs->ensureDirectoryExists($path);
45042 }
45043
45044 protected function getPort()
45045 {
45046 return $this->p4Port;
45047 }
45048
45049 public function setStream($stream)
45050 {
45051 $this->p4Stream = $stream;
45052 $index = strrpos($stream, '/');
45053
45054  if ($index > 2) {
45055 $this->p4DepotType = 'stream';
45056 }
45057 }
45058
45059 public function isStream()
45060 {
45061 return (strcmp($this->p4DepotType, 'stream') === 0);
45062 }
45063
45064 public function getStream()
45065 {
45066 if (!isset($this->p4Stream)) {
45067 if ($this->isStream()) {
45068 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
45069 } else {
45070 $this->p4Stream = '//' . $this->p4Depot;
45071 }
45072 }
45073
45074 return $this->p4Stream;
45075 }
45076
45077 public function getStreamWithoutLabel($stream)
45078 {
45079 $index = strpos($stream, '@');
45080 if ($index === false) {
45081 return $stream;
45082 }
45083
45084 return substr($stream, 0, $index);
45085 }
45086
45087 public function getP4ClientSpec()
45088 {
45089 return $this->path . '/' . $this->getClient() . '.p4.spec';
45090 }
45091
45092 public function getUser()
45093 {
45094 return $this->p4User;
45095 }
45096
45097 public function setUser($user)
45098 {
45099 $this->p4User = $user;
45100 }
45101
45102 public function queryP4User()
45103 {
45104 $this->getUser();
45105 if (strlen($this->p4User) > 0) {
45106 return;
45107 }
45108 $this->p4User = $this->getP4variable('P4USER');
45109 if (strlen($this->p4User) > 0) {
45110 return;
45111 }
45112 $this->p4User = $this->io->ask('Enter P4 User:');
45113 if ($this->windowsFlag) {
45114 $command = 'p4 set P4USER=' . $this->p4User;
45115 } else {
45116 $command = 'export P4USER=' . $this->p4User;
45117 }
45118 $this->executeCommand($command);
45119 }
45120
45121 protected function getP4variable($name)
45122 {
45123 if ($this->windowsFlag) {
45124 $command = 'p4 set';
45125 $this->executeCommand($command);
45126 $result = trim($this->commandResult);
45127 $resArray = explode(PHP_EOL, $result);
45128 foreach ($resArray as $line) {
45129 $fields = explode('=', $line);
45130 if (strcmp($name, $fields[0]) == 0) {
45131 $index = strpos($fields[1], ' ');
45132 if ($index === false) {
45133 $value = $fields[1];
45134 } else {
45135 $value = substr($fields[1], 0, $index);
45136 }
45137 $value = trim($value);
45138
45139 return $value;
45140 }
45141 }
45142
45143 return null;
45144 }
45145
45146 $command = 'echo $' . $name;
45147 $this->executeCommand($command);
45148 $result = trim($this->commandResult);
45149
45150 return $result;
45151 }
45152
45153 public function queryP4Password()
45154 {
45155 if (isset($this->p4Password)) {
45156 return $this->p4Password;
45157 }
45158 $password = $this->getP4variable('P4PASSWD');
45159 if (strlen($password) <= 0) {
45160 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
45161 }
45162 $this->p4Password = $password;
45163
45164 return $password;
45165 }
45166
45167 public function generateP4Command($command, $useClient = true)
45168 {
45169 $p4Command = 'p4 ';
45170 $p4Command .= '-u ' . $this->getUser() . ' ';
45171 if ($useClient) {
45172 $p4Command .= '-c ' . $this->getClient() . ' ';
45173 }
45174 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ' . $command;
45175
45176 return $p4Command;
45177 }
45178
45179 public function isLoggedIn()
45180 {
45181 $command = $this->generateP4Command('login -s', false);
45182 $exitCode = $this->executeCommand($command);
45183 if ($exitCode) {
45184 $errorOutput = $this->process->getErrorOutput();
45185 $index = strpos($errorOutput, $this->getUser());
45186 if ($index === false) {
45187 $index = strpos($errorOutput, 'p4');
45188 if ($index === false) {
45189 return false;
45190 }
45191 throw new \Exception('p4 command not found in path: ' . $errorOutput);
45192 }
45193 throw new \Exception('Invalid user name: ' . $this->getUser());
45194 }
45195
45196 return true;
45197 }
45198
45199 public function connectClient()
45200 {
45201 $p4CreateClientCommand = $this->generateP4Command(
45202 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
45203 );
45204 $this->executeCommand($p4CreateClientCommand);
45205 }
45206
45207 public function syncCodeBase($sourceReference)
45208 {
45209 $prevDir = getcwd();
45210 chdir($this->path);
45211 $p4SyncCommand = $this->generateP4Command('sync -f ');
45212 if (null !== $sourceReference) {
45213 $p4SyncCommand .= '@' . $sourceReference;
45214 }
45215 $this->executeCommand($p4SyncCommand);
45216 chdir($prevDir);
45217 }
45218
45219 public function writeClientSpecToFile($spec)
45220 {
45221 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
45222 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
45223 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
45224 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
45225 fwrite($spec, 'Description:' . PHP_EOL);
45226 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
45227 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
45228 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
45229 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
45230 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
45231 if ($this->isStream()) {
45232 fwrite($spec, 'Stream:' . PHP_EOL);
45233 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
45234 } else {
45235 fwrite(
45236 $spec,
45237 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
45238 );
45239 }
45240 }
45241
45242 public function writeP4ClientSpec()
45243 {
45244 $clientSpec = $this->getP4ClientSpec();
45245 $spec = fopen($clientSpec, 'w');
45246 try {
45247 $this->writeClientSpecToFile($spec);
45248 } catch (\Exception $e) {
45249 fclose($spec);
45250 throw $e;
45251 }
45252 fclose($spec);
45253 }
45254
45255 protected function read($pipe, $name)
45256 {
45257 if (feof($pipe)) {
45258 return;
45259 }
45260 $line = fgets($pipe);
45261 while ($line !== false) {
45262 $line = fgets($pipe);
45263 }
45264 }
45265
45266 public function windowsLogin($password)
45267 {
45268 $command = $this->generateP4Command(' login -a');
45269
45270
45271  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
45272 $process = Process::fromShellCommandline($command, null, null, $password);
45273 } else {
45274 $process = new Process($command, null, null, $password);
45275 }
45276
45277 return $process->run();
45278 }
45279
45280 public function p4Login()
45281 {
45282 $this->queryP4User();
45283 if (!$this->isLoggedIn()) {
45284 $password = $this->queryP4Password();
45285 if ($this->windowsFlag) {
45286 $this->windowsLogin($password);
45287 } else {
45288 $command = 'echo ' . ProcessExecutor::escape($password) . ' | ' . $this->generateP4Command(' login -a', false);
45289 $exitCode = $this->executeCommand($command);
45290 $result = trim($this->commandResult);
45291 if ($exitCode) {
45292 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
45293 }
45294 }
45295 }
45296 }
45297
45298 public function getComposerInformation($identifier)
45299 {
45300 $composerFileContent = $this->getFileContent('composer.json', $identifier);
45301
45302 if (!$composerFileContent) {
45303 return;
45304 }
45305
45306 return json_decode($composerFileContent, true);
45307 }
45308
45309 public function getFileContent($file, $identifier)
45310 {
45311 $path = $this->getFilePath($file, $identifier);
45312
45313 $command = $this->generateP4Command(' print ' . ProcessExecutor::escape($path));
45314 $this->executeCommand($command);
45315 $result = $this->commandResult;
45316
45317 if (!trim($result)) {
45318 return null;
45319 }
45320
45321 return $result;
45322 }
45323
45324 public function getFilePath($file, $identifier)
45325 {
45326 $index = strpos($identifier, '@');
45327 if ($index === false) {
45328 $path = $identifier. '/' . $file;
45329
45330 return $path;
45331 }
45332
45333 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
45334 $command = $this->generateP4Command(' files ' . ProcessExecutor::escape($path), false);
45335 $this->executeCommand($command);
45336 $result = $this->commandResult;
45337 $index2 = strpos($result, 'no such file(s).');
45338 if ($index2 === false) {
45339 $index3 = strpos($result, 'change');
45340 if ($index3 !== false) {
45341 $phrase = trim(substr($result, $index3));
45342 $fields = explode(' ', $phrase);
45343
45344 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
45345 }
45346 }
45347
45348 return null;
45349 }
45350
45351 public function getBranches()
45352 {
45353 $possibleBranches = array();
45354 if (!$this->isStream()) {
45355 $possibleBranches[$this->p4Branch] = $this->getStream();
45356 } else {
45357 $command = $this->generateP4Command('streams '.ProcessExecutor::escape('//' . $this->p4Depot . '/...'));
45358 $this->executeCommand($command);
45359 $result = $this->commandResult;
45360 $resArray = explode(PHP_EOL, $result);
45361 foreach ($resArray as $line) {
45362 $resBits = explode(' ', $line);
45363 if (count($resBits) > 4) {
45364 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
45365 $possibleBranches[$branch] = $resBits[1];
45366 }
45367 }
45368 }
45369 $command = $this->generateP4Command('changes '. ProcessExecutor::escape($this->getStream() . '/...'), false);
45370 $this->executeCommand($command);
45371 $result = $this->commandResult;
45372 $resArray = explode(PHP_EOL, $result);
45373 $lastCommit = $resArray[0];
45374 $lastCommitArr = explode(' ', $lastCommit);
45375 $lastCommitNum = $lastCommitArr[1];
45376
45377 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
45378
45379 return $branches;
45380 }
45381
45382 public function getTags()
45383 {
45384 $command = $this->generateP4Command('labels');
45385 $this->executeCommand($command);
45386 $result = $this->commandResult;
45387 $resArray = explode(PHP_EOL, $result);
45388 $tags = array();
45389 foreach ($resArray as $line) {
45390 if (strpos($line, 'Label') !== false) {
45391 $fields = explode(' ', $line);
45392 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
45393 }
45394 }
45395
45396 return $tags;
45397 }
45398
45399 public function checkStream()
45400 {
45401 $command = $this->generateP4Command('depots', false);
45402 $this->executeCommand($command);
45403 $result = $this->commandResult;
45404 $resArray = explode(PHP_EOL, $result);
45405 foreach ($resArray as $line) {
45406 if (strpos($line, 'Depot') !== false) {
45407 $fields = explode(' ', $line);
45408 if (strcmp($this->p4Depot, $fields[1]) === 0) {
45409 $this->p4DepotType = $fields[3];
45410
45411 return $this->isStream();
45412 }
45413 }
45414 }
45415
45416 return false;
45417 }
45418
45419
45420
45421
45422
45423 protected function getChangeList($reference)
45424 {
45425 $index = strpos($reference, '@');
45426 if ($index === false) {
45427 return null;
45428 }
45429 $label = substr($reference, $index);
45430 $command = $this->generateP4Command(' changes -m1 ' . ProcessExecutor::escape($label));
45431 $this->executeCommand($command);
45432 $changes = $this->commandResult;
45433 if (strpos($changes, 'Change') !== 0) {
45434 return null;
45435 }
45436 $fields = explode(' ', $changes);
45437
45438 return $fields[1];
45439 }
45440
45441
45442
45443
45444
45445
45446 public function getCommitLogs($fromReference, $toReference)
45447 {
45448 $fromChangeList = $this->getChangeList($fromReference);
45449 if ($fromChangeList === null) {
45450 return null;
45451 }
45452 $toChangeList = $this->getChangeList($toReference);
45453 if ($toChangeList === null) {
45454 return null;
45455 }
45456 $index = strpos($fromReference, '@');
45457 $main = substr($fromReference, 0, $index) . '/...';
45458 $command = $this->generateP4Command('filelog ' . ProcessExecutor::escape($main . '@' . $fromChangeList. ',' . $toChangeList));
45459 $this->executeCommand($command);
45460
45461 return $this->commandResult;
45462 }
45463
45464 public function getFilesystem()
45465 {
45466 if (empty($this->filesystem)) {
45467 $this->filesystem = new Filesystem($this->process);
45468 }
45469
45470 return $this->filesystem;
45471 }
45472
45473 public function setFilesystem(Filesystem $fs)
45474 {
45475 $this->filesystem = $fs;
45476 }
45477 }
45478 <?php
45479
45480
45481
45482
45483
45484
45485
45486
45487
45488
45489
45490 namespace Composer\Util;
45491
45492
45493
45494
45495
45496
45497 class Platform
45498 {
45499
45500
45501
45502
45503
45504
45505 public static function expandPath($path)
45506 {
45507 if (preg_match('#^~[\\/]#', $path)) {
45508 return self::getUserDirectory() . substr($path, 1);
45509 }
45510
45511 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
45512
45513  if (Platform::isWindows() && $matches['var'] == 'HOME') {
45514 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
45515 }
45516
45517 return getenv($matches['var']) . $matches['path'];
45518 }, $path);
45519 }
45520
45521
45522
45523
45524
45525 public static function getUserDirectory()
45526 {
45527 if (false !== ($home = getenv('HOME'))) {
45528 return $home;
45529 }
45530
45531 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
45532 return $home;
45533 }
45534
45535 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
45536 $info = posix_getpwuid(posix_getuid());
45537
45538 return $info['dir'];
45539 }
45540
45541 throw new \RuntimeException('Could not determine user directory');
45542 }
45543
45544
45545
45546
45547 public static function isWindows()
45548 {
45549 return defined('PHP_WINDOWS_VERSION_BUILD');
45550 }
45551
45552
45553
45554
45555
45556 public static function strlen($str)
45557 {
45558 static $useMbString = null;
45559 if (null === $useMbString) {
45560 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
45561 }
45562
45563 if ($useMbString) {
45564 return mb_strlen($str, '8bit');
45565 }
45566
45567 return strlen($str);
45568 }
45569 }
45570 <?php
45571
45572
45573
45574
45575
45576
45577
45578
45579
45580
45581
45582 namespace Composer\Util;
45583
45584 use Composer\IO\IOInterface;
45585 use Symfony\Component\Process\Process;
45586 use Symfony\Component\Process\ProcessUtils;
45587
45588
45589
45590
45591 class ProcessExecutor
45592 {
45593 protected static $timeout = 300;
45594
45595 protected $captureOutput;
45596 protected $errorOutput;
45597 protected $io;
45598
45599 public function __construct(IOInterface $io = null)
45600 {
45601 $this->io = $io;
45602 }
45603
45604
45605
45606
45607
45608
45609
45610
45611
45612
45613 public function execute($command, &$output = null, $cwd = null)
45614 {
45615 if ($this->io && $this->io->isDebug()) {
45616 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
45617 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
45618 return '://***:***@';
45619 }
45620
45621 return '://'.$m['user'].':***@';
45622 }, $command);
45623 $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand);
45624 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
45625 }
45626
45627
45628  
45629  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
45630 $cwd = realpath(getcwd());
45631 }
45632
45633 $this->captureOutput = func_num_args() > 1;
45634 $this->errorOutput = null;
45635
45636
45637  if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
45638 $process = Process::fromShellCommandline($command, $cwd, null, null, static::getTimeout());
45639 } else {
45640 $process = new Process($command, $cwd, null, null, static::getTimeout());
45641 }
45642
45643 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
45644 $process->run($callback);
45645
45646 if ($this->captureOutput && !is_callable($output)) {
45647 $output = $process->getOutput();
45648 }
45649
45650 $this->errorOutput = $process->getErrorOutput();
45651
45652 return $process->getExitCode();
45653 }
45654
45655 public function splitLines($output)
45656 {
45657 $output = trim($output);
45658
45659 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
45660 }
45661
45662
45663
45664
45665
45666
45667 public function getErrorOutput()
45668 {
45669 return $this->errorOutput;
45670 }
45671
45672 public function outputHandler($type, $buffer)
45673 {
45674 if ($this->captureOutput) {
45675 return;
45676 }
45677
45678 if (null === $this->io) {
45679 echo $buffer;
45680
45681 return;
45682 }
45683
45684 if (method_exists($this->io, 'writeRaw')) {
45685 if (Process::ERR === $type) {
45686 $this->io->writeErrorRaw($buffer, false);
45687 } else {
45688 $this->io->writeRaw($buffer, false);
45689 }
45690 } else {
45691 if (Process::ERR === $type) {
45692 $this->io->writeError($buffer, false);
45693 } else {
45694 $this->io->write($buffer, false);
45695 }
45696 }
45697 }
45698
45699 public static function getTimeout()
45700 {
45701 return static::$timeout;
45702 }
45703
45704 public static function setTimeout($timeout)
45705 {
45706 static::$timeout = $timeout;
45707 }
45708
45709
45710
45711
45712
45713
45714
45715
45716 public static function escape($argument)
45717 {
45718 return self::escapeArgument($argument);
45719 }
45720
45721
45722
45723
45724
45725
45726
45727
45728 private static function escapeArgument($argument)
45729 {
45730
45731  
45732  
45733  
45734  if ('\\' === DIRECTORY_SEPARATOR) {
45735 if ((string) $argument === '') {
45736 return escapeshellarg($argument);
45737 }
45738
45739 $escapedArgument = '';
45740 $quote = false;
45741 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
45742 if ('"' === $part) {
45743 $escapedArgument .= '\\"';
45744 } elseif (self::isSurroundedBy($part, '%')) {
45745
45746  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
45747 } else {
45748
45749  if ('\\' === substr($part, -1)) {
45750 $part .= '\\';
45751 }
45752 $quote = true;
45753 $escapedArgument .= $part;
45754 }
45755 }
45756 if ($quote) {
45757 $escapedArgument = '"'.$escapedArgument.'"';
45758 }
45759
45760 return $escapedArgument;
45761 }
45762
45763 return "'".str_replace("'", "'\\''", $argument)."'";
45764 }
45765
45766 private static function isSurroundedBy($arg, $char)
45767 {
45768 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
45769 }
45770 }
45771 <?php
45772
45773
45774
45775
45776
45777
45778
45779
45780
45781
45782
45783 namespace Composer\Util;
45784
45785 use Composer\Config;
45786 use Composer\Composer;
45787 use Composer\Semver\Constraint\Constraint;
45788 use Composer\Package\Version\VersionParser;
45789 use Composer\IO\IOInterface;
45790 use Composer\Downloader\TransportException;
45791 use Composer\CaBundle\CaBundle;
45792 use Psr\Log\LoggerInterface;
45793
45794
45795
45796
45797
45798
45799 class RemoteFilesystem
45800 {
45801 private $io;
45802 private $config;
45803 private $scheme;
45804 private $bytesMax;
45805 private $originUrl;
45806 private $fileUrl;
45807 private $fileName;
45808 private $retry;
45809 private $progress;
45810 private $lastProgress;
45811 private $options = array();
45812 private $peerCertificateMap = array();
45813 private $disableTls = false;
45814 private $retryAuthFailure;
45815 private $lastHeaders;
45816 private $storeAuth;
45817 private $degradedMode = false;
45818 private $redirects;
45819 private $maxRedirects = 20;
45820 private $displayedOriginAuthentications = array();
45821
45822
45823
45824
45825
45826
45827
45828
45829
45830 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
45831 {
45832 $this->io = $io;
45833
45834
45835  
45836  if ($disableTls === false) {
45837 $this->options = $this->getTlsDefaults($options);
45838 } else {
45839 $this->disableTls = true;
45840 }
45841
45842
45843  $this->options = array_replace_recursive($this->options, $options);
45844 $this->config = $config;
45845 }
45846
45847
45848
45849
45850
45851
45852
45853
45854
45855
45856
45857
45858 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
45859 {
45860 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
45861 }
45862
45863
45864
45865
45866
45867
45868
45869
45870
45871
45872
45873 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
45874 {
45875 return $this->get($originUrl, $fileUrl, $options, null, $progress);
45876 }
45877
45878
45879
45880
45881
45882
45883 public function getOptions()
45884 {
45885 return $this->options;
45886 }
45887
45888
45889
45890
45891
45892
45893 public function setOptions(array $options)
45894 {
45895 $this->options = array_replace_recursive($this->options, $options);
45896 }
45897
45898
45899
45900
45901
45902
45903 public function isTlsDisabled()
45904 {
45905 return $this->disableTls === true;
45906 }
45907
45908
45909
45910
45911
45912
45913 public function getLastHeaders()
45914 {
45915 return $this->lastHeaders;
45916 }
45917
45918
45919
45920
45921
45922
45923 public function findHeaderValue(array $headers, $name)
45924 {
45925 $value = null;
45926 foreach ($headers as $header) {
45927 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
45928 $value = $match[1];
45929 } elseif (preg_match('{^HTTP/}i', $header)) {
45930
45931  
45932  $value = null;
45933 }
45934 }
45935
45936 return $value;
45937 }
45938
45939
45940
45941
45942
45943 public function findStatusCode(array $headers)
45944 {
45945 $value = null;
45946 foreach ($headers as $header) {
45947 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
45948
45949  
45950  $value = (int) $match[1];
45951 }
45952 }
45953
45954 return $value;
45955 }
45956
45957
45958
45959
45960
45961 public function findStatusMessage(array $headers)
45962 {
45963 $value = null;
45964 foreach ($headers as $header) {
45965 if (preg_match('{^HTTP/\S+ \d+}i', $header)) {
45966
45967  
45968  $value = $header;
45969 }
45970 }
45971
45972 return $value;
45973 }
45974
45975
45976
45977
45978
45979
45980
45981
45982
45983
45984
45985
45986
45987
45988
45989 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
45990 {
45991 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
45992 $originUrl = 'github.com';
45993 }
45994
45995
45996  
45997  if (
45998 $this->config
45999 && is_array($this->config->get('gitlab-domains'))
46000 && false === strpos($originUrl, '/')
46001 && !in_array($originUrl, $this->config->get('gitlab-domains'))
46002 ) {
46003 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
46004 if (0 === strpos($gitlabDomain, $originUrl)) {
46005 $originUrl = $gitlabDomain;
46006 break;
46007 }
46008 }
46009 unset($gitlabDomain);
46010 }
46011
46012 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
46013 $this->bytesMax = 0;
46014 $this->originUrl = $originUrl;
46015 $this->fileUrl = $fileUrl;
46016 $this->fileName = $fileName;
46017 $this->progress = $progress;
46018 $this->lastProgress = null;
46019 $this->retryAuthFailure = true;
46020 $this->lastHeaders = array();
46021 $this->redirects = 1; 
46022
46023
46024  if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
46025 $this->io->setAuthentication($originUrl, rawurldecode($match[1]), rawurldecode($match[2]));
46026 }
46027
46028 $tempAdditionalOptions = $additionalOptions;
46029 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
46030 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
46031
46032 unset($tempAdditionalOptions['retry-auth-failure']);
46033 }
46034
46035 $isRedirect = false;
46036 if (isset($tempAdditionalOptions['redirects'])) {
46037 $this->redirects = $tempAdditionalOptions['redirects'];
46038 $isRedirect = true;
46039
46040 unset($tempAdditionalOptions['redirects']);
46041 }
46042
46043 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
46044 unset($tempAdditionalOptions);
46045
46046 $origFileUrl = $fileUrl;
46047
46048 if (isset($options['github-token'])) {
46049
46050  if (preg_match('{^https?://api\.github\.com/}', $fileUrl)) {
46051 $options['http']['header'][] = 'Authorization: token '.$options['github-token'];
46052 }
46053 unset($options['github-token']);
46054 }
46055
46056 if (isset($options['gitlab-token'])) {
46057 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
46058 unset($options['gitlab-token']);
46059 }
46060
46061 if (isset($options['http'])) {
46062 $options['http']['ignore_errors'] = true;
46063 }
46064
46065 if ($this->degradedMode && substr($fileUrl, 0, 26) === 'http://repo.packagist.org/') {
46066
46067  $fileUrl = 'http://' . gethostbyname('repo.packagist.org') . substr($fileUrl, 20);
46068 $degradedPackagist = true;
46069 }
46070
46071 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
46072
46073 $actualContextOptions = stream_context_get_options($ctx);
46074 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
46075 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $this->stripCredentialsFromUrl($origFileUrl) . $usingProxy, true, IOInterface::DEBUG);
46076 unset($origFileUrl, $actualContextOptions);
46077
46078
46079  if ((!preg_match('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
46080 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
46081 }
46082
46083 if ($this->progress && !$isRedirect) {
46084 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
46085 }
46086
46087 $errorMessage = '';
46088 $errorCode = 0;
46089 $result = false;
46090 set_error_handler(function ($code, $msg) use (&$errorMessage) {
46091 if ($errorMessage) {
46092 $errorMessage .= "\n";
46093 }
46094 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
46095
46096 return true;
46097 });
46098 try {
46099 $result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header);
46100
46101 if (!empty($http_response_header[0])) {
46102 $statusCode = $this->findStatusCode($http_response_header);
46103 if ($statusCode >= 400 && $this->findHeaderValue($http_response_header, 'content-type') === 'application/json') {
46104 self::outputWarnings($this->io, $originUrl, json_decode($result, true));
46105 }
46106
46107 if (in_array($statusCode, array(401, 403)) && $this->retryAuthFailure) {
46108 $this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), null, $http_response_header);
46109 }
46110 }
46111
46112 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
46113 if ($contentLength && Platform::strlen($result) < $contentLength) {
46114
46115  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
46116 $e->setHeaders($http_response_header);
46117 $e->setStatusCode($this->findStatusCode($http_response_header));
46118 $e->setResponse($result);
46119 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
46120
46121 throw $e;
46122 }
46123
46124 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
46125
46126  $params = stream_context_get_params($ctx);
46127 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
46128 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
46129
46130
46131  if ($expectedPeerFingerprint !== $peerFingerprint) {
46132 throw new TransportException('Peer fingerprint did not match');
46133 }
46134 }
46135 } catch (\Exception $e) {
46136 if ($e instanceof TransportException && !empty($http_response_header[0])) {
46137 $e->setHeaders($http_response_header);
46138 $e->setStatusCode($this->findStatusCode($http_response_header));
46139 }
46140 if ($e instanceof TransportException && $result !== false) {
46141 $e->setResponse($result);
46142 }
46143 $result = false;
46144 }
46145 if ($errorMessage && !filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
46146 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
46147 }
46148 restore_error_handler();
46149 if (isset($e) && !$this->retry) {
46150 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
46151 $this->degradedMode = true;
46152 $this->io->writeError('');
46153 $this->io->writeError(array(
46154 '<error>'.$e->getMessage().'</error>',
46155 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
46156 ));
46157
46158 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46159 }
46160
46161 throw $e;
46162 }
46163
46164 $statusCode = null;
46165 $contentType = null;
46166 $locationHeader = null;
46167 if (!empty($http_response_header[0])) {
46168 $statusCode = $this->findStatusCode($http_response_header);
46169 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
46170 $locationHeader = $this->findHeaderValue($http_response_header, 'location');
46171 }
46172
46173
46174  if ($originUrl === 'bitbucket.org'
46175 && !$this->isPublicBitBucketDownload($fileUrl)
46176 && substr($fileUrl, -4) === '.zip'
46177 && (!$locationHeader || substr($locationHeader, -4) !== '.zip')
46178 && $contentType && preg_match('{^text/html\b}i', $contentType)
46179 ) {
46180 $result = false;
46181 if ($this->retryAuthFailure) {
46182 $this->promptAuthAndRetry(401);
46183 }
46184 }
46185
46186
46187  if ($statusCode === 404
46188 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
46189 && false !== strpos($fileUrl, 'archive.zip')
46190 ) {
46191 $result = false;
46192 if ($this->retryAuthFailure) {
46193 $this->promptAuthAndRetry(401);
46194 }
46195 }
46196
46197
46198  $hasFollowedRedirect = false;
46199 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
46200 $hasFollowedRedirect = true;
46201 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
46202 }
46203
46204
46205  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
46206 if (!$this->retry) {
46207 if ($this->progress && !$this->retry && !$isRedirect) {
46208 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
46209 }
46210
46211 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
46212 $e->setHeaders($http_response_header);
46213 $e->setResponse($result);
46214 $e->setStatusCode($statusCode);
46215 throw $e;
46216 }
46217 $result = false;
46218 }
46219
46220 if ($this->progress && !$this->retry && !$isRedirect) {
46221 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
46222 }
46223
46224
46225  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
46226 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
46227 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
46228
46229 if ($decode) {
46230 try {
46231 if (PHP_VERSION_ID >= 50400) {
46232 $result = zlib_decode($result);
46233 } else {
46234
46235  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
46236 }
46237
46238 if (!$result) {
46239 throw new TransportException('Failed to decode zlib stream');
46240 }
46241 } catch (\Exception $e) {
46242 if ($this->degradedMode) {
46243 throw $e;
46244 }
46245
46246 $this->degradedMode = true;
46247 $this->io->writeError(array(
46248 '',
46249 '<error>Failed to decode response: '.$e->getMessage().'</error>',
46250 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
46251 ));
46252
46253 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46254 }
46255 }
46256 }
46257
46258
46259  if (false !== $result && null !== $fileName && !$isRedirect) {
46260 if ('' === $result) {
46261 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
46262 }
46263
46264 $errorMessage = '';
46265 set_error_handler(function ($code, $msg) use (&$errorMessage) {
46266 if ($errorMessage) {
46267 $errorMessage .= "\n";
46268 }
46269 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
46270
46271 return true;
46272 });
46273 $result = (bool) file_put_contents($fileName, $result);
46274 restore_error_handler();
46275 if (false === $result) {
46276 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
46277 }
46278 }
46279
46280
46281  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
46282
46283  
46284  
46285  
46286  
46287  
46288  
46289  
46290  
46291  
46292  
46293  
46294  
46295  
46296  
46297  
46298  if (CaBundle::isOpensslParseSafe()) {
46299 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
46300
46301 if ($certDetails) {
46302 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
46303
46304 $this->retry = true;
46305 }
46306 } else {
46307 $this->io->writeError('');
46308 $this->io->writeError(sprintf(
46309 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
46310 PHP_VERSION
46311 ));
46312 }
46313 }
46314
46315 if ($this->retry) {
46316 $this->retry = false;
46317
46318 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46319
46320 if ($this->storeAuth && $this->config) {
46321 $authHelper = new AuthHelper($this->io, $this->config);
46322 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
46323 $this->storeAuth = false;
46324 }
46325
46326 return $result;
46327 }
46328
46329 if (false === $result) {
46330 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
46331 if (!empty($http_response_header[0])) {
46332 $e->setHeaders($http_response_header);
46333 }
46334
46335 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
46336 $this->degradedMode = true;
46337 $this->io->writeError('');
46338 $this->io->writeError(array(
46339 '<error>'.$e->getMessage().'</error>',
46340 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
46341 ));
46342
46343 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
46344 }
46345
46346 throw $e;
46347 }
46348
46349 if (!empty($http_response_header[0])) {
46350 $this->lastHeaders = $http_response_header;
46351 }
46352
46353 return $result;
46354 }
46355
46356
46357
46358
46359
46360
46361
46362
46363
46364
46365 protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null)
46366 {
46367 try {
46368 $e = null;
46369 $result = file_get_contents($fileUrl, false, $context);
46370 } catch (\Throwable $e) {
46371 } catch (\Exception $e) {
46372 }
46373
46374 $responseHeaders = isset($http_response_header) ? $http_response_header : array();
46375
46376 if (null !== $e) {
46377 throw $e;
46378 }
46379
46380 return $result;
46381 }
46382
46383
46384
46385
46386
46387
46388
46389
46390
46391
46392
46393
46394 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
46395 {
46396 switch ($notificationCode) {
46397 case STREAM_NOTIFY_FAILURE:
46398 if (400 === $messageCode) {
46399
46400  
46401  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
46402 }
46403 break;
46404
46405 case STREAM_NOTIFY_FILE_SIZE_IS:
46406 $this->bytesMax = $bytesMax;
46407 break;
46408
46409 case STREAM_NOTIFY_PROGRESS:
46410 if ($this->bytesMax > 0 && $this->progress) {
46411 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
46412
46413 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
46414 $this->lastProgress = $progression;
46415 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
46416 }
46417 }
46418 break;
46419
46420 default:
46421 break;
46422 }
46423 }
46424
46425 protected function promptAuthAndRetry($httpStatus, $reason = null, $warning = null, $headers = array())
46426 {
46427 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
46428 $gitHubUtil = new GitHub($this->io, $this->config, null);
46429 $message = "\n";
46430
46431 $rateLimited = $gitHubUtil->isRateLimited($headers);
46432 if ($rateLimited) {
46433 $rateLimit = $gitHubUtil->getRateLimit($headers);
46434 if ($this->io->hasAuthentication($this->originUrl)) {
46435 $message = 'Review your configured GitHub OAuth token or enter a new one to go over the API rate limit.';
46436 } else {
46437 $message = 'Create a GitHub OAuth token to go over the API rate limit.';
46438 }
46439
46440 $message = sprintf(
46441 '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.',
46442 $rateLimit['limit'],
46443 $rateLimit['reset']
46444 )."\n";
46445 } else {
46446 $message .= 'Could not fetch '.$this->fileUrl.', please ';
46447 if ($this->io->hasAuthentication($this->originUrl)) {
46448 $message .= 'review your configured GitHub OAuth token or enter a new one to access private repos';
46449 } else {
46450 $message .= 'create a GitHub OAuth token to access private repos';
46451 }
46452 }
46453
46454 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
46455 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
46456 ) {
46457 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
46458 }
46459 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
46460 $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');
46461 $gitLabUtil = new GitLab($this->io, $this->config, null);
46462
46463 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && in_array($auth['password'], array('gitlab-ci-token', 'private-token', 'oauth2'), true)) {
46464 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
46465 }
46466
46467 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
46468 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
46469 ) {
46470 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
46471 }
46472 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
46473 $askForOAuthToken = true;
46474 if ($this->io->hasAuthentication($this->originUrl)) {
46475 $auth = $this->io->getAuthentication($this->originUrl);
46476 if ($auth['username'] !== 'x-token-auth') {
46477 $bitbucketUtil = new Bitbucket($this->io, $this->config);
46478 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
46479 if (!empty($accessToken)) {
46480 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
46481 $askForOAuthToken = false;
46482 }
46483 } else {
46484 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
46485 }
46486 }
46487
46488 if ($askForOAuthToken) {
46489 $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');
46490 $bitBucketUtil = new Bitbucket($this->io, $this->config);
46491 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
46492 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
46493 ) {
46494 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
46495 }
46496 }
46497 } else {
46498
46499  if ($httpStatus === 404) {
46500 return;
46501 }
46502
46503
46504  if (!$this->io->isInteractive()) {
46505 if ($httpStatus === 401) {
46506 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
46507 }
46508 if ($httpStatus === 403) {
46509 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
46510 }
46511
46512 throw new TransportException($message, $httpStatus);
46513 }
46514
46515  if ($this->io->hasAuthentication($this->originUrl)) {
46516 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
46517 }
46518
46519 $this->io->writeError('    Authentication required (<info>'.$this->originUrl.'</info>):');
46520 $username = $this->io->ask('      Username: ');
46521 $password = $this->io->askAndHideAnswer('      Password: ');
46522 $this->io->setAuthentication($this->originUrl, $username, $password);
46523 $this->storeAuth = $this->config->get('store-auths');
46524 }
46525
46526 $this->retry = true;
46527 throw new TransportException('RETRY');
46528 }
46529
46530 protected function getOptionsForUrl($originUrl, $additionalOptions)
46531 {
46532 $tlsOptions = array();
46533
46534
46535  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
46536 $host = parse_url($this->fileUrl, PHP_URL_HOST);
46537
46538 if (PHP_VERSION_ID < 50304) {
46539
46540  
46541  
46542  
46543
46544 if ($host === 'github.com' || $host === 'api.github.com') {
46545 $host = '*.github.com';
46546 }
46547 }
46548
46549 $tlsOptions['ssl']['CN_match'] = $host;
46550 $tlsOptions['ssl']['SNI_server_name'] = $host;
46551
46552 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
46553
46554 if (isset($this->peerCertificateMap[$urlAuthority])) {
46555
46556  $certMap = $this->peerCertificateMap[$urlAuthority];
46557
46558 $this->io->writeError('', true, IOInterface::DEBUG);
46559 $this->io->writeError(sprintf(
46560 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
46561 $certMap['cn'],
46562 $urlAuthority
46563 ), true, IOInterface::DEBUG);
46564
46565 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
46566 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
46567 } elseif (!CaBundle::isOpensslParseSafe() && $host === 'repo.packagist.org') {
46568
46569  $tlsOptions['ssl']['CN_match'] = 'packagist.org';
46570 }
46571 }
46572
46573 $headers = array();
46574
46575 if (extension_loaded('zlib')) {
46576 $headers[] = 'Accept-Encoding: gzip';
46577 }
46578
46579 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
46580 if (!$this->degradedMode) {
46581
46582  
46583  $options['http']['protocol_version'] = 1.1;
46584 $headers[] = 'Connection: close';
46585 }
46586
46587 if ($this->io->hasAuthentication($originUrl)) {
46588 $authenticationDisplayMessage = null;
46589 $auth = $this->io->getAuthentication($originUrl);
46590 if ($auth['password'] === 'bearer') {
46591 $headers[] = 'Authorization: Bearer '.$auth['username'];
46592 } elseif ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
46593 $options['github-token'] = $auth['username'];
46594 $authenticationDisplayMessage = 'Using GitHub token authentication';
46595 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
46596 if ($auth['password'] === 'oauth2') {
46597 $headers[] = 'Authorization: Bearer '.$auth['username'];
46598 $authenticationDisplayMessage = 'Using GitLab OAuth token authentication';
46599 } elseif ($auth['password'] === 'private-token' || $auth['password'] === 'gitlab-ci-token') {
46600 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
46601 $authenticationDisplayMessage = 'Using GitLab private token authentication';
46602 }
46603 } elseif ('bitbucket.org' === $originUrl
46604 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
46605 ) {
46606 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
46607 $headers[] = 'Authorization: Bearer ' . $auth['password'];
46608 $authenticationDisplayMessage = 'Using Bitbucket OAuth token authentication';
46609 }
46610 } else {
46611 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
46612 $headers[] = 'Authorization: Basic '.$authStr;
46613 $authenticationDisplayMessage = 'Using HTTP basic authentication with username "' . $auth['username'] . '"';
46614 }
46615
46616 if ($authenticationDisplayMessage && !in_array($originUrl, $this->displayedOriginAuthentications, true)) {
46617 $this->io->writeError($authenticationDisplayMessage, true, IOInterface::DEBUG);
46618 $this->displayedOriginAuthentications[] = $originUrl;
46619 }
46620 }
46621
46622 $options['http']['follow_location'] = 0;
46623
46624 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
46625 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
46626 }
46627 foreach ($headers as $header) {
46628 $options['http']['header'][] = $header;
46629 }
46630
46631 return $options;
46632 }
46633
46634 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
46635 {
46636 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
46637 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
46638
46639  $targetUrl = $locationHeader;
46640 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
46641
46642  $targetUrl = $this->scheme.':'.$locationHeader;
46643 } elseif ('/' === $locationHeader[0]) {
46644
46645  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
46646
46647
46648  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
46649 } else {
46650
46651  
46652  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
46653 }
46654 }
46655
46656 if (!empty($targetUrl)) {
46657 $this->redirects++;
46658
46659 $this->io->writeError('', true, IOInterface::DEBUG);
46660 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $this->stripCredentialsFromUrl($targetUrl)), true, IOInterface::DEBUG);
46661
46662 $additionalOptions['redirects'] = $this->redirects;
46663
46664 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
46665 }
46666
46667 if (!$this->retry) {
46668 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
46669 $e->setHeaders($http_response_header);
46670 $e->setResponse($result);
46671
46672 throw $e;
46673 }
46674
46675 return false;
46676 }
46677
46678
46679
46680
46681
46682
46683 private function getTlsDefaults(array $options)
46684 {
46685 $ciphers = implode(':', array(
46686 'ECDHE-RSA-AES128-GCM-SHA256',
46687 'ECDHE-ECDSA-AES128-GCM-SHA256',
46688 'ECDHE-RSA-AES256-GCM-SHA384',
46689 'ECDHE-ECDSA-AES256-GCM-SHA384',
46690 'DHE-RSA-AES128-GCM-SHA256',
46691 'DHE-DSS-AES128-GCM-SHA256',
46692 'kEDH+AESGCM',
46693 'ECDHE-RSA-AES128-SHA256',
46694 'ECDHE-ECDSA-AES128-SHA256',
46695 'ECDHE-RSA-AES128-SHA',
46696 'ECDHE-ECDSA-AES128-SHA',
46697 'ECDHE-RSA-AES256-SHA384',
46698 'ECDHE-ECDSA-AES256-SHA384',
46699 'ECDHE-RSA-AES256-SHA',
46700 'ECDHE-ECDSA-AES256-SHA',
46701 'DHE-RSA-AES128-SHA256',
46702 'DHE-RSA-AES128-SHA',
46703 'DHE-DSS-AES128-SHA256',
46704 'DHE-RSA-AES256-SHA256',
46705 'DHE-DSS-AES256-SHA',
46706 'DHE-RSA-AES256-SHA',
46707 'AES128-GCM-SHA256',
46708 'AES256-GCM-SHA384',
46709 'AES128-SHA256',
46710 'AES256-SHA256',
46711 'AES128-SHA',
46712 'AES256-SHA',
46713 'AES',
46714 'CAMELLIA',
46715 'DES-CBC3-SHA',
46716 '!aNULL',
46717 '!eNULL',
46718 '!EXPORT',
46719 '!DES',
46720 '!RC4',
46721 '!MD5',
46722 '!PSK',
46723 '!aECDH',
46724 '!EDH-DSS-DES-CBC3-SHA',
46725 '!EDH-RSA-DES-CBC3-SHA',
46726 '!KRB5-DES-CBC3-SHA',
46727 ));
46728
46729
46730
46731
46732
46733
46734
46735 $defaults = array(
46736 'ssl' => array(
46737 'ciphers' => $ciphers,
46738 'verify_peer' => true,
46739 'verify_depth' => 7,
46740 'SNI_enabled' => true,
46741 'capture_peer_cert' => true,
46742 ),
46743 );
46744
46745 if (isset($options['ssl'])) {
46746 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
46747 }
46748
46749 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
46750
46751
46752
46753
46754
46755 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
46756 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
46757
46758 if (is_dir($result)) {
46759 $defaults['ssl']['capath'] = $result;
46760 } else {
46761 $defaults['ssl']['cafile'] = $result;
46762 }
46763 }
46764
46765 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
46766 throw new TransportException('The configured cafile was not valid or could not be read.');
46767 }
46768
46769 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
46770 throw new TransportException('The configured capath was not valid or could not be read.');
46771 }
46772
46773
46774
46775
46776 if (PHP_VERSION_ID >= 50413) {
46777 $defaults['ssl']['disable_compression'] = true;
46778 }
46779
46780 return $defaults;
46781 }
46782
46783
46784
46785
46786
46787
46788 private function getCertificateCnAndFp($url, $options)
46789 {
46790 if (PHP_VERSION_ID >= 50600) {
46791 throw new \BadMethodCallException(sprintf(
46792 '%s must not be used on PHP >= 5.6',
46793 __METHOD__
46794 ));
46795 }
46796
46797 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
46798 'ssl' => array(
46799 'capture_peer_cert' => true,
46800 'verify_peer' => false, 
46801  ), ),
46802 ));
46803
46804
46805  
46806  if (false === $handle = @fopen($url, 'rb', false, $context)) {
46807 return;
46808 }
46809
46810
46811  fclose($handle);
46812 $handle = null;
46813
46814 $params = stream_context_get_params($context);
46815
46816 if (!empty($params['options']['ssl']['peer_certificate'])) {
46817 $peerCertificate = $params['options']['ssl']['peer_certificate'];
46818
46819 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
46820 return array(
46821 'cn' => $commonName,
46822 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
46823 );
46824 }
46825 }
46826 }
46827
46828 private function getUrlAuthority($url)
46829 {
46830 $defaultPorts = array(
46831 'ftp' => 21,
46832 'http' => 80,
46833 'https' => 443,
46834 'ssh2.sftp' => 22,
46835 'ssh2.scp' => 22,
46836 );
46837
46838 $scheme = parse_url($url, PHP_URL_SCHEME);
46839
46840 if (!isset($defaultPorts[$scheme])) {
46841 throw new \InvalidArgumentException(sprintf(
46842 'Could not get default port for unknown scheme: %s',
46843 $scheme
46844 ));
46845 }
46846
46847 $defaultPort = $defaultPorts[$scheme];
46848 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
46849
46850 return parse_url($url, PHP_URL_HOST).':'.$port;
46851 }
46852
46853
46854
46855
46856
46857
46858
46859
46860 private function isPublicBitBucketDownload($urlToBitBucketFile)
46861 {
46862 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
46863 if (strpos($domain, 'bitbucket.org') === false) {
46864
46865  
46866  return true;
46867 }
46868
46869 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
46870
46871
46872  
46873  $pathParts = explode('/', $path);
46874
46875 return count($pathParts) >= 4 && $pathParts[3] == 'downloads';
46876 }
46877
46878 public static function outputWarnings(IOInterface $io, $url, $data)
46879 {
46880 foreach (array('warning', 'info') as $type) {
46881 if (empty($data[$type])) {
46882 continue;
46883 }
46884
46885 if (!empty($data[$type . '-versions'])) {
46886 $versionParser = new VersionParser();
46887 $constraint = $versionParser->parseConstraints($data[$type . '-versions']);
46888 $composer = new Constraint('==', $versionParser->normalize(Composer::getVersion()));
46889 if (!$constraint->matches($composer)) {
46890 continue;
46891 }
46892 }
46893
46894 $io->writeError('<'.$type.'>'.ucfirst($type).' from '.$url.': '.$data[$type].'</'.$type.'>');
46895 }
46896 }
46897
46898 public static function getOrigin($urlOrPath)
46899 {
46900 $hostPort = parse_url($urlOrPath, PHP_URL_HOST);
46901 if (!$hostPort) {
46902 return $urlOrPath;
46903 }
46904 if (parse_url($urlOrPath, PHP_URL_PORT)) {
46905 $hostPort .= ':'.parse_url($urlOrPath, PHP_URL_PORT);
46906 }
46907
46908 return $hostPort;
46909 }
46910
46911 private function stripCredentialsFromUrl($url)
46912 {
46913
46914  
46915  return preg_replace('{([&?]access_token=)[^&]+}', '$1***', $url);
46916 }
46917 }
46918 <?php
46919
46920
46921
46922
46923
46924
46925
46926
46927
46928
46929
46930 namespace Composer\Util;
46931
46932
46933
46934
46935
46936
46937 class Silencer
46938 {
46939
46940
46941
46942 private static $stack = array();
46943
46944
46945
46946
46947
46948
46949
46950 public static function suppress($mask = null)
46951 {
46952 if (!isset($mask)) {
46953 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
46954 }
46955 $old = error_reporting();
46956 self::$stack[] = $old;
46957 error_reporting($old & ~$mask);
46958
46959 return $old;
46960 }
46961
46962
46963
46964
46965 public static function restore()
46966 {
46967 if (!empty(self::$stack)) {
46968 error_reporting(array_pop(self::$stack));
46969 }
46970 }
46971
46972
46973
46974
46975
46976
46977
46978
46979
46980
46981 public static function call($callable )
46982 {
46983 try {
46984 self::suppress();
46985 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
46986 self::restore();
46987
46988 return $result;
46989 } catch (\Exception $e) {
46990
46991  self::restore();
46992 throw $e;
46993 }
46994 }
46995 }
46996 <?php
46997
46998
46999
47000
47001
47002
47003
47004
47005
47006
47007
47008 namespace Composer\Util;
47009
47010 use Composer\Spdx\SpdxLicenses;
47011
47012 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
47013
47014
47015
47016
47017 class SpdxLicense extends SpdxLicenses
47018 {
47019 }
47020 <?php
47021
47022
47023
47024
47025
47026
47027
47028
47029
47030
47031
47032 namespace Composer\Util;
47033
47034 use Composer\Composer;
47035
47036
47037
47038
47039
47040
47041
47042 final class StreamContextFactory
47043 {
47044
47045
47046
47047
47048
47049
47050
47051
47052
47053 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
47054 {
47055 $options = array('http' => array(
47056
47057  'follow_location' => 1,
47058 'max_redirects' => 20,
47059 ));
47060
47061
47062  if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
47063 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
47064 }
47065
47066
47067  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
47068 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
47069 }
47070
47071
47072  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
47073 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
47074 }
47075
47076
47077  if (!empty($_SERVER['NO_PROXY']) || !empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
47078 $pattern = new NoProxyPattern(!empty($_SERVER['no_proxy']) ? $_SERVER['no_proxy'] : $_SERVER['NO_PROXY']);
47079 if ($pattern->test($url)) {
47080 unset($proxy);
47081 }
47082 }
47083
47084 if (!empty($proxy)) {
47085 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
47086 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
47087
47088 if (isset($proxy['port'])) {
47089 $proxyURL .= ":" . $proxy['port'];
47090 } elseif ('http://' == substr($proxyURL, 0, 7)) {
47091 $proxyURL .= ":80";
47092 } elseif ('https://' == substr($proxyURL, 0, 8)) {
47093 $proxyURL .= ":443";
47094 }
47095
47096
47097  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
47098
47099 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
47100 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
47101 }
47102
47103 $options['http']['proxy'] = $proxyURL;
47104
47105
47106  switch (parse_url($url, PHP_URL_SCHEME)) {
47107 case 'http': 
47108  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
47109 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
47110 $options['http']['request_fulluri'] = true;
47111 }
47112 break;
47113 case 'https': 
47114  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
47115 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
47116 $options['http']['request_fulluri'] = true;
47117 }
47118 break;
47119 }
47120
47121
47122  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
47123 $options['ssl']['SNI_enabled'] = true;
47124 if (PHP_VERSION_ID < 50600) {
47125 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
47126 }
47127 }
47128
47129
47130  if (isset($proxy['user'])) {
47131 $auth = rawurldecode($proxy['user']);
47132 if (isset($proxy['pass'])) {
47133 $auth .= ':' . rawurldecode($proxy['pass']);
47134 }
47135 $auth = base64_encode($auth);
47136
47137
47138  if (isset($defaultOptions['http']['header'])) {
47139 if (is_string($defaultOptions['http']['header'])) {
47140 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
47141 }
47142 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
47143 } else {
47144 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
47145 }
47146 }
47147 }
47148
47149 $options = array_replace_recursive($options, $defaultOptions);
47150
47151 if (isset($options['http']['header'])) {
47152 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
47153 }
47154
47155 if (defined('HHVM_VERSION')) {
47156 $phpVersion = 'HHVM ' . HHVM_VERSION;
47157 } else {
47158 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
47159 }
47160
47161 if (!isset($options['http']['header']) || false === stripos(implode('', $options['http']['header']), 'user-agent')) {
47162 $options['http']['header'][] = sprintf(
47163 'User-Agent: Composer/%s (%s; %s; %s%s)',
47164 Composer::getVersion(),
47165 function_exists('php_uname') ? php_uname('s') : 'Unknown',
47166 function_exists('php_uname') ? php_uname('r') : 'Unknown',
47167 $phpVersion,
47168 getenv('CI') ? '; CI' : ''
47169 );
47170 }
47171
47172 return stream_context_create($options, $defaultParams);
47173 }
47174
47175
47176
47177
47178
47179
47180
47181
47182
47183
47184
47185 private static function fixHttpHeaderField($header)
47186 {
47187 if (!is_array($header)) {
47188 $header = explode("\r\n", $header);
47189 }
47190 uasort($header, function ($el) {
47191 return stripos($el, 'content-type') === 0 ? 1 : -1;
47192 });
47193
47194 return $header;
47195 }
47196 }
47197 <?php
47198
47199
47200
47201
47202
47203
47204
47205
47206
47207
47208
47209 namespace Composer\Util;
47210
47211 use Composer\Config;
47212 use Composer\IO\IOInterface;
47213
47214
47215
47216
47217
47218 class Svn
47219 {
47220 const MAX_QTY_AUTH_TRIES = 5;
47221
47222
47223
47224
47225 protected $credentials;
47226
47227
47228
47229
47230 protected $hasAuth;
47231
47232
47233
47234
47235 protected $io;
47236
47237
47238
47239
47240 protected $url;
47241
47242
47243
47244
47245 protected $cacheCredentials = true;
47246
47247
47248
47249
47250 protected $process;
47251
47252
47253
47254
47255 protected $qtyAuthTries = 0;
47256
47257
47258
47259
47260 protected $config;
47261
47262
47263
47264
47265 private static $version;
47266
47267
47268
47269
47270
47271
47272
47273 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
47274 {
47275 $this->url = $url;
47276 $this->io = $io;
47277 $this->config = $config;
47278 $this->process = $process ?: new ProcessExecutor($io);
47279 }
47280
47281 public static function cleanEnv()
47282 {
47283
47284  putenv("DYLD_LIBRARY_PATH");
47285 unset($_SERVER['DYLD_LIBRARY_PATH']);
47286 }
47287
47288
47289
47290
47291
47292
47293
47294
47295
47296
47297
47298
47299
47300
47301 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
47302 {
47303
47304  $this->config->prohibitUrlByConfig($url, $this->io);
47305
47306 return $this->executeWithAuthRetry($command, $cwd, $url, $path, $verbose);
47307 }
47308
47309
47310
47311
47312
47313
47314
47315
47316
47317
47318
47319
47320
47321 public function executeLocal($command, $path, $cwd = null, $verbose = false)
47322 {
47323
47324  return $this->executeWithAuthRetry($command, $cwd, '', $path, $verbose);
47325 }
47326
47327 private function executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose)
47328 {
47329
47330  $command = $this->getCommand($svnCommand, $url, $path);
47331
47332 $output = null;
47333 $io = $this->io;
47334 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
47335 if ($type !== 'out') {
47336 return;
47337 }
47338 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
47339 return;
47340 }
47341 $output .= $buffer;
47342 if ($verbose) {
47343 $io->writeError($buffer, false);
47344 }
47345 };
47346 $status = $this->process->execute($command, $handler, $cwd);
47347 if (0 === $status) {
47348 return $output;
47349 }
47350
47351 $errorOutput = $this->process->getErrorOutput();
47352 $fullOutput = implode("\n", array($output, $errorOutput));
47353
47354
47355  if (false === stripos($fullOutput, 'Could not authenticate to server:')
47356 && false === stripos($fullOutput, 'authorization failed')
47357 && false === stripos($fullOutput, 'svn: E170001:')
47358 && false === stripos($fullOutput, 'svn: E215004:')) {
47359 throw new \RuntimeException($fullOutput);
47360 }
47361
47362 if (!$this->hasAuth()) {
47363 $this->doAuthDance();
47364 }
47365
47366
47367  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
47368
47369  return $this->executeWithAuthRetry($svnCommand, $cwd, $url, $path, $verbose);
47370 }
47371
47372 throw new \RuntimeException(
47373 'wrong credentials provided ('.$fullOutput.')'
47374 );
47375 }
47376
47377
47378
47379
47380 public function setCacheCredentials($cacheCredentials)
47381 {
47382 $this->cacheCredentials = $cacheCredentials;
47383 }
47384
47385
47386
47387
47388
47389
47390
47391 protected function doAuthDance()
47392 {
47393
47394  if (!$this->io->isInteractive()) {
47395 throw new \RuntimeException(
47396 'can not ask for authentication in non interactive mode'
47397 );
47398 }
47399
47400 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
47401
47402 $this->hasAuth = true;
47403 $this->credentials['username'] = $this->io->ask("Username: ");
47404 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
47405
47406 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
47407
47408 return $this;
47409 }
47410
47411
47412
47413
47414
47415
47416
47417
47418
47419
47420 protected function getCommand($cmd, $url, $path = null)
47421 {
47422 $cmd = sprintf(
47423 '%s %s%s %s',
47424 $cmd,
47425 '--non-interactive ',
47426 $this->getCredentialString(),
47427 ProcessExecutor::escape($url)
47428 );
47429
47430 if ($path) {
47431 $cmd .= ' ' . ProcessExecutor::escape($path);
47432 }
47433
47434 return $cmd;
47435 }
47436
47437
47438
47439
47440
47441
47442
47443
47444 protected function getCredentialString()
47445 {
47446 if (!$this->hasAuth()) {
47447 return '';
47448 }
47449
47450 return sprintf(
47451 ' %s--username %s --password %s ',
47452 $this->getAuthCache(),
47453 ProcessExecutor::escape($this->getUsername()),
47454 ProcessExecutor::escape($this->getPassword())
47455 );
47456 }
47457
47458
47459
47460
47461
47462
47463
47464 protected function getPassword()
47465 {
47466 if ($this->credentials === null) {
47467 throw new \LogicException("No svn auth detected.");
47468 }
47469
47470 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
47471 }
47472
47473
47474
47475
47476
47477
47478
47479 protected function getUsername()
47480 {
47481 if ($this->credentials === null) {
47482 throw new \LogicException("No svn auth detected.");
47483 }
47484
47485 return $this->credentials['username'];
47486 }
47487
47488
47489
47490
47491
47492
47493 protected function hasAuth()
47494 {
47495 if (null !== $this->hasAuth) {
47496 return $this->hasAuth;
47497 }
47498
47499 if (false === $this->createAuthFromConfig()) {
47500 $this->createAuthFromUrl();
47501 }
47502
47503 return $this->hasAuth;
47504 }
47505
47506
47507
47508
47509
47510
47511 protected function getAuthCache()
47512 {
47513 return $this->cacheCredentials ? '' : '--no-auth-cache ';
47514 }
47515
47516
47517
47518
47519
47520
47521 private function createAuthFromConfig()
47522 {
47523 if (!$this->config->has('http-basic')) {
47524 return $this->hasAuth = false;
47525 }
47526
47527 $authConfig = $this->config->get('http-basic');
47528
47529 $host = parse_url($this->url, PHP_URL_HOST);
47530 if (isset($authConfig[$host])) {
47531 $this->credentials['username'] = $authConfig[$host]['username'];
47532 $this->credentials['password'] = $authConfig[$host]['password'];
47533
47534 return $this->hasAuth = true;
47535 }
47536
47537 return $this->hasAuth = false;
47538 }
47539
47540
47541
47542
47543
47544
47545 private function createAuthFromUrl()
47546 {
47547 $uri = parse_url($this->url);
47548 if (empty($uri['user'])) {
47549 return $this->hasAuth = false;
47550 }
47551
47552 $this->credentials['username'] = $uri['user'];
47553 if (!empty($uri['pass'])) {
47554 $this->credentials['password'] = $uri['pass'];
47555 }
47556
47557 return $this->hasAuth = true;
47558 }
47559
47560
47561
47562
47563
47564
47565 public function binaryVersion()
47566 {
47567 if (!self::$version) {
47568 if (0 === $this->process->execute('svn --version', $output)) {
47569 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match)) {
47570 self::$version = $match[1];
47571 }
47572 }
47573 }
47574
47575 return self::$version;
47576 }
47577 }
47578 <?php
47579
47580
47581
47582
47583
47584
47585
47586
47587
47588
47589
47590 namespace Composer\Util;
47591
47592 use Composer\CaBundle\CaBundle;
47593
47594
47595
47596
47597 final class TlsHelper
47598 {
47599
47600
47601
47602
47603
47604
47605
47606
47607
47608 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
47609 {
47610 $names = self::getCertificateNames($certificate);
47611
47612 if (empty($names)) {
47613 return false;
47614 }
47615
47616 $combinedNames = array_merge($names['san'], array($names['cn']));
47617 $hostname = strtolower($hostname);
47618
47619 foreach ($combinedNames as $certName) {
47620 $matcher = self::certNameMatcher($certName);
47621
47622 if ($matcher && $matcher($hostname)) {
47623 $cn = $names['cn'];
47624
47625 return true;
47626 }
47627 }
47628
47629 return false;
47630 }
47631
47632
47633
47634
47635
47636
47637
47638
47639 public static function getCertificateNames($certificate)
47640 {
47641 if (is_array($certificate)) {
47642 $info = $certificate;
47643 } elseif (CaBundle::isOpensslParseSafe()) {
47644 $info = openssl_x509_parse($certificate, false);
47645 }
47646
47647 if (!isset($info['subject']['commonName'])) {
47648 return null;
47649 }
47650
47651 $commonName = strtolower($info['subject']['commonName']);
47652 $subjectAltNames = array();
47653
47654 if (isset($info['extensions']['subjectAltName'])) {
47655 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
47656 $subjectAltNames = array_filter(array_map(function ($name) {
47657 if (0 === strpos($name, 'DNS:')) {
47658 return strtolower(ltrim(substr($name, 4)));
47659 }
47660
47661 return null;
47662 }, $subjectAltNames));
47663 $subjectAltNames = array_values($subjectAltNames);
47664 }
47665
47666 return array(
47667 'cn' => $commonName,
47668 'san' => $subjectAltNames,
47669 );
47670 }
47671
47672
47673
47674
47675
47676
47677
47678
47679
47680
47681
47682
47683
47684
47685
47686
47687
47688
47689
47690
47691
47692
47693
47694
47695
47696
47697
47698
47699
47700
47701
47702
47703
47704
47705
47706
47707
47708
47709
47710
47711 public static function getCertificateFingerprint($certificate)
47712 {
47713 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
47714 $pubkeypem = $pubkeydetails['key'];
47715
47716  $start = '-----BEGIN PUBLIC KEY-----';
47717 $end = '-----END PUBLIC KEY-----';
47718 $pemtrim = substr($pubkeypem, strpos($pubkeypem, $start) + strlen($start), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
47719 $der = base64_decode($pemtrim);
47720
47721 return sha1($der);
47722 }
47723
47724
47725
47726
47727
47728
47729
47730
47731
47732 public static function isOpensslParseSafe()
47733 {
47734 return CaBundle::isOpensslParseSafe();
47735 }
47736
47737
47738
47739
47740
47741
47742
47743
47744 private static function certNameMatcher($certName)
47745 {
47746 $wildcards = substr_count($certName, '*');
47747
47748 if (0 === $wildcards) {
47749
47750  return function ($hostname) use ($certName) {
47751 return $hostname === $certName;
47752 };
47753 }
47754
47755 if (1 === $wildcards) {
47756 $components = explode('.', $certName);
47757
47758 if (3 > count($components)) {
47759
47760  return;
47761 }
47762
47763 $firstComponent = $components[0];
47764
47765
47766  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
47767 return;
47768 }
47769
47770 $wildcardRegex = preg_quote($certName);
47771 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
47772 $wildcardRegex = "{^{$wildcardRegex}$}";
47773
47774 return function ($hostname) use ($wildcardRegex) {
47775 return 1 === preg_match($wildcardRegex, $hostname);
47776 };
47777 }
47778 }
47779 }
47780 <?php
47781
47782
47783
47784
47785
47786
47787
47788
47789
47790
47791
47792 namespace Composer\Util;
47793
47794 use Composer\Config;
47795
47796
47797
47798
47799 class Url
47800 {
47801 public static function updateDistReference(Config $config, $url, $ref)
47802 {
47803 $host = parse_url($url, PHP_URL_HOST);
47804
47805 if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') {
47806 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
47807
47808  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
47809 } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
47810
47811  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
47812 } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
47813
47814  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref;
47815 }
47816 } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') {
47817 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
47818
47819  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4];
47820 }
47821 } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') {
47822 if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) {
47823
47824  $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref;
47825 }
47826 } elseif (in_array($host, $config->get('github-domains'), true)) {
47827 $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url);
47828 } elseif (in_array($host, $config->get('gitlab-domains'), true)) {
47829 $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url);
47830 }
47831
47832 return $url;
47833 }
47834 }
47835 <?php
47836
47837
47838
47839
47840
47841
47842
47843
47844
47845
47846
47847 namespace Composer\Util;
47848
47849
47850
47851
47852 class Zip
47853 {
47854
47855
47856
47857
47858
47859
47860
47861 public static function getComposerJson($pathToZip)
47862 {
47863 if (!extension_loaded('zip')) {
47864 throw new \RuntimeException('The Zip Util requires PHP\'s zip extension');
47865 }
47866
47867 $zip = new \ZipArchive();
47868 if ($zip->open($pathToZip) !== true) {
47869 return null;
47870 }
47871
47872 if (0 == $zip->numFiles) {
47873 $zip->close();
47874
47875 return null;
47876 }
47877
47878 $foundFileIndex = self::locateFile($zip, 'composer.json');
47879 if (false === $foundFileIndex) {
47880 $zip->close();
47881
47882 return null;
47883 }
47884
47885 $content = null;
47886 $configurationFileName = $zip->getNameIndex($foundFileIndex);
47887 $stream = $zip->getStream($configurationFileName);
47888
47889 if (false !== $stream) {
47890 $content = stream_get_contents($stream);
47891 }
47892
47893 $zip->close();
47894
47895 return $content;
47896 }
47897
47898
47899
47900
47901
47902
47903
47904
47905
47906 private static function locateFile(\ZipArchive $zip, $filename)
47907 {
47908 $indexOfShortestMatch = false;
47909 $lengthOfShortestMatch = -1;
47910
47911 for ($i = 0; $i < $zip->numFiles; $i++) {
47912 $stat = $zip->statIndex($i);
47913 if (strcmp(basename($stat['name']), $filename) === 0) {
47914 $directoryName = dirname($stat['name']);
47915 if ($directoryName === '.') {
47916
47917  
47918  return $i;
47919 }
47920
47921 if (strpos($directoryName, '\\') !== false ||
47922 strpos($directoryName, '/') !== false) {
47923
47924  continue;
47925 }
47926
47927 $length = strlen($stat['name']);
47928 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
47929
47930  $contents = $zip->getFromIndex($i);
47931 if ($contents !== false) {
47932 $indexOfShortestMatch = $i;
47933 $lengthOfShortestMatch = $length;
47934 }
47935 }
47936 }
47937 }
47938
47939 return $indexOfShortestMatch;
47940 }
47941 }
47942 <?php
47943
47944
47945
47946
47947
47948
47949
47950
47951
47952
47953
47954 namespace Composer;
47955
47956 use Symfony\Component\Console\Output\OutputInterface;
47957
47958 trigger_error('The ' . __NAMESPACE__ . '\XdebugHandler class is deprecated, use Composer\XdebugHandler\XdebugHandler instead,', E_USER_DEPRECATED);
47959
47960
47961
47962
47963 class XdebugHandler extends XdebugHandler\XdebugHandler
47964 {
47965 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
47966 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
47967
47968 public function __construct(OutputInterface $output)
47969 {
47970 parent::__construct('composer', '--ansi');
47971 }
47972 }
47973 <?php
47974
47975
47976
47977
47978
47979
47980
47981
47982
47983
47984
47985 function includeIfExists($file)
47986 {
47987 return file_exists($file) ? include $file : false;
47988 }
47989
47990 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
47991 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
47992 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
47993 exit(1);
47994 }
47995
47996 return $loader;
47997 <?php
47998
47999 /*
48000  * This file is part of Composer.
48001  *
48002  * (c) Nils Adermann <naderman@naderman.de>
48003  *     Jordi Boggiano <j.boggiano@seld.be>
48004  *
48005  * For the full copyright and license information, please view the LICENSE
48006  * file that was distributed with this source code.
48007  */
48008
48009 namespace Composer\Autoload;
48010
48011 /**
48012  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
48013  *
48014  *     $loader = new \Composer\Autoload\ClassLoader();
48015  *
48016  *     // register classes with namespaces
48017  *     $loader->add('Symfony\Component', __DIR__.'/component');
48018  *     $loader->add('Symfony',           __DIR__.'/framework');
48019  *
48020  *     // activate the autoloader
48021  *     $loader->register();
48022  *
48023  *     // to enable searching the include path (eg. for PEAR packages)
48024  *     $loader->setUseIncludePath(true);
48025  *
48026  * In this example, if you try to use a class in the Symfony\Component
48027  * namespace or one of its children (Symfony\Component\Console for instance),
48028  * the autoloader will first look for the class under the component/
48029  * directory, and it will then fallback to the framework/ directory if not
48030  * found before giving up.
48031  *
48032  * This class is loosely based on the Symfony UniversalClassLoader.
48033  *
48034  * @author Fabien Potencier <fabien@symfony.com>
48035  * @author Jordi Boggiano <j.boggiano@seld.be>
48036  * @see    http://www.php-fig.org/psr/psr-0/
48037  * @see    http://www.php-fig.org/psr/psr-4/
48038  */
48039 class ClassLoader
48040 {
48041     // PSR-4
48042     private $prefixLengthsPsr4 = array();
48043     private $prefixDirsPsr4 = array();
48044     private $fallbackDirsPsr4 = array();
48045
48046     // PSR-0
48047     private $prefixesPsr0 = array();
48048     private $fallbackDirsPsr0 = array();
48049
48050     private $useIncludePath = false;
48051     private $classMap = array();
48052     private $classMapAuthoritative = false;
48053     private $missingClasses = array();
48054     private $apcuPrefix;
48055
48056     public function getPrefixes()
48057     {
48058         if (!empty($this->prefixesPsr0)) {
48059             return call_user_func_array('array_merge', $this->prefixesPsr0);
48060         }
48061
48062         return array();
48063     }
48064
48065     public function getPrefixesPsr4()
48066     {
48067         return $this->prefixDirsPsr4;
48068     }
48069
48070     public function getFallbackDirs()
48071     {
48072         return $this->fallbackDirsPsr0;
48073     }
48074
48075     public function getFallbackDirsPsr4()
48076     {
48077         return $this->fallbackDirsPsr4;
48078     }
48079
48080     public function getClassMap()
48081     {
48082         return $this->classMap;
48083     }
48084
48085     /**
48086      * @param array $classMap Class to filename map
48087      */
48088     public function addClassMap(array $classMap)
48089     {
48090         if ($this->classMap) {
48091             $this->classMap = array_merge($this->classMap, $classMap);
48092         } else {
48093             $this->classMap = $classMap;
48094         }
48095     }
48096
48097     /**
48098      * Registers a set of PSR-0 directories for a given prefix, either
48099      * appending or prepending to the ones previously set for this prefix.
48100      *
48101      * @param string       $prefix  The prefix
48102      * @param array|string $paths   The PSR-0 root directories
48103      * @param bool         $prepend Whether to prepend the directories
48104      */
48105     public function add($prefix, $paths, $prepend = false)
48106     {
48107         if (!$prefix) {
48108             if ($prepend) {
48109                 $this->fallbackDirsPsr0 = array_merge(
48110                     (array) $paths,
48111                     $this->fallbackDirsPsr0
48112                 );
48113             } else {
48114                 $this->fallbackDirsPsr0 = array_merge(
48115                     $this->fallbackDirsPsr0,
48116                     (array) $paths
48117                 );
48118             }
48119
48120             return;
48121         }
48122
48123         $first = $prefix[0];
48124         if (!isset($this->prefixesPsr0[$first][$prefix])) {
48125             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
48126
48127             return;
48128         }
48129         if ($prepend) {
48130             $this->prefixesPsr0[$first][$prefix] = array_merge(
48131                 (array) $paths,
48132                 $this->prefixesPsr0[$first][$prefix]
48133             );
48134         } else {
48135             $this->prefixesPsr0[$first][$prefix] = array_merge(
48136                 $this->prefixesPsr0[$first][$prefix],
48137                 (array) $paths
48138             );
48139         }
48140     }
48141
48142     /**
48143      * Registers a set of PSR-4 directories for a given namespace, either
48144      * appending or prepending to the ones previously set for this namespace.
48145      *
48146      * @param string       $prefix  The prefix/namespace, with trailing '\\'
48147      * @param array|string $paths   The PSR-4 base directories
48148      * @param bool         $prepend Whether to prepend the directories
48149      *
48150      * @throws \InvalidArgumentException
48151      */
48152     public function addPsr4($prefix, $paths, $prepend = false)
48153     {
48154         if (!$prefix) {
48155             // Register directories for the root namespace.
48156             if ($prepend) {
48157                 $this->fallbackDirsPsr4 = array_merge(
48158                     (array) $paths,
48159                     $this->fallbackDirsPsr4
48160                 );
48161             } else {
48162                 $this->fallbackDirsPsr4 = array_merge(
48163                     $this->fallbackDirsPsr4,
48164                     (array) $paths
48165                 );
48166             }
48167         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
48168             // Register directories for a new namespace.
48169             $length = strlen($prefix);
48170             if ('\\' !== $prefix[$length - 1]) {
48171                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
48172             }
48173             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
48174             $this->prefixDirsPsr4[$prefix] = (array) $paths;
48175         } elseif ($prepend) {
48176             // Prepend directories for an already registered namespace.
48177             $this->prefixDirsPsr4[$prefix] = array_merge(
48178                 (array) $paths,
48179                 $this->prefixDirsPsr4[$prefix]
48180             );
48181         } else {
48182             // Append directories for an already registered namespace.
48183             $this->prefixDirsPsr4[$prefix] = array_merge(
48184                 $this->prefixDirsPsr4[$prefix],
48185                 (array) $paths
48186             );
48187         }
48188     }
48189
48190     /**
48191      * Registers a set of PSR-0 directories for a given prefix,
48192      * replacing any others previously set for this prefix.
48193      *
48194      * @param string       $prefix The prefix
48195      * @param array|string $paths  The PSR-0 base directories
48196      */
48197     public function set($prefix, $paths)
48198     {
48199         if (!$prefix) {
48200             $this->fallbackDirsPsr0 = (array) $paths;
48201         } else {
48202             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
48203         }
48204     }
48205
48206     /**
48207      * Registers a set of PSR-4 directories for a given namespace,
48208      * replacing any others previously set for this namespace.
48209      *
48210      * @param string       $prefix The prefix/namespace, with trailing '\\'
48211      * @param array|string $paths  The PSR-4 base directories
48212      *
48213      * @throws \InvalidArgumentException
48214      */
48215     public function setPsr4($prefix, $paths)
48216     {
48217         if (!$prefix) {
48218             $this->fallbackDirsPsr4 = (array) $paths;
48219         } else {
48220             $length = strlen($prefix);
48221             if ('\\' !== $prefix[$length - 1]) {
48222                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
48223             }
48224             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
48225             $this->prefixDirsPsr4[$prefix] = (array) $paths;
48226         }
48227     }
48228
48229     /**
48230      * Turns on searching the include path for class files.
48231      *
48232      * @param bool $useIncludePath
48233      */
48234     public function setUseIncludePath($useIncludePath)
48235     {
48236         $this->useIncludePath = $useIncludePath;
48237     }
48238
48239     /**
48240      * Can be used to check if the autoloader uses the include path to check
48241      * for classes.
48242      *
48243      * @return bool
48244      */
48245     public function getUseIncludePath()
48246     {
48247         return $this->useIncludePath;
48248     }
48249
48250     /**
48251      * Turns off searching the prefix and fallback directories for classes
48252      * that have not been registered with the class map.
48253      *
48254      * @param bool $classMapAuthoritative
48255      */
48256     public function setClassMapAuthoritative($classMapAuthoritative)
48257     {
48258         $this->classMapAuthoritative = $classMapAuthoritative;
48259     }
48260
48261     /**
48262      * Should class lookup fail if not found in the current class map?
48263      *
48264      * @return bool
48265      */
48266     public function isClassMapAuthoritative()
48267     {
48268         return $this->classMapAuthoritative;
48269     }
48270
48271     /**
48272      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
48273      *
48274      * @param string|null $apcuPrefix
48275      */
48276     public function setApcuPrefix($apcuPrefix)
48277     {
48278         $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
48279     }
48280
48281     /**
48282      * The APCu prefix in use, or null if APCu caching is not enabled.
48283      *
48284      * @return string|null
48285      */
48286     public function getApcuPrefix()
48287     {
48288         return $this->apcuPrefix;
48289     }
48290
48291     /**
48292      * Registers this instance as an autoloader.
48293      *
48294      * @param bool $prepend Whether to prepend the autoloader or not
48295      */
48296     public function register($prepend = false)
48297     {
48298         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
48299     }
48300
48301     /**
48302      * Unregisters this instance as an autoloader.
48303      */
48304     public function unregister()
48305     {
48306         spl_autoload_unregister(array($this, 'loadClass'));
48307     }
48308
48309     /**
48310      * Loads the given class or interface.
48311      *
48312      * @param  string    $class The name of the class
48313      * @return bool|null True if loaded, null otherwise
48314      */
48315     public function loadClass($class)
48316     {
48317         if ($file = $this->findFile($class)) {
48318             includeFile($file);
48319
48320             return true;
48321         }
48322     }
48323
48324     /**
48325      * Finds the path to the file where the class is defined.
48326      *
48327      * @param string $class The name of the class
48328      *
48329      * @return string|false The path if found, false otherwise
48330      */
48331     public function findFile($class)
48332     {
48333         // class map lookup
48334         if (isset($this->classMap[$class])) {
48335             return $this->classMap[$class];
48336         }
48337         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
48338             return false;
48339         }
48340         if (null !== $this->apcuPrefix) {
48341             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
48342             if ($hit) {
48343                 return $file;
48344             }
48345         }
48346
48347         $file = $this->findFileWithExtension($class, '.php');
48348
48349         // Search for Hack files if we are running on HHVM
48350         if (false === $file && defined('HHVM_VERSION')) {
48351             $file = $this->findFileWithExtension($class, '.hh');
48352         }
48353
48354         if (null !== $this->apcuPrefix) {
48355             apcu_add($this->apcuPrefix.$class, $file);
48356         }
48357
48358         if (false === $file) {
48359             // Remember that this class does not exist.
48360             $this->missingClasses[$class] = true;
48361         }
48362
48363         return $file;
48364     }
48365
48366     private function findFileWithExtension($class, $ext)
48367     {
48368         // PSR-4 lookup
48369         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
48370
48371         $first = $class[0];
48372         if (isset($this->prefixLengthsPsr4[$first])) {
48373             $subPath = $class;
48374             while (false !== $lastPos = strrpos($subPath, '\\')) {
48375                 $subPath = substr($subPath, 0, $lastPos);
48376                 $search = $subPath . '\\';
48377                 if (isset($this->prefixDirsPsr4[$search])) {
48378                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
48379                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
48380                         if (file_exists($file = $dir . $pathEnd)) {
48381                             return $file;
48382                         }
48383                     }
48384                 }
48385             }
48386         }
48387
48388         // PSR-4 fallback dirs
48389         foreach ($this->fallbackDirsPsr4 as $dir) {
48390             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
48391                 return $file;
48392             }
48393         }
48394
48395         // PSR-0 lookup
48396         if (false !== $pos = strrpos($class, '\\')) {
48397             // namespaced class name
48398             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
48399                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
48400         } else {
48401             // PEAR-like class name
48402             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
48403         }
48404
48405         if (isset($this->prefixesPsr0[$first])) {
48406             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
48407                 if (0 === strpos($class, $prefix)) {
48408                     foreach ($dirs as $dir) {
48409                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
48410                             return $file;
48411                         }
48412                     }
48413                 }
48414             }
48415         }
48416
48417         // PSR-0 fallback dirs
48418         foreach ($this->fallbackDirsPsr0 as $dir) {
48419             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
48420                 return $file;
48421             }
48422         }
48423
48424         // PSR-0 include paths.
48425         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
48426             return $file;
48427         }
48428
48429         return false;
48430     }
48431 }
48432
48433 /**
48434  * Scope isolated include.
48435  *
48436  * Prevents access to $this/self from included files.
48437  */
48438 function includeFile($file)
48439 {
48440     include $file;
48441 }
48442 {
48443     "$schema": "http://json-schema.org/draft-04/schema#",
48444     "description": "A representation of packages metadata.",
48445     "type": "object",
48446     "oneOf": [
48447         { "required": [ "packages" ] },
48448         { "required": [ "providers" ] },
48449         { "required": [ "provider-includes", "providers-url" ] }
48450     ],
48451     "properties": {
48452         "packages": {
48453             "type": ["object", "array"],
48454             "description": "A hashmap of package names in the form of <vendor>/<name>.",
48455             "additionalProperties": { "$ref": "#/definitions/versions" }
48456         },
48457         "providers-url": {
48458             "type": "string",
48459             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
48460         },
48461         "provider-includes": {
48462             "type": "object",
48463             "description": "A hashmap of provider listings.",
48464             "additionalProperties": { "$ref": "#/definitions/provider" }
48465         },
48466         "providers": {
48467             "type": "object",
48468             "description": "A hashmap of package names in the form of <vendor>/<name>.",
48469             "additionalProperties": { "$ref": "#/definitions/provider" }
48470         },
48471         "notify-batch": {
48472             "type": "string",
48473             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
48474         },
48475         "search": {
48476             "type": "string",
48477             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
48478         },
48479         "warning": {
48480             "type": "string",
48481             "description": "A message that will be output by Composer as a warning when this source is consulted."
48482         }
48483     },
48484     "definitions": {
48485         "versions": {
48486             "type": "object",
48487             "description": "A hashmap of versions and their metadata.",
48488             "additionalProperties": { "$ref": "#/definitions/version" }
48489         },
48490         "version": {
48491             "type": "object",
48492             "oneOf": [
48493                 { "$ref": "#/definitions/package" },
48494                 { "$ref": "#/definitions/metapackage" }
48495             ]
48496         },
48497         "package-base": {
48498             "properties": {
48499                 "name": { "type": "string" },
48500                 "type": { "type": "string" },
48501                 "version": { "type": "string" },
48502                 "version_normalized": {
48503                     "type": "string",
48504                     "description": "Normalized version, optional but can save computational time on client side."
48505                 },
48506                 "autoload": { "type": "object" },
48507                 "require": { "type": "object" },
48508                 "replace": { "type": "object" },
48509                 "conflict": { "type": "object" },
48510                 "provide": { "type": "object" },
48511                 "time": { "type": "string" }
48512             },
48513             "additionalProperties": true
48514         },
48515         "package": {
48516             "allOf": [
48517                 { "$ref": "#/definitions/package-base" },
48518                 {
48519                     "properties": {
48520                         "dist": { "type": "object" },
48521                         "source": { "type": "object" }
48522                     }
48523                 },
48524                 { "oneOf": [
48525                     { "required": [ "name", "version", "source" ] },
48526                     { "required": [ "name", "version", "dist" ] }
48527                 ] }
48528             ]
48529         },
48530         "metapackage": {
48531             "allOf": [
48532                 { "$ref": "#/definitions/package-base" },
48533                 {
48534                     "properties": {
48535                         "type": { "type": "string", "enum": [ "metapackage" ] }
48536                     },
48537                     "required": [ "name", "version", "type" ]
48538                 }
48539             ]
48540         },
48541         "provider": {
48542             "type": "object",
48543             "properties": {
48544                 "sha256": {
48545                     "type": "string",
48546                     "description": "Hash value that can be used to validate the resource."
48547                 }
48548             }
48549         }
48550     }
48551 }
48552 {
48553     "$schema": "http://json-schema.org/draft-04/schema#",
48554     "name": "Package",
48555     "type": "object",
48556     "additionalProperties": false,
48557     "required": [ "name", "description" ],
48558     "properties": {
48559         "name": {
48560             "type": "string",
48561             "description": "Package name, including 'vendor-name/' prefix."
48562         },
48563         "type": {
48564             "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.",
48565             "type": "string",
48566             "pattern": "^[a-z0-9-]+$"
48567         },
48568         "target-dir": {
48569             "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.",
48570             "type": "string"
48571         },
48572         "description": {
48573             "type": "string",
48574             "description": "Short package description."
48575         },
48576         "keywords": {
48577             "type": "array",
48578             "items": {
48579                 "type": "string",
48580                 "description": "A tag/keyword that this package relates to."
48581             }
48582         },
48583         "homepage": {
48584             "type": "string",
48585             "description": "Homepage URL for the project.",
48586             "format": "uri"
48587         },
48588         "readme": {
48589             "type": "string",
48590             "description": "Relative path to the readme document."
48591         },
48592         "version": {
48593             "type": "string",
48594             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.",
48595             "pattern": "^v?\\d+(((\\.\\d+)?\\.\\d+)?\\.\\d+)?|^dev-"
48596         },
48597         "time": {
48598             "type": "string",
48599             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
48600         },
48601         "license": {
48602             "type": ["string", "array"],
48603             "description": "License name. Or an array of license names."
48604         },
48605         "authors": {
48606             "$ref": "#/definitions/authors"
48607         },
48608         "require": {
48609             "type": "object",
48610             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
48611             "additionalProperties": {
48612                 "type": "string"
48613             }
48614         },
48615         "replace": {
48616             "type": "object",
48617             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
48618             "additionalProperties": {
48619                 "type": "string"
48620             }
48621         },
48622         "conflict": {
48623             "type": "object",
48624             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
48625             "additionalProperties": {
48626                 "type": "string"
48627             }
48628         },
48629         "provide": {
48630             "type": "object",
48631             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
48632             "additionalProperties": {
48633                 "type": "string"
48634             }
48635         },
48636         "require-dev": {
48637             "type": "object",
48638             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
48639             "additionalProperties": {
48640                 "type": "string"
48641             }
48642         },
48643         "suggest": {
48644             "type": "object",
48645             "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).",
48646             "additionalProperties": {
48647                 "type": "string"
48648             }
48649         },
48650         "config": {
48651             "type": "object",
48652             "description": "Composer options.",
48653             "properties": {
48654                 "process-timeout": {
48655                     "type": "integer",
48656                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
48657                 },
48658                 "use-include-path": {
48659                     "type": "boolean",
48660                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
48661                 },
48662                 "preferred-install": {
48663                     "type": ["string", "object"],
48664                     "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\"}."
48665                 },
48666                 "notify-on-install": {
48667                     "type": "boolean",
48668                     "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."
48669                 },
48670                 "github-protocols": {
48671                     "type": "array",
48672                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
48673                     "items": {
48674                         "type": "string"
48675                     }
48676                 },
48677                 "github-oauth": {
48678                     "type": "object",
48679                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
48680                     "additionalProperties": {
48681                         "type": "string"
48682                     }
48683                 },
48684                 "gitlab-oauth": {
48685                     "type": "object",
48686                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
48687                     "additionalProperties": {
48688                         "type": "string"
48689                     }
48690                 },
48691                 "gitlab-token": {
48692                     "type": "object",
48693                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
48694                     "additionalProperties": {
48695                         "type": "string"
48696                     }
48697                 },
48698                 "bearer": {
48699                     "type": "object",
48700                     "description": "A hash of domain name => bearer authentication token, for example {\"example.com\":\"<token>\"}.",
48701                     "additionalProperties": {
48702                         "type": "string"
48703                     }
48704                 },
48705                 "disable-tls": {
48706                     "type": "boolean",
48707                     "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."
48708                 },
48709                 "secure-http": {
48710                     "type": "boolean",
48711                     "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."
48712                 },
48713                 "cafile": {
48714                     "type": "string",
48715                     "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."
48716                 },
48717                 "capath": {
48718                     "type": "string",
48719                     "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."
48720                 },
48721                 "http-basic": {
48722                     "type": "object",
48723                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
48724                     "additionalProperties": {
48725                         "type": "object",
48726                         "required": ["username", "password"],
48727                         "properties": {
48728                             "username": {
48729                                 "type": "string",
48730                                 "description": "The username used for HTTP Basic authentication"
48731                             },
48732                             "password": {
48733                                 "type": "string",
48734                                 "description": "The password used for HTTP Basic authentication"
48735                             }
48736                         }
48737                     }
48738                 },
48739                 "store-auths": {
48740                     "type": ["string", "boolean"],
48741                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
48742                 },
48743                 "platform": {
48744                     "type": "object",
48745                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
48746                     "additionalProperties": {
48747                         "type": "string"
48748                     }
48749                 },
48750                 "vendor-dir": {
48751                     "type": "string",
48752                     "description": "The location where all packages are installed, defaults to \"vendor\"."
48753                 },
48754                 "bin-dir": {
48755                     "type": "string",
48756                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
48757                 },
48758                 "data-dir": {
48759                     "type": "string",
48760                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
48761                 },
48762                 "cache-dir": {
48763                     "type": "string",
48764                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
48765                 },
48766                 "cache-files-dir": {
48767                     "type": "string",
48768                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
48769                 },
48770                 "cache-repo-dir": {
48771                     "type": "string",
48772                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
48773                 },
48774                 "cache-vcs-dir": {
48775                     "type": "string",
48776                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
48777                 },
48778                 "cache-ttl": {
48779                     "type": "integer",
48780                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
48781                 },
48782                 "cache-files-ttl": {
48783                     "type": "integer",
48784                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
48785                 },
48786                 "cache-files-maxsize": {
48787                     "type": ["string", "integer"],
48788                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
48789                 },
48790                 "bin-compat": {
48791                     "enum": ["auto", "full"],
48792                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
48793                 },
48794                 "discard-changes": {
48795                     "type": ["string", "boolean"],
48796                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
48797                 },
48798                 "autoloader-suffix": {
48799                     "type": "string",
48800                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
48801                 },
48802                 "optimize-autoloader": {
48803                     "type": "boolean",
48804                     "description": "Always optimize when dumping the autoloader."
48805                 },
48806                 "prepend-autoloader": {
48807                     "type": "boolean",
48808                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
48809                 },
48810                 "classmap-authoritative": {
48811                     "type": "boolean",
48812                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
48813                 },
48814                 "apcu-autoloader": {
48815                     "type": "boolean",
48816                     "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."
48817                 },
48818                 "github-domains": {
48819                     "type": "array",
48820                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
48821                     "items": {
48822                         "type": "string"
48823                     }
48824                 },
48825                 "github-expose-hostname": {
48826                     "type": "boolean",
48827                     "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."
48828                 },
48829                 "gitlab-domains": {
48830                     "type": "array",
48831                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
48832                     "items": {
48833                         "type": "string"
48834                     }
48835                 },
48836                 "use-github-api": {
48837                     "type": "boolean",
48838                     "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."
48839                 },
48840                 "archive-format": {
48841                     "type": "string",
48842                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
48843                 },
48844                 "archive-dir": {
48845                     "type": "string",
48846                     "description": "The default archive path when not provided on cli, defaults to \".\"."
48847                 },
48848                 "htaccess-protect": {
48849                     "type": "boolean",
48850                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
48851                 },
48852                 "sort-packages": {
48853                     "type": "boolean",
48854                     "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency."
48855                 },
48856                 "lock": {
48857                     "type": "boolean",
48858                     "description": "Defaults to true. If set to false, Composer will not create a composer.lock file."
48859                 }
48860             }
48861         },
48862         "extra": {
48863             "type": ["object", "array"],
48864             "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.",
48865             "additionalProperties": true
48866         },
48867         "autoload": {
48868             "$ref": "#/definitions/autoload"
48869         },
48870         "autoload-dev": {
48871             "type": "object",
48872             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
48873             "properties": {
48874                 "psr-0": {
48875                     "type": "object",
48876                     "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.",
48877                     "additionalProperties": {
48878                         "type": ["string", "array"],
48879                         "items": {
48880                             "type": "string"
48881                         }
48882                     }
48883                 },
48884                 "psr-4": {
48885                     "type": "object",
48886                     "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.",
48887                     "additionalProperties": {
48888                         "type": ["string", "array"],
48889                         "items": {
48890                             "type": "string"
48891                         }
48892                     }
48893                 },
48894                 "classmap": {
48895                     "type": "array",
48896                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
48897                 },
48898                 "files": {
48899                     "type": "array",
48900                     "description": "This is an array of files that are always required on every request."
48901                 }
48902             }
48903         },
48904         "archive": {
48905             "type": ["object"],
48906             "description": "Options for creating package archives for distribution.",
48907             "properties": {
48908                 "exclude": {
48909                     "type": "array",
48910                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
48911                 }
48912             }
48913         },
48914         "repositories": {
48915             "type": ["object", "array"],
48916             "description": "A set of additional repositories where packages can be found.",
48917             "additionalProperties": {
48918                 "oneOf": [
48919                     { "$ref": "#/definitions/repository" },
48920                     { "type": "boolean", "enum": [false] }
48921                 ]
48922             },
48923             "items": {
48924                 "oneOf": [
48925                     { "$ref": "#/definitions/repository" },
48926                     {
48927                         "type": "object",
48928                         "additionalProperties": { "type": "boolean", "enum": [false] },
48929                         "minProperties": 1,
48930                         "maxProperties": 1
48931                     }
48932                 ]
48933             }
48934         },
48935         "minimum-stability": {
48936             "type": ["string"],
48937             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
48938             "pattern": "^dev|alpha|beta|rc|RC|stable$"
48939         },
48940         "prefer-stable": {
48941             "type": ["boolean"],
48942             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
48943         },
48944         "bin": {
48945             "type": ["string", "array"],
48946             "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
48947             "items": {
48948                 "type": "string"
48949             }
48950         },
48951         "include-path": {
48952             "type": ["array"],
48953             "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.",
48954             "items": {
48955                 "type": "string"
48956             }
48957         },
48958         "scripts": {
48959             "type": ["object"],
48960             "description": "Script listeners that will be executed before/after some events.",
48961             "properties": {
48962                 "pre-install-cmd": {
48963                     "type": ["array", "string"],
48964                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
48965                 },
48966                 "post-install-cmd": {
48967                     "type": ["array", "string"],
48968                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
48969                 },
48970                 "pre-update-cmd": {
48971                     "type": ["array", "string"],
48972                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
48973                 },
48974                 "post-update-cmd": {
48975                     "type": ["array", "string"],
48976                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
48977                 },
48978                 "pre-status-cmd": {
48979                     "type": ["array", "string"],
48980                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
48981                 },
48982                 "post-status-cmd": {
48983                     "type": ["array", "string"],
48984                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
48985                 },
48986                 "pre-package-install": {
48987                     "type": ["array", "string"],
48988                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
48989                 },
48990                 "post-package-install": {
48991                     "type": ["array", "string"],
48992                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
48993                 },
48994                 "pre-package-update": {
48995                     "type": ["array", "string"],
48996                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
48997                 },
48998                 "post-package-update": {
48999                     "type": ["array", "string"],
49000                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
49001                 },
49002                 "pre-package-uninstall": {
49003                     "type": ["array", "string"],
49004                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
49005                 },
49006                 "post-package-uninstall": {
49007                     "type": ["array", "string"],
49008                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
49009                 },
49010                 "pre-autoload-dump": {
49011                     "type": ["array", "string"],
49012                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
49013                 },
49014                 "post-autoload-dump": {
49015                     "type": ["array", "string"],
49016                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
49017                 },
49018                 "post-root-package-install": {
49019                     "type": ["array", "string"],
49020                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
49021                 },
49022                 "post-create-project-cmd": {
49023                     "type": ["array", "string"],
49024                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
49025                 }
49026             }
49027         },
49028         "scripts-descriptions": {
49029             "type": ["object"],
49030             "description": "Descriptions for custom commands, shown in console help.",
49031             "additionalProperties": {
49032                 "type": "string"
49033             }
49034         },
49035         "support": {
49036             "type": "object",
49037             "properties": {
49038                 "email": {
49039                     "type": "string",
49040                     "description": "Email address for support.",
49041                     "format": "email"
49042                 },
49043                 "issues": {
49044                     "type": "string",
49045                     "description": "URL to the issue tracker.",
49046                     "format": "uri"
49047                 },
49048                 "forum": {
49049                     "type": "string",
49050                     "description": "URL to the forum.",
49051                     "format": "uri"
49052                 },
49053                 "wiki": {
49054                     "type": "string",
49055                     "description": "URL to the wiki.",
49056                     "format": "uri"
49057                 },
49058                 "irc": {
49059                     "type": "string",
49060                     "description": "IRC channel for support, as irc://server/channel.",
49061                     "format": "uri"
49062                 },
49063                 "chat": {
49064                     "type": "string",
49065                     "description": "URL to the support chat.",
49066                     "format": "uri"
49067                 },
49068                 "source": {
49069                     "type": "string",
49070                     "description": "URL to browse or download the sources.",
49071                     "format": "uri"
49072                 },
49073                 "docs": {
49074                     "type": "string",
49075                     "description": "URL to the documentation.",
49076                     "format": "uri"
49077                 },
49078                 "rss": {
49079                     "type": "string",
49080                     "description": "URL to the RSS feed.",
49081                     "format": "uri"
49082                 }
49083             }
49084         },
49085         "funding": {
49086             "type": "array",
49087             "description": "A list of options to fund the development and maintenance of the package.",
49088             "items": {
49089                 "type": "object",
49090                 "properties": {
49091                     "type": {
49092                         "type": "string",
49093                         "description": "Type of funding or platform through which funding is possible."
49094                     },
49095                     "url": {
49096                         "type": "string",
49097                         "description": "URL to a website with details on funding and a way to fund the package.",
49098                         "format": "uri"
49099                     }
49100                 }
49101             }
49102         },
49103         "non-feature-branches": {
49104             "type": ["array"],
49105             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
49106             "items": {
49107                 "type": "string"
49108             }
49109         },
49110         "abandoned": {
49111             "type": ["boolean", "string"],
49112             "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."
49113         },
49114         "_comment": {
49115             "type": ["array", "string"],
49116             "description": "A key to store comments in"
49117         }
49118     },
49119     "definitions": {
49120         "authors": {
49121             "type": "array",
49122             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
49123             "items": {
49124                 "type": "object",
49125                 "additionalProperties": false,
49126                 "required": [ "name"],
49127                 "properties": {
49128                     "name": {
49129                         "type": "string",
49130                         "description": "Full name of the author."
49131                     },
49132                     "email": {
49133                         "type": "string",
49134                         "description": "Email address of the author.",
49135                         "format": "email"
49136                     },
49137                     "homepage": {
49138                         "type": "string",
49139                         "description": "Homepage URL for the author.",
49140                         "format": "uri"
49141                     },
49142                     "role": {
49143                         "type": "string",
49144                         "description": "Author's role in the project."
49145                     }
49146                 }
49147             }
49148         },
49149         "autoload": {
49150             "type": "object",
49151             "description": "Description of how the package can be autoloaded.",
49152             "properties": {
49153                 "psr-0": {
49154                     "type": "object",
49155                     "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.",
49156                     "additionalProperties": {
49157                         "type": ["string", "array"],
49158                         "items": {
49159                             "type": "string"
49160                         }
49161                     }
49162                 },
49163                 "psr-4": {
49164                     "type": "object",
49165                     "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.",
49166                     "additionalProperties": {
49167                         "type": ["string", "array"],
49168                         "items": {
49169                             "type": "string"
49170                         }
49171                     }
49172                 },
49173                 "classmap": {
49174                     "type": "array",
49175                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
49176                 },
49177                 "files": {
49178                     "type": "array",
49179                     "description": "This is an array of files that are always required on every request."
49180                 },
49181                 "exclude-from-classmap": {
49182                     "type": "array",
49183                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
49184                 }
49185             }
49186         },
49187         "repository": {
49188             "type": "object",
49189             "oneOf": [
49190                 { "$ref": "#/definitions/composer-repository" },
49191                 { "$ref": "#/definitions/vcs-repository" },
49192                 { "$ref": "#/definitions/path-repository" },
49193                 { "$ref": "#/definitions/artifact-repository" },
49194                 { "$ref": "#/definitions/pear-repository" },
49195                 { "$ref": "#/definitions/package-repository" }
49196             ]
49197         },
49198         "composer-repository": {
49199             "type": "object",
49200             "required": ["type", "url"],
49201             "properties": {
49202                 "type": { "type": "string", "enum": ["composer"] },
49203                 "url": { "type": "string" },
49204                 "options": {
49205                     "type": "object",
49206                     "additionalProperties": true
49207                 },
49208                 "allow_ssl_downgrade": { "type": "boolean" },
49209                 "force-lazy-providers": { "type": "boolean" }
49210             }
49211         },
49212         "vcs-repository": {
49213             "type": "object",
49214             "required": ["type", "url"],
49215             "properties": {
49216                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
49217                 "url": { "type": "string" },
49218                 "no-api": { "type": "boolean" },
49219                 "secure-http": { "type": "boolean" },
49220                 "svn-cache-credentials": { "type": "boolean" },
49221                 "trunk-path": { "type": ["string", "boolean"] },
49222                 "branches-path": { "type": ["string", "boolean"] },
49223                 "tags-path": { "type": ["string", "boolean"] },
49224                 "package-path": { "type": "string" },
49225                 "depot": { "type": "string" },
49226                 "branch": { "type": "string" },
49227                 "unique_perforce_client_name": { "type": "string" },
49228                 "p4user": { "type": "string" },
49229                 "p4password": { "type": "string" }
49230             }
49231         },
49232         "path-repository": {
49233             "type": "object",
49234             "required": ["type", "url"],
49235             "properties": {
49236                 "type": { "type": "string", "enum": ["path"] },
49237                 "url": { "type": "string" },
49238                 "options": {
49239                     "type": "object",
49240                     "properties": {
49241                         "symlink": { "type": ["boolean", "null"] }
49242                     },
49243                     "additionalProperties": true
49244                 }
49245             }
49246         },
49247         "artifact-repository": {
49248             "type": "object",
49249             "required": ["type", "url"],
49250             "properties": {
49251                 "type": { "type": "string", "enum": ["artifact"] },
49252                 "url": { "type": "string" }
49253             }
49254         },
49255         "pear-repository": {
49256             "type": "object",
49257             "required": ["type", "url"],
49258             "properties": {
49259                 "type": { "type": "string", "enum": ["pear"] },
49260                 "url": { "type": "string" },
49261                 "vendor-alias": { "type": "string" }
49262             }
49263         },
49264         "package-repository": {
49265             "type": "object",
49266             "required": ["type", "package"],
49267             "properties": {
49268                 "type": { "type": "string", "enum": ["package"] },
49269                 "package": {
49270                     "oneOf": [
49271                         { "$ref": "#/definitions/inline-package" },
49272                         {
49273                             "type": "array",
49274                             "items": { "$ref": "#/definitions/inline-package" }
49275                         }
49276                     ]
49277                 }
49278             }
49279         },
49280         "inline-package": {
49281             "type": "object",
49282             "required": ["name", "version"],
49283             "properties": {
49284                 "name": {
49285                     "type": "string",
49286                     "description": "Package name, including 'vendor-name/' prefix."
49287                 },
49288                 "type": {
49289                     "type": "string"
49290                 },
49291                 "target-dir": {
49292                     "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.",
49293                     "type": "string"
49294                 },
49295                 "description": {
49296                     "type": "string"
49297                 },
49298                 "keywords": {
49299                     "type": "array",
49300                     "items": {
49301                         "type": "string"
49302                     }
49303                 },
49304                 "homepage": {
49305                     "type": "string",
49306                     "format": "uri"
49307                 },
49308                 "version": {
49309                     "type": "string"
49310                 },
49311                 "time": {
49312                     "type": "string"
49313                 },
49314                 "license": {
49315                     "type": [
49316                         "string",
49317                         "array"
49318                     ]
49319                 },
49320                 "authors": {
49321                     "$ref": "#/definitions/authors"
49322                 },
49323                 "require": {
49324                     "type": "object",
49325                     "additionalProperties": {
49326                         "type": "string"
49327                     }
49328                 },
49329                 "replace": {
49330                     "type": "object",
49331                     "additionalProperties": {
49332                         "type": "string"
49333                     }
49334                 },
49335                 "conflict": {
49336                     "type": "object",
49337                     "additionalProperties": {
49338                         "type": "string"
49339                     }
49340                 },
49341                 "provide": {
49342                     "type": "object",
49343                     "additionalProperties": {
49344                         "type": "string"
49345                     }
49346                 },
49347                 "require-dev": {
49348                     "type": "object",
49349                     "additionalProperties": {
49350                         "type": "string"
49351                     }
49352                 },
49353                 "suggest": {
49354                     "type": "object",
49355                     "additionalProperties": {
49356                         "type": "string"
49357                     }
49358                 },
49359                 "extra": {
49360                     "type": ["object", "array"],
49361                     "additionalProperties": true
49362                 },
49363                 "autoload": {
49364                     "$ref": "#/definitions/autoload"
49365                 },
49366                 "archive": {
49367                     "type": ["object"],
49368                     "properties": {
49369                         "exclude": {
49370                             "type": "array"
49371                         }
49372                     }
49373                 },
49374                 "bin": {
49375                     "type": ["string", "array"],
49376                     "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).",
49377                     "items": {
49378                         "type": "string"
49379                     }
49380                 },
49381                 "include-path": {
49382                     "type": ["array"],
49383                     "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.",
49384                     "items": {
49385                         "type": "string"
49386                     }
49387                 },
49388                 "source": {
49389                     "type": "object",
49390                     "required": ["type", "url", "reference"],
49391                     "properties": {
49392                         "type": {
49393                             "type": "string"
49394                         },
49395                         "url": {
49396                             "type": "string"
49397                         },
49398                         "reference": {
49399                             "type": "string"
49400                         },
49401                         "mirrors": {
49402                             "type": "array"
49403                         }
49404                     }
49405                 },
49406                 "dist": {
49407                     "type": "object",
49408                     "required": ["type", "url"],
49409                     "properties": {
49410                         "type": {
49411                             "type": "string"
49412                         },
49413                         "url": {
49414                             "type": "string"
49415                         },
49416                         "reference": {
49417                             "type": "string"
49418                         },
49419                         "shasum": {
49420                             "type": "string"
49421                         },
49422                         "mirrors": {
49423                             "type": "array"
49424                         }
49425                     }
49426                 }
49427             },
49428             "additionalProperties": true
49429         }
49430     }
49431 }
49432 {
49433     "389-exception": [
49434         "389 Directory Server Exception"
49435     ],
49436     "Autoconf-exception-2.0": [
49437         "Autoconf exception 2.0"
49438     ],
49439     "Autoconf-exception-3.0": [
49440         "Autoconf exception 3.0"
49441     ],
49442     "Bison-exception-2.2": [
49443         "Bison exception 2.2"
49444     ],
49445     "Bootloader-exception": [
49446         "Bootloader Distribution Exception"
49447     ],
49448     "Classpath-exception-2.0": [
49449         "Classpath exception 2.0"
49450     ],
49451     "CLISP-exception-2.0": [
49452         "CLISP exception 2.0"
49453     ],
49454     "DigiRule-FOSS-exception": [
49455         "DigiRule FOSS License Exception"
49456     ],
49457     "eCos-exception-2.0": [
49458         "eCos exception 2.0"
49459     ],
49460     "Fawkes-Runtime-exception": [
49461         "Fawkes Runtime Exception"
49462     ],
49463     "FLTK-exception": [
49464         "FLTK exception"
49465     ],
49466     "Font-exception-2.0": [
49467         "Font exception 2.0"
49468     ],
49469     "freertos-exception-2.0": [
49470         "FreeRTOS Exception 2.0"
49471     ],
49472     "GCC-exception-2.0": [
49473         "GCC Runtime Library exception 2.0"
49474     ],
49475     "GCC-exception-3.1": [
49476         "GCC Runtime Library exception 3.1"
49477     ],
49478     "gnu-javamail-exception": [
49479         "GNU JavaMail exception"
49480     ],
49481     "GPL-3.0-linking-exception": [
49482         "GPL-3.0 Linking Exception"
49483     ],
49484     "GPL-3.0-linking-source-exception": [
49485         "GPL-3.0 Linking Exception (with Corresponding Source)"
49486     ],
49487     "GPL-CC-1.0": [
49488         "GPL Cooperation Commitment 1.0"
49489     ],
49490     "i2p-gpl-java-exception": [
49491         "i2p GPL+Java Exception"
49492     ],
49493     "Libtool-exception": [
49494         "Libtool Exception"
49495     ],
49496     "Linux-syscall-note": [
49497         "Linux Syscall Note"
49498     ],
49499     "LLVM-exception": [
49500         "LLVM Exception"
49501     ],
49502     "LZMA-exception": [
49503         "LZMA exception"
49504     ],
49505     "mif-exception": [
49506         "Macros and Inline Functions Exception"
49507     ],
49508     "Nokia-Qt-exception-1.1": [
49509         "Nokia Qt LGPL exception 1.1"
49510     ],
49511     "OCaml-LGPL-linking-exception": [
49512         "OCaml LGPL Linking Exception"
49513     ],
49514     "OCCT-exception-1.0": [
49515         "Open CASCADE Exception 1.0"
49516     ],
49517     "OpenJDK-assembly-exception-1.0": [
49518         "OpenJDK Assembly exception 1.0"
49519     ],
49520     "openvpn-openssl-exception": [
49521         "OpenVPN OpenSSL Exception"
49522     ],
49523     "PS-or-PDF-font-exception-20170817": [
49524         "PS/PDF font exception (2017-08-17)"
49525     ],
49526     "Qt-GPL-exception-1.0": [
49527         "Qt GPL exception 1.0"
49528     ],
49529     "Qt-LGPL-exception-1.1": [
49530         "Qt LGPL exception 1.1"
49531     ],
49532     "Qwt-exception-1.0": [
49533         "Qwt exception 1.0"
49534     ],
49535     "Swift-exception": [
49536         "Swift Exception"
49537     ],
49538     "u-boot-exception-2.0": [
49539         "U-Boot exception 2.0"
49540     ],
49541     "Universal-FOSS-exception-1.0": [
49542         "Universal FOSS Exception, Version 1.0"
49543     ],
49544     "WxWindows-exception-3.1": [
49545         "WxWindows Library Exception 3.1"
49546     ]
49547 }{
49548     "0BSD": [
49549         "BSD Zero Clause License",
49550         true,
49551         false
49552     ],
49553     "AAL": [
49554         "Attribution Assurance License",
49555         true,
49556         false
49557     ],
49558     "Abstyles": [
49559         "Abstyles License",
49560         false,
49561         false
49562     ],
49563     "Adobe-2006": [
49564         "Adobe Systems Incorporated Source Code License Agreement",
49565         false,
49566         false
49567     ],
49568     "Adobe-Glyph": [
49569         "Adobe Glyph List License",
49570         false,
49571         false
49572     ],
49573     "ADSL": [
49574         "Amazon Digital Services License",
49575         false,
49576         false
49577     ],
49578     "AFL-1.1": [
49579         "Academic Free License v1.1",
49580         true,
49581         false
49582     ],
49583     "AFL-1.2": [
49584         "Academic Free License v1.2",
49585         true,
49586         false
49587     ],
49588     "AFL-2.0": [
49589         "Academic Free License v2.0",
49590         true,
49591         false
49592     ],
49593     "AFL-2.1": [
49594         "Academic Free License v2.1",
49595         true,
49596         false
49597     ],
49598     "AFL-3.0": [
49599         "Academic Free License v3.0",
49600         true,
49601         false
49602     ],
49603     "Afmparse": [
49604         "Afmparse License",
49605         false,
49606         false
49607     ],
49608     "AGPL-1.0": [
49609         "Affero General Public License v1.0",
49610         false,
49611         true
49612     ],
49613     "AGPL-1.0-only": [
49614         "Affero General Public License v1.0 only",
49615         false,
49616         false
49617     ],
49618     "AGPL-1.0-or-later": [
49619         "Affero General Public License v1.0 or later",
49620         false,
49621         false
49622     ],
49623     "AGPL-3.0": [
49624         "GNU Affero General Public License v3.0",
49625         true,
49626         true
49627     ],
49628     "AGPL-3.0-only": [
49629         "GNU Affero General Public License v3.0 only",
49630         true,
49631         false
49632     ],
49633     "AGPL-3.0-or-later": [
49634         "GNU Affero General Public License v3.0 or later",
49635         true,
49636         false
49637     ],
49638     "Aladdin": [
49639         "Aladdin Free Public License",
49640         false,
49641         false
49642     ],
49643     "AMDPLPA": [
49644         "AMD's plpa_map.c License",
49645         false,
49646         false
49647     ],
49648     "AML": [
49649         "Apple MIT License",
49650         false,
49651         false
49652     ],
49653     "AMPAS": [
49654         "Academy of Motion Picture Arts and Sciences BSD",
49655         false,
49656         false
49657     ],
49658     "ANTLR-PD": [
49659         "ANTLR Software Rights Notice",
49660         false,
49661         false
49662     ],
49663     "Apache-1.0": [
49664         "Apache License 1.0",
49665         false,
49666         false
49667     ],
49668     "Apache-1.1": [
49669         "Apache License 1.1",
49670         true,
49671         false
49672     ],
49673     "Apache-2.0": [
49674         "Apache License 2.0",
49675         true,
49676         false
49677     ],
49678     "APAFML": [
49679         "Adobe Postscript AFM License",
49680         false,
49681         false
49682     ],
49683     "APL-1.0": [
49684         "Adaptive Public License 1.0",
49685         true,
49686         false
49687     ],
49688     "APSL-1.0": [
49689         "Apple Public Source License 1.0",
49690         true,
49691         false
49692     ],
49693     "APSL-1.1": [
49694         "Apple Public Source License 1.1",
49695         true,
49696         false
49697     ],
49698     "APSL-1.2": [
49699         "Apple Public Source License 1.2",
49700         true,
49701         false
49702     ],
49703     "APSL-2.0": [
49704         "Apple Public Source License 2.0",
49705         true,
49706         false
49707     ],
49708     "Artistic-1.0": [
49709         "Artistic License 1.0",
49710         true,
49711         false
49712     ],
49713     "Artistic-1.0-cl8": [
49714         "Artistic License 1.0 w/clause 8",
49715         true,
49716         false
49717     ],
49718     "Artistic-1.0-Perl": [
49719         "Artistic License 1.0 (Perl)",
49720         true,
49721         false
49722     ],
49723     "Artistic-2.0": [
49724         "Artistic License 2.0",
49725         true,
49726         false
49727     ],
49728     "Bahyph": [
49729         "Bahyph License",
49730         false,
49731         false
49732     ],
49733     "Barr": [
49734         "Barr License",
49735         false,
49736         false
49737     ],
49738     "Beerware": [
49739         "Beerware License",
49740         false,
49741         false
49742     ],
49743     "BitTorrent-1.0": [
49744         "BitTorrent Open Source License v1.0",
49745         false,
49746         false
49747     ],
49748     "BitTorrent-1.1": [
49749         "BitTorrent Open Source License v1.1",
49750         false,
49751         false
49752     ],
49753     "blessing": [
49754         "SQLite Blessing",
49755         false,
49756         false
49757     ],
49758     "BlueOak-1.0.0": [
49759         "Blue Oak Model License 1.0.0",
49760         false,
49761         false
49762     ],
49763     "Borceux": [
49764         "Borceux license",
49765         false,
49766         false
49767     ],
49768     "BSD-1-Clause": [
49769         "BSD 1-Clause License",
49770         false,
49771         false
49772     ],
49773     "BSD-2-Clause": [
49774         "BSD 2-Clause \"Simplified\" License",
49775         true,
49776         false
49777     ],
49778     "BSD-2-Clause-FreeBSD": [
49779         "BSD 2-Clause FreeBSD License",
49780         false,
49781         false
49782     ],
49783     "BSD-2-Clause-NetBSD": [
49784         "BSD 2-Clause NetBSD License",
49785         false,
49786         false
49787     ],
49788     "BSD-2-Clause-Patent": [
49789         "BSD-2-Clause Plus Patent License",
49790         true,
49791         false
49792     ],
49793     "BSD-3-Clause": [
49794         "BSD 3-Clause \"New\" or \"Revised\" License",
49795         true,
49796         false
49797     ],
49798     "BSD-3-Clause-Attribution": [
49799         "BSD with attribution",
49800         false,
49801         false
49802     ],
49803     "BSD-3-Clause-Clear": [
49804         "BSD 3-Clause Clear License",
49805         false,
49806         false
49807     ],
49808     "BSD-3-Clause-LBNL": [
49809         "Lawrence Berkeley National Labs BSD variant license",
49810         true,
49811         false
49812     ],
49813     "BSD-3-Clause-No-Nuclear-License": [
49814         "BSD 3-Clause No Nuclear License",
49815         false,
49816         false
49817     ],
49818     "BSD-3-Clause-No-Nuclear-License-2014": [
49819         "BSD 3-Clause No Nuclear License 2014",
49820         false,
49821         false
49822     ],
49823     "BSD-3-Clause-No-Nuclear-Warranty": [
49824         "BSD 3-Clause No Nuclear Warranty",
49825         false,
49826         false
49827     ],
49828     "BSD-3-Clause-Open-MPI": [
49829         "BSD 3-Clause Open MPI variant",
49830         false,
49831         false
49832     ],
49833     "BSD-4-Clause": [
49834         "BSD 4-Clause \"Original\" or \"Old\" License",
49835         false,
49836         false
49837     ],
49838     "BSD-4-Clause-UC": [
49839         "BSD-4-Clause (University of California-Specific)",
49840         false,
49841         false
49842     ],
49843     "BSD-Protection": [
49844         "BSD Protection License",
49845         false,
49846         false
49847     ],
49848     "BSD-Source-Code": [
49849         "BSD Source Code Attribution",
49850         false,
49851         false
49852     ],
49853     "BSL-1.0": [
49854         "Boost Software License 1.0",
49855         true,
49856         false
49857     ],
49858     "bzip2-1.0.5": [
49859         "bzip2 and libbzip2 License v1.0.5",
49860         false,
49861         false
49862     ],
49863     "bzip2-1.0.6": [
49864         "bzip2 and libbzip2 License v1.0.6",
49865         false,
49866         false
49867     ],
49868     "Caldera": [
49869         "Caldera License",
49870         false,
49871         false
49872     ],
49873     "CATOSL-1.1": [
49874         "Computer Associates Trusted Open Source License 1.1",
49875         true,
49876         false
49877     ],
49878     "CC-BY-1.0": [
49879         "Creative Commons Attribution 1.0 Generic",
49880         false,
49881         false
49882     ],
49883     "CC-BY-2.0": [
49884         "Creative Commons Attribution 2.0 Generic",
49885         false,
49886         false
49887     ],
49888     "CC-BY-2.5": [
49889         "Creative Commons Attribution 2.5 Generic",
49890         false,
49891         false
49892     ],
49893     "CC-BY-3.0": [
49894         "Creative Commons Attribution 3.0 Unported",
49895         false,
49896         false
49897     ],
49898     "CC-BY-4.0": [
49899         "Creative Commons Attribution 4.0 International",
49900         false,
49901         false
49902     ],
49903     "CC-BY-NC-1.0": [
49904         "Creative Commons Attribution Non Commercial 1.0 Generic",
49905         false,
49906         false
49907     ],
49908     "CC-BY-NC-2.0": [
49909         "Creative Commons Attribution Non Commercial 2.0 Generic",
49910         false,
49911         false
49912     ],
49913     "CC-BY-NC-2.5": [
49914         "Creative Commons Attribution Non Commercial 2.5 Generic",
49915         false,
49916         false
49917     ],
49918     "CC-BY-NC-3.0": [
49919         "Creative Commons Attribution Non Commercial 3.0 Unported",
49920         false,
49921         false
49922     ],
49923     "CC-BY-NC-4.0": [
49924         "Creative Commons Attribution Non Commercial 4.0 International",
49925         false,
49926         false
49927     ],
49928     "CC-BY-NC-ND-1.0": [
49929         "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",
49930         false,
49931         false
49932     ],
49933     "CC-BY-NC-ND-2.0": [
49934         "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",
49935         false,
49936         false
49937     ],
49938     "CC-BY-NC-ND-2.5": [
49939         "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",
49940         false,
49941         false
49942     ],
49943     "CC-BY-NC-ND-3.0": [
49944         "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",
49945         false,
49946         false
49947     ],
49948     "CC-BY-NC-ND-4.0": [
49949         "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",
49950         false,
49951         false
49952     ],
49953     "CC-BY-NC-SA-1.0": [
49954         "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",
49955         false,
49956         false
49957     ],
49958     "CC-BY-NC-SA-2.0": [
49959         "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",
49960         false,
49961         false
49962     ],
49963     "CC-BY-NC-SA-2.5": [
49964         "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",
49965         false,
49966         false
49967     ],
49968     "CC-BY-NC-SA-3.0": [
49969         "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",
49970         false,
49971         false
49972     ],
49973     "CC-BY-NC-SA-4.0": [
49974         "Creative Commons Attribution Non Commercial Share Alike 4.0 International",
49975         false,
49976         false
49977     ],
49978     "CC-BY-ND-1.0": [
49979         "Creative Commons Attribution No Derivatives 1.0 Generic",
49980         false,
49981         false
49982     ],
49983     "CC-BY-ND-2.0": [
49984         "Creative Commons Attribution No Derivatives 2.0 Generic",
49985         false,
49986         false
49987     ],
49988     "CC-BY-ND-2.5": [
49989         "Creative Commons Attribution No Derivatives 2.5 Generic",
49990         false,
49991         false
49992     ],
49993     "CC-BY-ND-3.0": [
49994         "Creative Commons Attribution No Derivatives 3.0 Unported",
49995         false,
49996         false
49997     ],
49998     "CC-BY-ND-4.0": [
49999         "Creative Commons Attribution No Derivatives 4.0 International",
50000         false,
50001         false
50002     ],
50003     "CC-BY-SA-1.0": [
50004         "Creative Commons Attribution Share Alike 1.0 Generic",
50005         false,
50006         false
50007     ],
50008     "CC-BY-SA-2.0": [
50009         "Creative Commons Attribution Share Alike 2.0 Generic",
50010         false,
50011         false
50012     ],
50013     "CC-BY-SA-2.5": [
50014         "Creative Commons Attribution Share Alike 2.5 Generic",
50015         false,
50016         false
50017     ],
50018     "CC-BY-SA-3.0": [
50019         "Creative Commons Attribution Share Alike 3.0 Unported",
50020         false,
50021         false
50022     ],
50023     "CC-BY-SA-4.0": [
50024         "Creative Commons Attribution Share Alike 4.0 International",
50025         false,
50026         false
50027     ],
50028     "CC-PDDC": [
50029         "Creative Commons Public Domain Dedication and Certification",
50030         false,
50031         false
50032     ],
50033     "CC0-1.0": [
50034         "Creative Commons Zero v1.0 Universal",
50035         false,
50036         false
50037     ],
50038     "CDDL-1.0": [
50039         "Common Development and Distribution License 1.0",
50040         true,
50041         false
50042     ],
50043     "CDDL-1.1": [
50044         "Common Development and Distribution License 1.1",
50045         false,
50046         false
50047     ],
50048     "CDLA-Permissive-1.0": [
50049         "Community Data License Agreement Permissive 1.0",
50050         false,
50051         false
50052     ],
50053     "CDLA-Sharing-1.0": [
50054         "Community Data License Agreement Sharing 1.0",
50055         false,
50056         false
50057     ],
50058     "CECILL-1.0": [
50059         "CeCILL Free Software License Agreement v1.0",
50060         false,
50061         false
50062     ],
50063     "CECILL-1.1": [
50064         "CeCILL Free Software License Agreement v1.1",
50065         false,
50066         false
50067     ],
50068     "CECILL-2.0": [
50069         "CeCILL Free Software License Agreement v2.0",
50070         false,
50071         false
50072     ],
50073     "CECILL-2.1": [
50074         "CeCILL Free Software License Agreement v2.1",
50075         true,
50076         false
50077     ],
50078     "CECILL-B": [
50079         "CeCILL-B Free Software License Agreement",
50080         false,
50081         false
50082     ],
50083     "CECILL-C": [
50084         "CeCILL-C Free Software License Agreement",
50085         false,
50086         false
50087     ],
50088     "CERN-OHL-1.1": [
50089         "CERN Open Hardware Licence v1.1",
50090         false,
50091         false
50092     ],
50093     "CERN-OHL-1.2": [
50094         "CERN Open Hardware Licence v1.2",
50095         false,
50096         false
50097     ],
50098     "ClArtistic": [
50099         "Clarified Artistic License",
50100         false,
50101         false
50102     ],
50103     "CNRI-Jython": [
50104         "CNRI Jython License",
50105         false,
50106         false
50107     ],
50108     "CNRI-Python": [
50109         "CNRI Python License",
50110         true,
50111         false
50112     ],
50113     "CNRI-Python-GPL-Compatible": [
50114         "CNRI Python Open Source GPL Compatible License Agreement",
50115         false,
50116         false
50117     ],
50118     "Condor-1.1": [
50119         "Condor Public License v1.1",
50120         false,
50121         false
50122     ],
50123     "copyleft-next-0.3.0": [
50124         "copyleft-next 0.3.0",
50125         false,
50126         false
50127     ],
50128     "copyleft-next-0.3.1": [
50129         "copyleft-next 0.3.1",
50130         false,
50131         false
50132     ],
50133     "CPAL-1.0": [
50134         "Common Public Attribution License 1.0",
50135         true,
50136         false
50137     ],
50138     "CPL-1.0": [
50139         "Common Public License 1.0",
50140         true,
50141         false
50142     ],
50143     "CPOL-1.02": [
50144         "Code Project Open License 1.02",
50145         false,
50146         false
50147     ],
50148     "Crossword": [
50149         "Crossword License",
50150         false,
50151         false
50152     ],
50153     "CrystalStacker": [
50154         "CrystalStacker License",
50155         false,
50156         false
50157     ],
50158     "CUA-OPL-1.0": [
50159         "CUA Office Public License v1.0",
50160         true,
50161         false
50162     ],
50163     "Cube": [
50164         "Cube License",
50165         false,
50166         false
50167     ],
50168     "curl": [
50169         "curl License",
50170         false,
50171         false
50172     ],
50173     "D-FSL-1.0": [
50174         "Deutsche Freie Software Lizenz",
50175         false,
50176         false
50177     ],
50178     "diffmark": [
50179         "diffmark license",
50180         false,
50181         false
50182     ],
50183     "DOC": [
50184         "DOC License",
50185         false,
50186         false
50187     ],
50188     "Dotseqn": [
50189         "Dotseqn License",
50190         false,
50191         false
50192     ],
50193     "DSDP": [
50194         "DSDP License",
50195         false,
50196         false
50197     ],
50198     "dvipdfm": [
50199         "dvipdfm License",
50200         false,
50201         false
50202     ],
50203     "ECL-1.0": [
50204         "Educational Community License v1.0",
50205         true,
50206         false
50207     ],
50208     "ECL-2.0": [
50209         "Educational Community License v2.0",
50210         true,
50211         false
50212     ],
50213     "eCos-2.0": [
50214         "eCos license version 2.0",
50215         false,
50216         true
50217     ],
50218     "EFL-1.0": [
50219         "Eiffel Forum License v1.0",
50220         true,
50221         false
50222     ],
50223     "EFL-2.0": [
50224         "Eiffel Forum License v2.0",
50225         true,
50226         false
50227     ],
50228     "eGenix": [
50229         "eGenix.com Public License 1.1.0",
50230         false,
50231         false
50232     ],
50233     "Entessa": [
50234         "Entessa Public License v1.0",
50235         true,
50236         false
50237     ],
50238     "EPL-1.0": [
50239         "Eclipse Public License 1.0",
50240         true,
50241         false
50242     ],
50243     "EPL-2.0": [
50244         "Eclipse Public License 2.0",
50245         true,
50246         false
50247     ],
50248     "ErlPL-1.1": [
50249         "Erlang Public License v1.1",
50250         false,
50251         false
50252     ],
50253     "etalab-2.0": [
50254         "Etalab Open License 2.0",
50255         false,
50256         false
50257     ],
50258     "EUDatagrid": [
50259         "EU DataGrid Software License",
50260         true,
50261         false
50262     ],
50263     "EUPL-1.0": [
50264         "European Union Public License 1.0",
50265         false,
50266         false
50267     ],
50268     "EUPL-1.1": [
50269         "European Union Public License 1.1",
50270         true,
50271         false
50272     ],
50273     "EUPL-1.2": [
50274         "European Union Public License 1.2",
50275         true,
50276         false
50277     ],
50278     "Eurosym": [
50279         "Eurosym License",
50280         false,
50281         false
50282     ],
50283     "Fair": [
50284         "Fair License",
50285         true,
50286         false
50287     ],
50288     "Frameworx-1.0": [
50289         "Frameworx Open License 1.0",
50290         true,
50291         false
50292     ],
50293     "FreeImage": [
50294         "FreeImage Public License v1.0",
50295         false,
50296         false
50297     ],
50298     "FSFAP": [
50299         "FSF All Permissive License",
50300         false,
50301         false
50302     ],
50303     "FSFUL": [
50304         "FSF Unlimited License",
50305         false,
50306         false
50307     ],
50308     "FSFULLR": [
50309         "FSF Unlimited License (with License Retention)",
50310         false,
50311         false
50312     ],
50313     "FTL": [
50314         "Freetype Project License",
50315         false,
50316         false
50317     ],
50318     "GFDL-1.1": [
50319         "GNU Free Documentation License v1.1",
50320         false,
50321         true
50322     ],
50323     "GFDL-1.1-only": [
50324         "GNU Free Documentation License v1.1 only",
50325         false,
50326         false
50327     ],
50328     "GFDL-1.1-or-later": [
50329         "GNU Free Documentation License v1.1 or later",
50330         false,
50331         false
50332     ],
50333     "GFDL-1.2": [
50334         "GNU Free Documentation License v1.2",
50335         false,
50336         true
50337     ],
50338     "GFDL-1.2-only": [
50339         "GNU Free Documentation License v1.2 only",
50340         false,
50341         false
50342     ],
50343     "GFDL-1.2-or-later": [
50344         "GNU Free Documentation License v1.2 or later",
50345         false,
50346         false
50347     ],
50348     "GFDL-1.3": [
50349         "GNU Free Documentation License v1.3",
50350         false,
50351         true
50352     ],
50353     "GFDL-1.3-only": [
50354         "GNU Free Documentation License v1.3 only",
50355         false,
50356         false
50357     ],
50358     "GFDL-1.3-or-later": [
50359         "GNU Free Documentation License v1.3 or later",
50360         false,
50361         false
50362     ],
50363     "Giftware": [
50364         "Giftware License",
50365         false,
50366         false
50367     ],
50368     "GL2PS": [
50369         "GL2PS License",
50370         false,
50371         false
50372     ],
50373     "Glide": [
50374         "3dfx Glide License",
50375         false,
50376         false
50377     ],
50378     "Glulxe": [
50379         "Glulxe License",
50380         false,
50381         false
50382     ],
50383     "gnuplot": [
50384         "gnuplot License",
50385         false,
50386         false
50387     ],
50388     "GPL-1.0": [
50389         "GNU General Public License v1.0 only",
50390         false,
50391         true
50392     ],
50393     "GPL-1.0+": [
50394         "GNU General Public License v1.0 or later",
50395         false,
50396         true
50397     ],
50398     "GPL-1.0-only": [
50399         "GNU General Public License v1.0 only",
50400         false,
50401         false
50402     ],
50403     "GPL-1.0-or-later": [
50404         "GNU General Public License v1.0 or later",
50405         false,
50406         false
50407     ],
50408     "GPL-2.0": [
50409         "GNU General Public License v2.0 only",
50410         true,
50411         true
50412     ],
50413     "GPL-2.0+": [
50414         "GNU General Public License v2.0 or later",
50415         true,
50416         true
50417     ],
50418     "GPL-2.0-only": [
50419         "GNU General Public License v2.0 only",
50420         true,
50421         false
50422     ],
50423     "GPL-2.0-or-later": [
50424         "GNU General Public License v2.0 or later",
50425         true,
50426         false
50427     ],
50428     "GPL-2.0-with-autoconf-exception": [
50429         "GNU General Public License v2.0 w/Autoconf exception",
50430         false,
50431         true
50432     ],
50433     "GPL-2.0-with-bison-exception": [
50434         "GNU General Public License v2.0 w/Bison exception",
50435         false,
50436         true
50437     ],
50438     "GPL-2.0-with-classpath-exception": [
50439         "GNU General Public License v2.0 w/Classpath exception",
50440         false,
50441         true
50442     ],
50443     "GPL-2.0-with-font-exception": [
50444         "GNU General Public License v2.0 w/Font exception",
50445         false,
50446         true
50447     ],
50448     "GPL-2.0-with-GCC-exception": [
50449         "GNU General Public License v2.0 w/GCC Runtime Library exception",
50450         false,
50451         true
50452     ],
50453     "GPL-3.0": [
50454         "GNU General Public License v3.0 only",
50455         true,
50456         true
50457     ],
50458     "GPL-3.0+": [
50459         "GNU General Public License v3.0 or later",
50460         true,
50461         true
50462     ],
50463     "GPL-3.0-only": [
50464         "GNU General Public License v3.0 only",
50465         true,
50466         false
50467     ],
50468     "GPL-3.0-or-later": [
50469         "GNU General Public License v3.0 or later",
50470         true,
50471         false
50472     ],
50473     "GPL-3.0-with-autoconf-exception": [
50474         "GNU General Public License v3.0 w/Autoconf exception",
50475         false,
50476         true
50477     ],
50478     "GPL-3.0-with-GCC-exception": [
50479         "GNU General Public License v3.0 w/GCC Runtime Library exception",
50480         true,
50481         true
50482     ],
50483     "gSOAP-1.3b": [
50484         "gSOAP Public License v1.3b",
50485         false,
50486         false
50487     ],
50488     "HaskellReport": [
50489         "Haskell Language Report License",
50490         false,
50491         false
50492     ],
50493     "HPND": [
50494         "Historical Permission Notice and Disclaimer",
50495         true,
50496         false
50497     ],
50498     "HPND-sell-variant": [
50499         "Historical Permission Notice and Disclaimer - sell variant",
50500         false,
50501         false
50502     ],
50503     "IBM-pibs": [
50504         "IBM PowerPC Initialization and Boot Software",
50505         false,
50506         false
50507     ],
50508     "ICU": [
50509         "ICU License",
50510         false,
50511         false
50512     ],
50513     "IJG": [
50514         "Independent JPEG Group License",
50515         false,
50516         false
50517     ],
50518     "ImageMagick": [
50519         "ImageMagick License",
50520         false,
50521         false
50522     ],
50523     "iMatix": [
50524         "iMatix Standard Function Library Agreement",
50525         false,
50526         false
50527     ],
50528     "Imlib2": [
50529         "Imlib2 License",
50530         false,
50531         false
50532     ],
50533     "Info-ZIP": [
50534         "Info-ZIP License",
50535         false,
50536         false
50537     ],
50538     "Intel": [
50539         "Intel Open Source License",
50540         true,
50541         false
50542     ],
50543     "Intel-ACPI": [
50544         "Intel ACPI Software License Agreement",
50545         false,
50546         false
50547     ],
50548     "Interbase-1.0": [
50549         "Interbase Public License v1.0",
50550         false,
50551         false
50552     ],
50553     "IPA": [
50554         "IPA Font License",
50555         true,
50556         false
50557     ],
50558     "IPL-1.0": [
50559         "IBM Public License v1.0",
50560         true,
50561         false
50562     ],
50563     "ISC": [
50564         "ISC License",
50565         true,
50566         false
50567     ],
50568     "JasPer-2.0": [
50569         "JasPer License",
50570         false,
50571         false
50572     ],
50573     "JPNIC": [
50574         "Japan Network Information Center License",
50575         false,
50576         false
50577     ],
50578     "JSON": [
50579         "JSON License",
50580         false,
50581         false
50582     ],
50583     "LAL-1.2": [
50584         "Licence Art Libre 1.2",
50585         false,
50586         false
50587     ],
50588     "LAL-1.3": [
50589         "Licence Art Libre 1.3",
50590         false,
50591         false
50592     ],
50593     "Latex2e": [
50594         "Latex2e License",
50595         false,
50596         false
50597     ],
50598     "Leptonica": [
50599         "Leptonica License",
50600         false,
50601         false
50602     ],
50603     "LGPL-2.0": [
50604         "GNU Library General Public License v2 only",
50605         true,
50606         true
50607     ],
50608     "LGPL-2.0+": [
50609         "GNU Library General Public License v2 or later",
50610         true,
50611         true
50612     ],
50613     "LGPL-2.0-only": [
50614         "GNU Library General Public License v2 only",
50615         true,
50616         false
50617     ],
50618     "LGPL-2.0-or-later": [
50619         "GNU Library General Public License v2 or later",
50620         true,
50621         false
50622     ],
50623     "LGPL-2.1": [
50624         "GNU Lesser General Public License v2.1 only",
50625         true,
50626         true
50627     ],
50628     "LGPL-2.1+": [
50629         "GNU Library General Public License v2.1 or later",
50630         true,
50631         true
50632     ],
50633     "LGPL-2.1-only": [
50634         "GNU Lesser General Public License v2.1 only",
50635         true,
50636         false
50637     ],
50638     "LGPL-2.1-or-later": [
50639         "GNU Lesser General Public License v2.1 or later",
50640         true,
50641         false
50642     ],
50643     "LGPL-3.0": [
50644         "GNU Lesser General Public License v3.0 only",
50645         true,
50646         true
50647     ],
50648     "LGPL-3.0+": [
50649         "GNU Lesser General Public License v3.0 or later",
50650         true,
50651         true
50652     ],
50653     "LGPL-3.0-only": [
50654         "GNU Lesser General Public License v3.0 only",
50655         true,
50656         false
50657     ],
50658     "LGPL-3.0-or-later": [
50659         "GNU Lesser General Public License v3.0 or later",
50660         true,
50661         false
50662     ],
50663     "LGPLLR": [
50664         "Lesser General Public License For Linguistic Resources",
50665         false,
50666         false
50667     ],
50668     "Libpng": [
50669         "libpng License",
50670         false,
50671         false
50672     ],
50673     "libpng-2.0": [
50674         "PNG Reference Library version 2",
50675         false,
50676         false
50677     ],
50678     "libselinux-1.0": [
50679         "libselinux public domain notice",
50680         false,
50681         false
50682     ],
50683     "libtiff": [
50684         "libtiff License",
50685         false,
50686         false
50687     ],
50688     "LiLiQ-P-1.1": [
50689         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
50690         true,
50691         false
50692     ],
50693     "LiLiQ-R-1.1": [
50694         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
50695         true,
50696         false
50697     ],
50698     "LiLiQ-Rplus-1.1": [
50699         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
50700         true,
50701         false
50702     ],
50703     "Linux-OpenIB": [
50704         "Linux Kernel Variant of OpenIB.org license",
50705         false,
50706         false
50707     ],
50708     "LPL-1.0": [
50709         "Lucent Public License Version 1.0",
50710         true,
50711         false
50712     ],
50713     "LPL-1.02": [
50714         "Lucent Public License v1.02",
50715         true,
50716         false
50717     ],
50718     "LPPL-1.0": [
50719         "LaTeX Project Public License v1.0",
50720         false,
50721         false
50722     ],
50723     "LPPL-1.1": [
50724         "LaTeX Project Public License v1.1",
50725         false,
50726         false
50727     ],
50728     "LPPL-1.2": [
50729         "LaTeX Project Public License v1.2",
50730         false,
50731         false
50732     ],
50733     "LPPL-1.3a": [
50734         "LaTeX Project Public License v1.3a",
50735         false,
50736         false
50737     ],
50738     "LPPL-1.3c": [
50739         "LaTeX Project Public License v1.3c",
50740         true,
50741         false
50742     ],
50743     "MakeIndex": [
50744         "MakeIndex License",
50745         false,
50746         false
50747     ],
50748     "MirOS": [
50749         "The MirOS Licence",
50750         true,
50751         false
50752     ],
50753     "MIT": [
50754         "MIT License",
50755         true,
50756         false
50757     ],
50758     "MIT-0": [
50759         "MIT No Attribution",
50760         false,
50761         false
50762     ],
50763     "MIT-advertising": [
50764         "Enlightenment License (e16)",
50765         false,
50766         false
50767     ],
50768     "MIT-CMU": [
50769         "CMU License",
50770         false,
50771         false
50772     ],
50773     "MIT-enna": [
50774         "enna License",
50775         false,
50776         false
50777     ],
50778     "MIT-feh": [
50779         "feh License",
50780         false,
50781         false
50782     ],
50783     "MITNFA": [
50784         "MIT +no-false-attribs license",
50785         false,
50786         false
50787     ],
50788     "Motosoto": [
50789         "Motosoto License",
50790         true,
50791         false
50792     ],
50793     "mpich2": [
50794         "mpich2 License",
50795         false,
50796         false
50797     ],
50798     "MPL-1.0": [
50799         "Mozilla Public License 1.0",
50800         true,
50801         false
50802     ],
50803     "MPL-1.1": [
50804         "Mozilla Public License 1.1",
50805         true,
50806         false
50807     ],
50808     "MPL-2.0": [
50809         "Mozilla Public License 2.0",
50810         true,
50811         false
50812     ],
50813     "MPL-2.0-no-copyleft-exception": [
50814         "Mozilla Public License 2.0 (no copyleft exception)",
50815         true,
50816         false
50817     ],
50818     "MS-PL": [
50819         "Microsoft Public License",
50820         true,
50821         false
50822     ],
50823     "MS-RL": [
50824         "Microsoft Reciprocal License",
50825         true,
50826         false
50827     ],
50828     "MTLL": [
50829         "Matrix Template Library License",
50830         false,
50831         false
50832     ],
50833     "MulanPSL-1.0": [
50834         "Mulan Permissive Software License, Version 1",
50835         false,
50836         false
50837     ],
50838     "Multics": [
50839         "Multics License",
50840         true,
50841         false
50842     ],
50843     "Mup": [
50844         "Mup License",
50845         false,
50846         false
50847     ],
50848     "NASA-1.3": [
50849         "NASA Open Source Agreement 1.3",
50850         true,
50851         false
50852     ],
50853     "Naumen": [
50854         "Naumen Public License",
50855         true,
50856         false
50857     ],
50858     "NBPL-1.0": [
50859         "Net Boolean Public License v1",
50860         false,
50861         false
50862     ],
50863     "NCSA": [
50864         "University of Illinois/NCSA Open Source License",
50865         true,
50866         false
50867     ],
50868     "Net-SNMP": [
50869         "Net-SNMP License",
50870         false,
50871         false
50872     ],
50873     "NetCDF": [
50874         "NetCDF license",
50875         false,
50876         false
50877     ],
50878     "Newsletr": [
50879         "Newsletr License",
50880         false,
50881         false
50882     ],
50883     "NGPL": [
50884         "Nethack General Public License",
50885         true,
50886         false
50887     ],
50888     "NLOD-1.0": [
50889         "Norwegian Licence for Open Government Data",
50890         false,
50891         false
50892     ],
50893     "NLPL": [
50894         "No Limit Public License",
50895         false,
50896         false
50897     ],
50898     "Nokia": [
50899         "Nokia Open Source License",
50900         true,
50901         false
50902     ],
50903     "NOSL": [
50904         "Netizen Open Source License",
50905         false,
50906         false
50907     ],
50908     "Noweb": [
50909         "Noweb License",
50910         false,
50911         false
50912     ],
50913     "NPL-1.0": [
50914         "Netscape Public License v1.0",
50915         false,
50916         false
50917     ],
50918     "NPL-1.1": [
50919         "Netscape Public License v1.1",
50920         false,
50921         false
50922     ],
50923     "NPOSL-3.0": [
50924         "Non-Profit Open Software License 3.0",
50925         true,
50926         false
50927     ],
50928     "NRL": [
50929         "NRL License",
50930         false,
50931         false
50932     ],
50933     "NTP": [
50934         "NTP License",
50935         true,
50936         false
50937     ],
50938     "NTP-0": [
50939         "NTP No Attribution",
50940         false,
50941         false
50942     ],
50943     "Nunit": [
50944         "Nunit License",
50945         false,
50946         true
50947     ],
50948     "OCCT-PL": [
50949         "Open CASCADE Technology Public License",
50950         false,
50951         false
50952     ],
50953     "OCLC-2.0": [
50954         "OCLC Research Public License 2.0",
50955         true,
50956         false
50957     ],
50958     "ODbL-1.0": [
50959         "ODC Open Database License v1.0",
50960         false,
50961         false
50962     ],
50963     "ODC-By-1.0": [
50964         "Open Data Commons Attribution License v1.0",
50965         false,
50966         false
50967     ],
50968     "OFL-1.0": [
50969         "SIL Open Font License 1.0",
50970         false,
50971         false
50972     ],
50973     "OFL-1.0-no-RFN": [
50974         "SIL Open Font License 1.0 with no Reserved Font Name",
50975         false,
50976         false
50977     ],
50978     "OFL-1.0-RFN": [
50979         "SIL Open Font License 1.0 with Reserved Font Name",
50980         false,
50981         false
50982     ],
50983     "OFL-1.1": [
50984         "SIL Open Font License 1.1",
50985         true,
50986         false
50987     ],
50988     "OFL-1.1-no-RFN": [
50989         "SIL Open Font License 1.1 with no Reserved Font Name",
50990         true,
50991         false
50992     ],
50993     "OFL-1.1-RFN": [
50994         "SIL Open Font License 1.1 with Reserved Font Name",
50995         true,
50996         false
50997     ],
50998     "OGL-Canada-2.0": [
50999         "Open Government Licence - Canada",
51000         false,
51001         false
51002     ],
51003     "OGL-UK-1.0": [
51004         "Open Government Licence v1.0",
51005         false,
51006         false
51007     ],
51008     "OGL-UK-2.0": [
51009         "Open Government Licence v2.0",
51010         false,
51011         false
51012     ],
51013     "OGL-UK-3.0": [
51014         "Open Government Licence v3.0",
51015         false,
51016         false
51017     ],
51018     "OGTSL": [
51019         "Open Group Test Suite License",
51020         true,
51021         false
51022     ],
51023     "OLDAP-1.1": [
51024         "Open LDAP Public License v1.1",
51025         false,
51026         false
51027     ],
51028     "OLDAP-1.2": [
51029         "Open LDAP Public License v1.2",
51030         false,
51031         false
51032     ],
51033     "OLDAP-1.3": [
51034         "Open LDAP Public License v1.3",
51035         false,
51036         false
51037     ],
51038     "OLDAP-1.4": [
51039         "Open LDAP Public License v1.4",
51040         false,
51041         false
51042     ],
51043     "OLDAP-2.0": [
51044         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
51045         false,
51046         false
51047     ],
51048     "OLDAP-2.0.1": [
51049         "Open LDAP Public License v2.0.1",
51050         false,
51051         false
51052     ],
51053     "OLDAP-2.1": [
51054         "Open LDAP Public License v2.1",
51055         false,
51056         false
51057     ],
51058     "OLDAP-2.2": [
51059         "Open LDAP Public License v2.2",
51060         false,
51061         false
51062     ],
51063     "OLDAP-2.2.1": [
51064         "Open LDAP Public License v2.2.1",
51065         false,
51066         false
51067     ],
51068     "OLDAP-2.2.2": [
51069         "Open LDAP Public License 2.2.2",
51070         false,
51071         false
51072     ],
51073     "OLDAP-2.3": [
51074         "Open LDAP Public License v2.3",
51075         false,
51076         false
51077     ],
51078     "OLDAP-2.4": [
51079         "Open LDAP Public License v2.4",
51080         false,
51081         false
51082     ],
51083     "OLDAP-2.5": [
51084         "Open LDAP Public License v2.5",
51085         false,
51086         false
51087     ],
51088     "OLDAP-2.6": [
51089         "Open LDAP Public License v2.6",
51090         false,
51091         false
51092     ],
51093     "OLDAP-2.7": [
51094         "Open LDAP Public License v2.7",
51095         false,
51096         false
51097     ],
51098     "OLDAP-2.8": [
51099         "Open LDAP Public License v2.8",
51100         false,
51101         false
51102     ],
51103     "OML": [
51104         "Open Market License",
51105         false,
51106         false
51107     ],
51108     "OpenSSL": [
51109         "OpenSSL License",
51110         false,
51111         false
51112     ],
51113     "OPL-1.0": [
51114         "Open Public License v1.0",
51115         false,
51116         false
51117     ],
51118     "OSET-PL-2.1": [
51119         "OSET Public License version 2.1",
51120         true,
51121         false
51122     ],
51123     "OSL-1.0": [
51124         "Open Software License 1.0",
51125         true,
51126         false
51127     ],
51128     "OSL-1.1": [
51129         "Open Software License 1.1",
51130         false,
51131         false
51132     ],
51133     "OSL-2.0": [
51134         "Open Software License 2.0",
51135         true,
51136         false
51137     ],
51138     "OSL-2.1": [
51139         "Open Software License 2.1",
51140         true,
51141         false
51142     ],
51143     "OSL-3.0": [
51144         "Open Software License 3.0",
51145         true,
51146         false
51147     ],
51148     "Parity-6.0.0": [
51149         "The Parity Public License 6.0.0",
51150         false,
51151         false
51152     ],
51153     "PDDL-1.0": [
51154         "ODC Public Domain Dedication & License 1.0",
51155         false,
51156         false
51157     ],
51158     "PHP-3.0": [
51159         "PHP License v3.0",
51160         true,
51161         false
51162     ],
51163     "PHP-3.01": [
51164         "PHP License v3.01",
51165         false,
51166         false
51167     ],
51168     "Plexus": [
51169         "Plexus Classworlds License",
51170         false,
51171         false
51172     ],
51173     "PostgreSQL": [
51174         "PostgreSQL License",
51175         true,
51176         false
51177     ],
51178     "PSF-2.0": [
51179         "Python Software Foundation License 2.0",
51180         false,
51181         false
51182     ],
51183     "psfrag": [
51184         "psfrag License",
51185         false,
51186         false
51187     ],
51188     "psutils": [
51189         "psutils License",
51190         false,
51191         false
51192     ],
51193     "Python-2.0": [
51194         "Python License 2.0",
51195         true,
51196         false
51197     ],
51198     "Qhull": [
51199         "Qhull License",
51200         false,
51201         false
51202     ],
51203     "QPL-1.0": [
51204         "Q Public License 1.0",
51205         true,
51206         false
51207     ],
51208     "Rdisc": [
51209         "Rdisc License",
51210         false,
51211         false
51212     ],
51213     "RHeCos-1.1": [
51214         "Red Hat eCos Public License v1.1",
51215         false,
51216         false
51217     ],
51218     "RPL-1.1": [
51219         "Reciprocal Public License 1.1",
51220         true,
51221         false
51222     ],
51223     "RPL-1.5": [
51224         "Reciprocal Public License 1.5",
51225         true,
51226         false
51227     ],
51228     "RPSL-1.0": [
51229         "RealNetworks Public Source License v1.0",
51230         true,
51231         false
51232     ],
51233     "RSA-MD": [
51234         "RSA Message-Digest License",
51235         false,
51236         false
51237     ],
51238     "RSCPL": [
51239         "Ricoh Source Code Public License",
51240         true,
51241         false
51242     ],
51243     "Ruby": [
51244         "Ruby License",
51245         false,
51246         false
51247     ],
51248     "SAX-PD": [
51249         "Sax Public Domain Notice",
51250         false,
51251         false
51252     ],
51253     "Saxpath": [
51254         "Saxpath License",
51255         false,
51256         false
51257     ],
51258     "SCEA": [
51259         "SCEA Shared Source License",
51260         false,
51261         false
51262     ],
51263     "Sendmail": [
51264         "Sendmail License",
51265         false,
51266         false
51267     ],
51268     "Sendmail-8.23": [
51269         "Sendmail License 8.23",
51270         false,
51271         false
51272     ],
51273     "SGI-B-1.0": [
51274         "SGI Free Software License B v1.0",
51275         false,
51276         false
51277     ],
51278     "SGI-B-1.1": [
51279         "SGI Free Software License B v1.1",
51280         false,
51281         false
51282     ],
51283     "SGI-B-2.0": [
51284         "SGI Free Software License B v2.0",
51285         false,
51286         false
51287     ],
51288     "SHL-0.5": [
51289         "Solderpad Hardware License v0.5",
51290         false,
51291         false
51292     ],
51293     "SHL-0.51": [
51294         "Solderpad Hardware License, Version 0.51",
51295         false,
51296         false
51297     ],
51298     "SimPL-2.0": [
51299         "Simple Public License 2.0",
51300         true,
51301         false
51302     ],
51303     "SISSL": [
51304         "Sun Industry Standards Source License v1.1",
51305         true,
51306         false
51307     ],
51308     "SISSL-1.2": [
51309         "Sun Industry Standards Source License v1.2",
51310         false,
51311         false
51312     ],
51313     "Sleepycat": [
51314         "Sleepycat License",
51315         true,
51316         false
51317     ],
51318     "SMLNJ": [
51319         "Standard ML of New Jersey License",
51320         false,
51321         false
51322     ],
51323     "SMPPL": [
51324         "Secure Messaging Protocol Public License",
51325         false,
51326         false
51327     ],
51328     "SNIA": [
51329         "SNIA Public License 1.1",
51330         false,
51331         false
51332     ],
51333     "Spencer-86": [
51334         "Spencer License 86",
51335         false,
51336         false
51337     ],
51338     "Spencer-94": [
51339         "Spencer License 94",
51340         false,
51341         false
51342     ],
51343     "Spencer-99": [
51344         "Spencer License 99",
51345         false,
51346         false
51347     ],
51348     "SPL-1.0": [
51349         "Sun Public License v1.0",
51350         true,
51351         false
51352     ],
51353     "SSH-OpenSSH": [
51354         "SSH OpenSSH license",
51355         false,
51356         false
51357     ],
51358     "SSH-short": [
51359         "SSH short notice",
51360         false,
51361         false
51362     ],
51363     "SSPL-1.0": [
51364         "Server Side Public License, v 1",
51365         false,
51366         false
51367     ],
51368     "StandardML-NJ": [
51369         "Standard ML of New Jersey License",
51370         false,
51371         true
51372     ],
51373     "SugarCRM-1.1.3": [
51374         "SugarCRM Public License v1.1.3",
51375         false,
51376         false
51377     ],
51378     "SWL": [
51379         "Scheme Widget Library (SWL) Software License Agreement",
51380         false,
51381         false
51382     ],
51383     "TAPR-OHL-1.0": [
51384         "TAPR Open Hardware License v1.0",
51385         false,
51386         false
51387     ],
51388     "TCL": [
51389         "TCL/TK License",
51390         false,
51391         false
51392     ],
51393     "TCP-wrappers": [
51394         "TCP Wrappers License",
51395         false,
51396         false
51397     ],
51398     "TMate": [
51399         "TMate Open Source License",
51400         false,
51401         false
51402     ],
51403     "TORQUE-1.1": [
51404         "TORQUE v2.5+ Software License v1.1",
51405         false,
51406         false
51407     ],
51408     "TOSL": [
51409         "Trusster Open Source License",
51410         false,
51411         false
51412     ],
51413     "TU-Berlin-1.0": [
51414         "Technische Universitaet Berlin License 1.0",
51415         false,
51416         false
51417     ],
51418     "TU-Berlin-2.0": [
51419         "Technische Universitaet Berlin License 2.0",
51420         false,
51421         false
51422     ],
51423     "UCL-1.0": [
51424         "Upstream Compatibility License v1.0",
51425         true,
51426         false
51427     ],
51428     "Unicode-DFS-2015": [
51429         "Unicode License Agreement - Data Files and Software (2015)",
51430         false,
51431         false
51432     ],
51433     "Unicode-DFS-2016": [
51434         "Unicode License Agreement - Data Files and Software (2016)",
51435         false,
51436         false
51437     ],
51438     "Unicode-TOU": [
51439         "Unicode Terms of Use",
51440         false,
51441         false
51442     ],
51443     "Unlicense": [
51444         "The Unlicense",
51445         false,
51446         false
51447     ],
51448     "UPL-1.0": [
51449         "Universal Permissive License v1.0",
51450         true,
51451         false
51452     ],
51453     "Vim": [
51454         "Vim License",
51455         false,
51456         false
51457     ],
51458     "VOSTROM": [
51459         "VOSTROM Public License for Open Source",
51460         false,
51461         false
51462     ],
51463     "VSL-1.0": [
51464         "Vovida Software License v1.0",
51465         true,
51466         false
51467     ],
51468     "W3C": [
51469         "W3C Software Notice and License (2002-12-31)",
51470         true,
51471         false
51472     ],
51473     "W3C-19980720": [
51474         "W3C Software Notice and License (1998-07-20)",
51475         false,
51476         false
51477     ],
51478     "W3C-20150513": [
51479         "W3C Software Notice and Document License (2015-05-13)",
51480         false,
51481         false
51482     ],
51483     "Watcom-1.0": [
51484         "Sybase Open Watcom Public License 1.0",
51485         true,
51486         false
51487     ],
51488     "Wsuipa": [
51489         "Wsuipa License",
51490         false,
51491         false
51492     ],
51493     "WTFPL": [
51494         "Do What The F*ck You Want To Public License",
51495         false,
51496         false
51497     ],
51498     "wxWindows": [
51499         "wxWindows Library License",
51500         false,
51501         true
51502     ],
51503     "X11": [
51504         "X11 License",
51505         false,
51506         false
51507     ],
51508     "Xerox": [
51509         "Xerox License",
51510         false,
51511         false
51512     ],
51513     "XFree86-1.1": [
51514         "XFree86 License 1.1",
51515         false,
51516         false
51517     ],
51518     "xinetd": [
51519         "xinetd License",
51520         false,
51521         false
51522     ],
51523     "Xnet": [
51524         "X.Net License",
51525         true,
51526         false
51527     ],
51528     "xpp": [
51529         "XPP License",
51530         false,
51531         false
51532     ],
51533     "XSkat": [
51534         "XSkat License",
51535         false,
51536         false
51537     ],
51538     "YPL-1.0": [
51539         "Yahoo! Public License v1.0",
51540         false,
51541         false
51542     ],
51543     "YPL-1.1": [
51544         "Yahoo! Public License v1.1",
51545         false,
51546         false
51547     ],
51548     "Zed": [
51549         "Zed License",
51550         false,
51551         false
51552     ],
51553     "Zend-2.0": [
51554         "Zend License v2.0",
51555         false,
51556         false
51557     ],
51558     "Zimbra-1.3": [
51559         "Zimbra Public License v1.3",
51560         false,
51561         false
51562     ],
51563     "Zimbra-1.4": [
51564         "Zimbra Public License v1.4",
51565         false,
51566         false
51567     ],
51568     "Zlib": [
51569         "zlib License",
51570         true,
51571         false
51572     ],
51573     "zlib-acknowledgement": [
51574         "zlib/libpng License with Acknowledgement",
51575         false,
51576         false
51577     ],
51578     "ZPL-1.1": [
51579         "Zope Public License 1.1",
51580         false,
51581         false
51582     ],
51583     "ZPL-2.0": [
51584         "Zope Public License 2.0",
51585         true,
51586         false
51587     ],
51588     "ZPL-2.1": [
51589         "Zope Public License 2.1",
51590         false,
51591         false
51592     ]
51593 }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
51594 $\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
51595 \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
51596 \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
51597 \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
51598 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
51599 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
51600 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
51601   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
51602     <security>\r
51603       <requestedPrivileges>\r
51604         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
51605       </requestedPrivileges>\r
51606     </security>\r
51607   </trustInfo>\r
51608   <dependency>\r
51609     <dependentAssembly>\r
51610       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
51611     </dependentAssembly>\r
51612   </dependency>\r
51613 </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
51614
51615
51616
51617
51618
51619
51620
51621
51622
51623
51624 namespace Symfony\Component\Console;
51625
51626 use Symfony\Component\Console\Command\Command;
51627 use Symfony\Component\Console\Command\HelpCommand;
51628 use Symfony\Component\Console\Command\ListCommand;
51629 use Symfony\Component\Console\Descriptor\TextDescriptor;
51630 use Symfony\Component\Console\Descriptor\XmlDescriptor;
51631 use Symfony\Component\Console\Event\ConsoleCommandEvent;
51632 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
51633 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
51634 use Symfony\Component\Console\Exception\CommandNotFoundException;
51635 use Symfony\Component\Console\Exception\ExceptionInterface;
51636 use Symfony\Component\Console\Exception\LogicException;
51637 use Symfony\Component\Console\Formatter\OutputFormatter;
51638 use Symfony\Component\Console\Helper\DebugFormatterHelper;
51639 use Symfony\Component\Console\Helper\DialogHelper;
51640 use Symfony\Component\Console\Helper\FormatterHelper;
51641 use Symfony\Component\Console\Helper\Helper;
51642 use Symfony\Component\Console\Helper\HelperSet;
51643 use Symfony\Component\Console\Helper\ProcessHelper;
51644 use Symfony\Component\Console\Helper\ProgressHelper;
51645 use Symfony\Component\Console\Helper\QuestionHelper;
51646 use Symfony\Component\Console\Helper\TableHelper;
51647 use Symfony\Component\Console\Input\ArgvInput;
51648 use Symfony\Component\Console\Input\ArrayInput;
51649 use Symfony\Component\Console\Input\InputArgument;
51650 use Symfony\Component\Console\Input\InputAwareInterface;
51651 use Symfony\Component\Console\Input\InputDefinition;
51652 use Symfony\Component\Console\Input\InputInterface;
51653 use Symfony\Component\Console\Input\InputOption;
51654 use Symfony\Component\Console\Output\BufferedOutput;
51655 use Symfony\Component\Console\Output\ConsoleOutput;
51656 use Symfony\Component\Console\Output\ConsoleOutputInterface;
51657 use Symfony\Component\Console\Output\OutputInterface;
51658 use Symfony\Component\Debug\Exception\FatalThrowableError;
51659 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
51660
51661
51662
51663
51664
51665
51666
51667
51668
51669
51670
51671
51672
51673
51674
51675
51676 class Application
51677 {
51678 private $commands = array();
51679 private $wantHelps = false;
51680 private $runningCommand;
51681 private $name;
51682 private $version;
51683 private $catchExceptions = true;
51684 private $autoExit = true;
51685 private $definition;
51686 private $helperSet;
51687 private $dispatcher;
51688 private $terminalDimensions;
51689 private $defaultCommand;
51690 private $initialized;
51691
51692
51693
51694
51695
51696 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
51697 {
51698 $this->name = $name;
51699 $this->version = $version;
51700 $this->defaultCommand = 'list';
51701 }
51702
51703 public function setDispatcher(EventDispatcherInterface $dispatcher)
51704 {
51705 $this->dispatcher = $dispatcher;
51706 }
51707
51708
51709
51710
51711
51712
51713
51714
51715 public function run(InputInterface $input = null, OutputInterface $output = null)
51716 {
51717 if (null === $input) {
51718 $input = new ArgvInput();
51719 }
51720
51721 if (null === $output) {
51722 $output = new ConsoleOutput();
51723 }
51724
51725 $this->configureIO($input, $output);
51726
51727 try {
51728 $e = null;
51729 $exitCode = $this->doRun($input, $output);
51730 } catch (\Exception $e) {
51731 }
51732
51733 if (null !== $e) {
51734 if (!$this->catchExceptions) {
51735 throw $e;
51736 }
51737
51738 if ($output instanceof ConsoleOutputInterface) {
51739 $this->renderException($e, $output->getErrorOutput());
51740 } else {
51741 $this->renderException($e, $output);
51742 }
51743
51744 $exitCode = $this->getExitCodeForThrowable($e);
51745 }
51746
51747 if ($this->autoExit) {
51748 if ($exitCode > 255) {
51749 $exitCode = 255;
51750 }
51751
51752 exit($exitCode);
51753 }
51754
51755 return $exitCode;
51756 }
51757
51758
51759
51760
51761
51762
51763 public function doRun(InputInterface $input, OutputInterface $output)
51764 {
51765 if (true === $input->hasParameterOption(array('--version', '-V'))) {
51766 $output->writeln($this->getLongVersion());
51767
51768 return 0;
51769 }
51770
51771 $name = $this->getCommandName($input);
51772 if (true === $input->hasParameterOption(array('--help', '-h'))) {
51773 if (!$name) {
51774 $name = 'help';
51775 $input = new ArrayInput(array('command' => 'help'));
51776 } else {
51777 $this->wantHelps = true;
51778 }
51779 }
51780
51781 if (!$name) {
51782 $name = $this->defaultCommand;
51783 $definition = $this->getDefinition();
51784 $definition->setArguments(array_merge(
51785 $definition->getArguments(),
51786 array(
51787 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
51788 )
51789 ));
51790 }
51791
51792 $this->runningCommand = null;
51793
51794  $command = $this->find($name);
51795
51796 $this->runningCommand = $command;
51797 $exitCode = $this->doRunCommand($command, $input, $output);
51798 $this->runningCommand = null;
51799
51800 return $exitCode;
51801 }
51802
51803 public function setHelperSet(HelperSet $helperSet)
51804 {
51805 $this->helperSet = $helperSet;
51806 }
51807
51808
51809
51810
51811
51812
51813 public function getHelperSet()
51814 {
51815 if (!$this->helperSet) {
51816 $this->helperSet = $this->getDefaultHelperSet();
51817 }
51818
51819 return $this->helperSet;
51820 }
51821
51822 public function setDefinition(InputDefinition $definition)
51823 {
51824 $this->definition = $definition;
51825 }
51826
51827
51828
51829
51830
51831
51832 public function getDefinition()
51833 {
51834 if (!$this->definition) {
51835 $this->definition = $this->getDefaultInputDefinition();
51836 }
51837
51838 return $this->definition;
51839 }
51840
51841
51842
51843
51844
51845
51846 public function getHelp()
51847 {
51848 return $this->getLongVersion();
51849 }
51850
51851
51852
51853
51854
51855
51856 public function setCatchExceptions($boolean)
51857 {
51858 $this->catchExceptions = (bool) $boolean;
51859 }
51860
51861
51862
51863
51864
51865
51866 public function setAutoExit($boolean)
51867 {
51868 $this->autoExit = (bool) $boolean;
51869 }
51870
51871
51872
51873
51874
51875
51876 public function getName()
51877 {
51878 return $this->name;
51879 }
51880
51881
51882
51883
51884
51885
51886 public function setName($name)
51887 {
51888 $this->name = $name;
51889 }
51890
51891
51892
51893
51894
51895
51896 public function getVersion()
51897 {
51898 return $this->version;
51899 }
51900
51901
51902
51903
51904
51905
51906 public function setVersion($version)
51907 {
51908 $this->version = $version;
51909 }
51910
51911
51912
51913
51914
51915
51916 public function getLongVersion()
51917 {
51918 if ('UNKNOWN' !== $this->getName()) {
51919 if ('UNKNOWN' !== $this->getVersion()) {
51920 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
51921 }
51922
51923 return sprintf('<info>%s</info>', $this->getName());
51924 }
51925
51926 return '<info>Console Tool</info>';
51927 }
51928
51929
51930
51931
51932
51933
51934
51935
51936 public function register($name)
51937 {
51938 return $this->add(new Command($name));
51939 }
51940
51941
51942
51943
51944
51945
51946
51947
51948 public function addCommands(array $commands)
51949 {
51950 foreach ($commands as $command) {
51951 $this->add($command);
51952 }
51953 }
51954
51955
51956
51957
51958
51959
51960
51961
51962
51963 public function add(Command $command)
51964 {
51965 $this->init();
51966
51967 $command->setApplication($this);
51968
51969 if (!$command->isEnabled()) {
51970 $command->setApplication(null);
51971
51972 return;
51973 }
51974
51975 if (null === $command->getDefinition()) {
51976 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($command)));
51977 }
51978
51979 $this->commands[$command->getName()] = $command;
51980
51981 foreach ($command->getAliases() as $alias) {
51982 $this->commands[$alias] = $command;
51983 }
51984
51985 return $command;
51986 }
51987
51988
51989
51990
51991
51992
51993
51994
51995
51996
51997 public function get($name)
51998 {
51999 $this->init();
52000
52001 if (!isset($this->commands[$name])) {
52002 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
52003 }
52004
52005 $command = $this->commands[$name];
52006
52007 if ($this->wantHelps) {
52008 $this->wantHelps = false;
52009
52010 $helpCommand = $this->get('help');
52011 $helpCommand->setCommand($command);
52012
52013 return $helpCommand;
52014 }
52015
52016 return $command;
52017 }
52018
52019
52020
52021
52022
52023
52024
52025
52026 public function has($name)
52027 {
52028 $this->init();
52029
52030 return isset($this->commands[$name]);
52031 }
52032
52033
52034
52035
52036
52037
52038
52039
52040 public function getNamespaces()
52041 {
52042 $namespaces = array();
52043 foreach ($this->all() as $command) {
52044 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
52045
52046 foreach ($command->getAliases() as $alias) {
52047 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
52048 }
52049 }
52050
52051 return array_values(array_unique(array_filter($namespaces)));
52052 }
52053
52054
52055
52056
52057
52058
52059
52060
52061
52062
52063 public function findNamespace($namespace)
52064 {
52065 $allNamespaces = $this->getNamespaces();
52066 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
52067 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
52068
52069 if (empty($namespaces)) {
52070 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
52071
52072 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
52073 if (1 == \count($alternatives)) {
52074 $message .= "\n\nDid you mean this?\n    ";
52075 } else {
52076 $message .= "\n\nDid you mean one of these?\n    ";
52077 }
52078
52079 $message .= implode("\n    ", $alternatives);
52080 }
52081
52082 throw new CommandNotFoundException($message, $alternatives);
52083 }
52084
52085 $exact = \in_array($namespace, $namespaces, true);
52086 if (\count($namespaces) > 1 && !$exact) {
52087 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
52088 }
52089
52090 return $exact ? $namespace : reset($namespaces);
52091 }
52092
52093
52094
52095
52096
52097
52098
52099
52100
52101
52102
52103
52104
52105 public function find($name)
52106 {
52107 $this->init();
52108 $aliases = array();
52109 $allCommands = array_keys($this->commands);
52110 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
52111 $commands = preg_grep('{^'.$expr.'}', $allCommands);
52112
52113 if (empty($commands) || \count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
52114 if (false !== $pos = strrpos($name, ':')) {
52115
52116  $this->findNamespace(substr($name, 0, $pos));
52117 }
52118
52119 $message = sprintf('Command "%s" is not defined.', $name);
52120
52121 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
52122 if (1 == \count($alternatives)) {
52123 $message .= "\n\nDid you mean this?\n    ";
52124 } else {
52125 $message .= "\n\nDid you mean one of these?\n    ";
52126 }
52127 $message .= implode("\n    ", $alternatives);
52128 }
52129
52130 throw new CommandNotFoundException($message, $alternatives);
52131 }
52132
52133
52134  if (\count($commands) > 1) {
52135 $commandList = $this->commands;
52136 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
52137 $commandName = $commandList[$nameOrAlias]->getName();
52138 $aliases[$nameOrAlias] = $commandName;
52139
52140 return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
52141 });
52142 }
52143
52144 $exact = \in_array($name, $commands, true) || isset($aliases[$name]);
52145 if (!$exact && \count($commands) > 1) {
52146 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
52147
52148 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
52149 }
52150
52151 return $this->get($exact ? $name : reset($commands));
52152 }
52153
52154
52155
52156
52157
52158
52159
52160
52161
52162
52163 public function all($namespace = null)
52164 {
52165 $this->init();
52166
52167 if (null === $namespace) {
52168 return $this->commands;
52169 }
52170
52171 $commands = array();
52172 foreach ($this->commands as $name => $command) {
52173 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
52174 $commands[$name] = $command;
52175 }
52176 }
52177
52178 return $commands;
52179 }
52180
52181
52182
52183
52184
52185
52186
52187
52188 public static function getAbbreviations($names)
52189 {
52190 $abbrevs = array();
52191 foreach ($names as $name) {
52192 for ($len = \strlen($name); $len > 0; --$len) {
52193 $abbrev = substr($name, 0, $len);
52194 $abbrevs[$abbrev][] = $name;
52195 }
52196 }
52197
52198 return $abbrevs;
52199 }
52200
52201
52202
52203
52204
52205
52206
52207
52208
52209
52210
52211 public function asText($namespace = null, $raw = false)
52212 {
52213 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
52214
52215 $descriptor = new TextDescriptor();
52216 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
52217 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
52218
52219 return $output->fetch();
52220 }
52221
52222
52223
52224
52225
52226
52227
52228
52229
52230
52231
52232 public function asXml($namespace = null, $asDom = false)
52233 {
52234 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
52235
52236 $descriptor = new XmlDescriptor();
52237
52238 if ($asDom) {
52239 return $descriptor->getApplicationDocument($this, $namespace);
52240 }
52241
52242 $output = new BufferedOutput();
52243 $descriptor->describe($output, $this, array('namespace' => $namespace));
52244
52245 return $output->fetch();
52246 }
52247
52248
52249
52250
52251 public function renderException($e, $output)
52252 {
52253 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
52254
52255 do {
52256 $title = sprintf('  [%s]  ', \get_class($e));
52257
52258 $len = Helper::strlen($title);
52259
52260 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
52261
52262  if (\defined('HHVM_VERSION') && $width > 1 << 31) {
52263 $width = 1 << 31;
52264 }
52265 $lines = array();
52266 foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) {
52267 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
52268
52269  $lineLength = Helper::strlen($line) + 4;
52270 $lines[] = array($line, $lineLength);
52271
52272 $len = max($lineLength, $len);
52273 }
52274 }
52275
52276 $messages = array();
52277 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
52278 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
52279 foreach ($lines as $line) {
52280 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
52281 }
52282 $messages[] = $emptyLine;
52283 $messages[] = '';
52284
52285 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
52286
52287 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
52288 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
52289
52290
52291  $trace = $e->getTrace();
52292 array_unshift($trace, array(
52293 'function' => '',
52294 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a',
52295 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a',
52296 'args' => array(),
52297 ));
52298
52299 for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
52300 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
52301 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
52302 $function = $trace[$i]['function'];
52303 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
52304 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
52305
52306 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
52307 }
52308
52309 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
52310 }
52311 } while ($e = $e->getPrevious());
52312
52313 if (null !== $this->runningCommand) {
52314 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
52315 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
52316 }
52317 }
52318
52319
52320
52321
52322
52323
52324 protected function getTerminalWidth()
52325 {
52326 $dimensions = $this->getTerminalDimensions();
52327
52328 return $dimensions[0];
52329 }
52330
52331
52332
52333
52334
52335
52336 protected function getTerminalHeight()
52337 {
52338 $dimensions = $this->getTerminalDimensions();
52339
52340 return $dimensions[1];
52341 }
52342
52343
52344
52345
52346
52347
52348 public function getTerminalDimensions()
52349 {
52350 if ($this->terminalDimensions) {
52351 return $this->terminalDimensions;
52352 }
52353
52354 if ('\\' === \DIRECTORY_SEPARATOR) {
52355
52356  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
52357 return array((int) $matches[1], (int) $matches[2]);
52358 }
52359
52360  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
52361 return array((int) $matches[1], (int) $matches[2]);
52362 }
52363 }
52364
52365 if ($sttyString = $this->getSttyColumns()) {
52366
52367  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
52368 return array((int) $matches[2], (int) $matches[1]);
52369 }
52370
52371  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
52372 return array((int) $matches[2], (int) $matches[1]);
52373 }
52374 }
52375
52376 return array(null, null);
52377 }
52378
52379
52380
52381
52382
52383
52384
52385
52386
52387
52388
52389 public function setTerminalDimensions($width, $height)
52390 {
52391 $this->terminalDimensions = array($width, $height);
52392
52393 return $this;
52394 }
52395
52396
52397
52398
52399 protected function configureIO(InputInterface $input, OutputInterface $output)
52400 {
52401 if (true === $input->hasParameterOption(array('--ansi'))) {
52402 $output->setDecorated(true);
52403 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
52404 $output->setDecorated(false);
52405 }
52406
52407 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
52408 $input->setInteractive(false);
52409 } elseif (\function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
52410 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
52411 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
52412 $input->setInteractive(false);
52413 }
52414 }
52415
52416 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
52417 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
52418 $input->setInteractive(false);
52419 } else {
52420 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) {
52421 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
52422 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) {
52423 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
52424 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
52425 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
52426 }
52427 }
52428 }
52429
52430
52431
52432
52433
52434
52435
52436
52437
52438 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
52439 {
52440 foreach ($command->getHelperSet() as $helper) {
52441 if ($helper instanceof InputAwareInterface) {
52442 $helper->setInput($input);
52443 }
52444 }
52445
52446 if (null === $this->dispatcher) {
52447 return $command->run($input, $output);
52448 }
52449
52450
52451  try {
52452 $command->mergeApplicationDefinition();
52453 $input->bind($command->getDefinition());
52454 } catch (ExceptionInterface $e) {
52455
52456  }
52457
52458 $event = new ConsoleCommandEvent($command, $input, $output);
52459 $e = null;
52460
52461 try {
52462 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
52463
52464 if ($event->commandShouldRun()) {
52465 $exitCode = $command->run($input, $output);
52466 } else {
52467 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
52468 }
52469 } catch (\Exception $e) {
52470 } catch (\Throwable $e) {
52471 }
52472 if (null !== $e) {
52473 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
52474 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
52475 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
52476
52477 if ($x !== $event->getException()) {
52478 $e = $event->getException();
52479 }
52480
52481 $exitCode = $this->getExitCodeForThrowable($e);
52482 }
52483
52484 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
52485 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
52486
52487 if (null !== $e) {
52488 throw $e;
52489 }
52490
52491 return $event->getExitCode();
52492 }
52493
52494
52495
52496
52497
52498
52499 protected function getCommandName(InputInterface $input)
52500 {
52501 return $input->getFirstArgument();
52502 }
52503
52504
52505
52506
52507
52508
52509 protected function getDefaultInputDefinition()
52510 {
52511 return new InputDefinition(array(
52512 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
52513
52514 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
52515 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
52516 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'),
52517 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
52518 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
52519 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
52520 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
52521 ));
52522 }
52523
52524
52525
52526
52527
52528
52529 protected function getDefaultCommands()
52530 {
52531 return array(new HelpCommand(), new ListCommand());
52532 }
52533
52534
52535
52536
52537
52538
52539 protected function getDefaultHelperSet()
52540 {
52541 return new HelperSet(array(
52542 new FormatterHelper(),
52543 new DialogHelper(false),
52544 new ProgressHelper(false),
52545 new TableHelper(false),
52546 new DebugFormatterHelper(),
52547 new ProcessHelper(),
52548 new QuestionHelper(),
52549 ));
52550 }
52551
52552
52553
52554
52555
52556
52557 private function getSttyColumns()
52558 {
52559 if (!\function_exists('proc_open')) {
52560 return;
52561 }
52562
52563 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
52564 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
52565 if (\is_resource($process)) {
52566 $info = stream_get_contents($pipes[1]);
52567 fclose($pipes[1]);
52568 fclose($pipes[2]);
52569 proc_close($process);
52570
52571 return $info;
52572 }
52573 }
52574
52575
52576
52577
52578
52579
52580 private function getConsoleMode()
52581 {
52582 if (!\function_exists('proc_open')) {
52583 return;
52584 }
52585
52586 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
52587 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
52588 if (\is_resource($process)) {
52589 $info = stream_get_contents($pipes[1]);
52590 fclose($pipes[1]);
52591 fclose($pipes[2]);
52592 proc_close($process);
52593
52594 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
52595 return $matches[2].'x'.$matches[1];
52596 }
52597 }
52598 }
52599
52600
52601
52602
52603
52604
52605
52606
52607 private function getAbbreviationSuggestions($abbrevs)
52608 {
52609 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], \count($abbrevs) > 2 ? sprintf(' and %d more', \count($abbrevs) - 2) : '');
52610 }
52611
52612
52613
52614
52615
52616
52617
52618
52619
52620
52621
52622 public function extractNamespace($name, $limit = null)
52623 {
52624 $parts = explode(':', $name);
52625 array_pop($parts);
52626
52627 return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
52628 }
52629
52630
52631
52632
52633
52634
52635
52636
52637
52638
52639 private function findAlternatives($name, $collection)
52640 {
52641 $threshold = 1e3;
52642 $alternatives = array();
52643
52644 $collectionParts = array();
52645 foreach ($collection as $item) {
52646 $collectionParts[$item] = explode(':', $item);
52647 }
52648
52649 foreach (explode(':', $name) as $i => $subname) {
52650 foreach ($collectionParts as $collectionName => $parts) {
52651 $exists = isset($alternatives[$collectionName]);
52652 if (!isset($parts[$i]) && $exists) {
52653 $alternatives[$collectionName] += $threshold;
52654 continue;
52655 } elseif (!isset($parts[$i])) {
52656 continue;
52657 }
52658
52659 $lev = levenshtein($subname, $parts[$i]);
52660 if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
52661 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
52662 } elseif ($exists) {
52663 $alternatives[$collectionName] += $threshold;
52664 }
52665 }
52666 }
52667
52668 foreach ($collection as $item) {
52669 $lev = levenshtein($name, $item);
52670 if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) {
52671 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
52672 }
52673 }
52674
52675 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
52676 asort($alternatives);
52677
52678 return array_keys($alternatives);
52679 }
52680
52681
52682
52683
52684
52685
52686 public function setDefaultCommand($commandName)
52687 {
52688 $this->defaultCommand = $commandName;
52689 }
52690
52691 private function splitStringByWidth($string, $width)
52692 {
52693
52694  
52695  
52696  if (false === $encoding = mb_detect_encoding($string, null, true)) {
52697 return str_split($string, $width);
52698 }
52699
52700 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
52701 $lines = array();
52702 $line = '';
52703 foreach (preg_split('//u', $utf8String) as $char) {
52704
52705  if (mb_strwidth($line.$char, 'utf8') <= $width) {
52706 $line .= $char;
52707 continue;
52708 }
52709
52710  $lines[] = str_pad($line, $width);
52711 $line = $char;
52712 }
52713
52714 $lines[] = \count($lines) ? str_pad($line, $width) : $line;
52715
52716 mb_convert_variables($encoding, 'utf8', $lines);
52717
52718 return $lines;
52719 }
52720
52721
52722
52723
52724
52725
52726
52727
52728 private function extractAllNamespaces($name)
52729 {
52730
52731  $parts = explode(':', $name, -1);
52732 $namespaces = array();
52733
52734 foreach ($parts as $part) {
52735 if (\count($namespaces)) {
52736 $namespaces[] = end($namespaces).':'.$part;
52737 } else {
52738 $namespaces[] = $part;
52739 }
52740 }
52741
52742 return $namespaces;
52743 }
52744
52745 private function init()
52746 {
52747 if ($this->initialized) {
52748 return;
52749 }
52750 $this->initialized = true;
52751
52752 foreach ($this->getDefaultCommands() as $command) {
52753 $this->add($command);
52754 }
52755 }
52756
52757
52758
52759
52760
52761
52762 private function getExitCodeForThrowable($throwable)
52763 {
52764 $exitCode = $throwable->getCode();
52765 if (is_numeric($exitCode)) {
52766 $exitCode = (int) $exitCode;
52767 if (0 === $exitCode) {
52768 $exitCode = 1;
52769 }
52770 } else {
52771 $exitCode = 1;
52772 }
52773
52774 return $exitCode;
52775 }
52776 }
52777 <?php
52778
52779
52780
52781
52782
52783
52784
52785
52786
52787
52788 namespace Symfony\Component\Console\Command;
52789
52790 use Symfony\Component\Console\Application;
52791 use Symfony\Component\Console\Descriptor\TextDescriptor;
52792 use Symfony\Component\Console\Descriptor\XmlDescriptor;
52793 use Symfony\Component\Console\Exception\ExceptionInterface;
52794 use Symfony\Component\Console\Exception\InvalidArgumentException;
52795 use Symfony\Component\Console\Exception\LogicException;
52796 use Symfony\Component\Console\Helper\HelperSet;
52797 use Symfony\Component\Console\Input\InputArgument;
52798 use Symfony\Component\Console\Input\InputDefinition;
52799 use Symfony\Component\Console\Input\InputInterface;
52800 use Symfony\Component\Console\Input\InputOption;
52801 use Symfony\Component\Console\Output\BufferedOutput;
52802 use Symfony\Component\Console\Output\OutputInterface;
52803
52804
52805
52806
52807
52808
52809 class Command
52810 {
52811 private $application;
52812 private $name;
52813 private $processTitle;
52814 private $aliases = array();
52815 private $definition;
52816 private $help;
52817 private $description;
52818 private $ignoreValidationErrors = false;
52819 private $applicationDefinitionMerged = false;
52820 private $applicationDefinitionMergedWithArgs = false;
52821 private $code;
52822 private $synopsis = array();
52823 private $usages = array();
52824 private $helperSet;
52825
52826
52827
52828
52829
52830
52831 public function __construct($name = null)
52832 {
52833 $this->definition = new InputDefinition();
52834
52835 if (null !== $name) {
52836 $this->setName($name);
52837 }
52838
52839 $this->configure();
52840
52841 if (!$this->name) {
52842 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($this)));
52843 }
52844 }
52845
52846
52847
52848
52849
52850
52851 public function ignoreValidationErrors()
52852 {
52853 $this->ignoreValidationErrors = true;
52854 }
52855
52856 public function setApplication(Application $application = null)
52857 {
52858 $this->application = $application;
52859 if ($application) {
52860 $this->setHelperSet($application->getHelperSet());
52861 } else {
52862 $this->helperSet = null;
52863 }
52864 }
52865
52866 public function setHelperSet(HelperSet $helperSet)
52867 {
52868 $this->helperSet = $helperSet;
52869 }
52870
52871
52872
52873
52874
52875
52876 public function getHelperSet()
52877 {
52878 return $this->helperSet;
52879 }
52880
52881
52882
52883
52884
52885
52886 public function getApplication()
52887 {
52888 return $this->application;
52889 }
52890
52891
52892
52893
52894
52895
52896
52897
52898
52899 public function isEnabled()
52900 {
52901 return true;
52902 }
52903
52904
52905
52906
52907 protected function configure()
52908 {
52909 }
52910
52911
52912
52913
52914
52915
52916
52917
52918
52919
52920
52921
52922
52923
52924
52925 protected function execute(InputInterface $input, OutputInterface $output)
52926 {
52927 throw new LogicException('You must override the execute() method in the concrete command class.');
52928 }
52929
52930
52931
52932
52933
52934
52935
52936
52937 protected function interact(InputInterface $input, OutputInterface $output)
52938 {
52939 }
52940
52941
52942
52943
52944
52945
52946
52947
52948
52949
52950
52951 protected function initialize(InputInterface $input, OutputInterface $output)
52952 {
52953 }
52954
52955
52956
52957
52958
52959
52960
52961
52962
52963
52964
52965
52966
52967
52968
52969 public function run(InputInterface $input, OutputInterface $output)
52970 {
52971
52972  $this->getSynopsis(true);
52973 $this->getSynopsis(false);
52974
52975
52976  $this->mergeApplicationDefinition();
52977
52978
52979  try {
52980 $input->bind($this->definition);
52981 } catch (ExceptionInterface $e) {
52982 if (!$this->ignoreValidationErrors) {
52983 throw $e;
52984 }
52985 }
52986
52987 $this->initialize($input, $output);
52988
52989 if (null !== $this->processTitle) {
52990 if (\function_exists('cli_set_process_title')) {
52991 if (!@cli_set_process_title($this->processTitle)) {
52992 if ('Darwin' === PHP_OS) {
52993 $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
52994 } else {
52995 cli_set_process_title($this->processTitle);
52996 }
52997 }
52998 } elseif (\function_exists('setproctitle')) {
52999 setproctitle($this->processTitle);
53000 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
53001 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
53002 }
53003 }
53004
53005 if ($input->isInteractive()) {
53006 $this->interact($input, $output);
53007 }
53008
53009
53010  
53011  
53012  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
53013 $input->setArgument('command', $this->getName());
53014 }
53015
53016 $input->validate();
53017
53018 if ($this->code) {
53019 $statusCode = \call_user_func($this->code, $input, $output);
53020 } else {
53021 $statusCode = $this->execute($input, $output);
53022 }
53023
53024 return is_numeric($statusCode) ? (int) $statusCode : 0;
53025 }
53026
53027
53028
53029
53030
53031
53032
53033
53034
53035
53036
53037
53038
53039
53040
53041 public function setCode($code)
53042 {
53043 if (!\is_callable($code)) {
53044 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
53045 }
53046
53047 if (\PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
53048 $r = new \ReflectionFunction($code);
53049 if (null === $r->getClosureThis()) {
53050 if (\PHP_VERSION_ID < 70000) {
53051
53052  
53053  
53054  
53055  $code = @\Closure::bind($code, $this);
53056 } else {
53057 $code = \Closure::bind($code, $this);
53058 }
53059 }
53060 }
53061
53062 $this->code = $code;
53063
53064 return $this;
53065 }
53066
53067
53068
53069
53070
53071
53072
53073
53074 public function mergeApplicationDefinition($mergeArgs = true)
53075 {
53076 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
53077 return;
53078 }
53079
53080 $this->definition->addOptions($this->application->getDefinition()->getOptions());
53081
53082 $this->applicationDefinitionMerged = true;
53083
53084 if ($mergeArgs) {
53085 $currentArguments = $this->definition->getArguments();
53086 $this->definition->setArguments($this->application->getDefinition()->getArguments());
53087 $this->definition->addArguments($currentArguments);
53088
53089 $this->applicationDefinitionMergedWithArgs = true;
53090 }
53091 }
53092
53093
53094
53095
53096
53097
53098
53099
53100 public function setDefinition($definition)
53101 {
53102 if ($definition instanceof InputDefinition) {
53103 $this->definition = $definition;
53104 } else {
53105 $this->definition->setDefinition($definition);
53106 }
53107
53108 $this->applicationDefinitionMerged = false;
53109
53110 return $this;
53111 }
53112
53113
53114
53115
53116
53117
53118 public function getDefinition()
53119 {
53120 return $this->definition;
53121 }
53122
53123
53124
53125
53126
53127
53128
53129
53130
53131
53132
53133 public function getNativeDefinition()
53134 {
53135 return $this->getDefinition();
53136 }
53137
53138
53139
53140
53141
53142
53143
53144
53145
53146
53147
53148
53149
53150 public function addArgument($name, $mode = null, $description = '', $default = null)
53151 {
53152 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
53153
53154 return $this;
53155 }
53156
53157
53158
53159
53160
53161
53162
53163
53164
53165
53166
53167
53168
53169
53170 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
53171 {
53172 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
53173
53174 return $this;
53175 }
53176
53177
53178
53179
53180
53181
53182
53183
53184
53185
53186
53187
53188
53189
53190
53191 public function setName($name)
53192 {
53193 $this->validateName($name);
53194
53195 $this->name = $name;
53196
53197 return $this;
53198 }
53199
53200
53201
53202
53203
53204
53205
53206
53207
53208
53209
53210
53211
53212 public function setProcessTitle($title)
53213 {
53214 $this->processTitle = $title;
53215
53216 return $this;
53217 }
53218
53219
53220
53221
53222
53223
53224 public function getName()
53225 {
53226 return $this->name;
53227 }
53228
53229
53230
53231
53232
53233
53234
53235
53236 public function setDescription($description)
53237 {
53238 $this->description = $description;
53239
53240 return $this;
53241 }
53242
53243
53244
53245
53246
53247
53248 public function getDescription()
53249 {
53250 return $this->description;
53251 }
53252
53253
53254
53255
53256
53257
53258
53259
53260 public function setHelp($help)
53261 {
53262 $this->help = $help;
53263
53264 return $this;
53265 }
53266
53267
53268
53269
53270
53271
53272 public function getHelp()
53273 {
53274 return $this->help;
53275 }
53276
53277
53278
53279
53280
53281
53282
53283 public function getProcessedHelp()
53284 {
53285 $name = $this->name;
53286
53287 $placeholders = array(
53288 '%command.name%',
53289 '%command.full_name%',
53290 );
53291 $replacements = array(
53292 $name,
53293 $_SERVER['PHP_SELF'].' '.$name,
53294 );
53295
53296 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
53297 }
53298
53299
53300
53301
53302
53303
53304
53305
53306
53307
53308 public function setAliases($aliases)
53309 {
53310 if (!\is_array($aliases) && !$aliases instanceof \Traversable) {
53311 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
53312 }
53313
53314 foreach ($aliases as $alias) {
53315 $this->validateName($alias);
53316 }
53317
53318 $this->aliases = $aliases;
53319
53320 return $this;
53321 }
53322
53323
53324
53325
53326
53327
53328 public function getAliases()
53329 {
53330 return $this->aliases;
53331 }
53332
53333
53334
53335
53336
53337
53338
53339
53340 public function getSynopsis($short = false)
53341 {
53342 $key = $short ? 'short' : 'long';
53343
53344 if (!isset($this->synopsis[$key])) {
53345 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
53346 }
53347
53348 return $this->synopsis[$key];
53349 }
53350
53351
53352
53353
53354
53355
53356
53357
53358 public function addUsage($usage)
53359 {
53360 if (0 !== strpos($usage, $this->name)) {
53361 $usage = sprintf('%s %s', $this->name, $usage);
53362 }
53363
53364 $this->usages[] = $usage;
53365
53366 return $this;
53367 }
53368
53369
53370
53371
53372
53373
53374 public function getUsages()
53375 {
53376 return $this->usages;
53377 }
53378
53379
53380
53381
53382
53383
53384
53385
53386
53387
53388
53389 public function getHelper($name)
53390 {
53391 if (null === $this->helperSet) {
53392 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));
53393 }
53394
53395 return $this->helperSet->get($name);
53396 }
53397
53398
53399
53400
53401
53402
53403
53404
53405 public function asText()
53406 {
53407 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
53408
53409 $descriptor = new TextDescriptor();
53410 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
53411 $descriptor->describe($output, $this, array('raw_output' => true));
53412
53413 return $output->fetch();
53414 }
53415
53416
53417
53418
53419
53420
53421
53422
53423
53424
53425 public function asXml($asDom = false)
53426 {
53427 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
53428
53429 $descriptor = new XmlDescriptor();
53430
53431 if ($asDom) {
53432 return $descriptor->getCommandDocument($this);
53433 }
53434
53435 $output = new BufferedOutput();
53436 $descriptor->describe($output, $this);
53437
53438 return $output->fetch();
53439 }
53440
53441
53442
53443
53444
53445
53446
53447
53448
53449
53450 private function validateName($name)
53451 {
53452 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
53453 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
53454 }
53455 }
53456 }
53457 <?php
53458
53459
53460
53461
53462
53463
53464
53465
53466
53467
53468 namespace Symfony\Component\Console\Command;
53469
53470 use Symfony\Component\Console\Helper\DescriptorHelper;
53471 use Symfony\Component\Console\Input\InputArgument;
53472 use Symfony\Component\Console\Input\InputInterface;
53473 use Symfony\Component\Console\Input\InputOption;
53474 use Symfony\Component\Console\Output\OutputInterface;
53475
53476
53477
53478
53479
53480
53481 class HelpCommand extends Command
53482 {
53483 private $command;
53484
53485
53486
53487
53488 protected function configure()
53489 {
53490 $this->ignoreValidationErrors();
53491
53492 $this
53493 ->setName('help')
53494 ->setDefinition(array(
53495 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
53496 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
53497 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
53498 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
53499 ))
53500 ->setDescription('Displays help for a command')
53501 ->setHelp(<<<'EOF'
53502 The <info>%command.name%</info> command displays help for a given command:
53503
53504   <info>php %command.full_name% list</info>
53505
53506 You can also output the help in other formats by using the <comment>--format</comment> option:
53507
53508   <info>php %command.full_name% --format=xml list</info>
53509
53510 To display the list of available commands, please use the <info>list</info> command.
53511 EOF
53512 )
53513 ;
53514 }
53515
53516 public function setCommand(Command $command)
53517 {
53518 $this->command = $command;
53519 }
53520
53521
53522
53523
53524 protected function execute(InputInterface $input, OutputInterface $output)
53525 {
53526 if (null === $this->command) {
53527 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
53528 }
53529
53530 if ($input->getOption('xml')) {
53531 @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);
53532
53533 $input->setOption('format', 'xml');
53534 }
53535
53536 $helper = new DescriptorHelper();
53537 $helper->describe($output, $this->command, array(
53538 'format' => $input->getOption('format'),
53539 'raw_text' => $input->getOption('raw'),
53540 ));
53541
53542 $this->command = null;
53543 }
53544 }
53545 <?php
53546
53547
53548
53549
53550
53551
53552
53553
53554
53555
53556 namespace Symfony\Component\Console\Command;
53557
53558 use Symfony\Component\Console\Helper\DescriptorHelper;
53559 use Symfony\Component\Console\Input\InputArgument;
53560 use Symfony\Component\Console\Input\InputDefinition;
53561 use Symfony\Component\Console\Input\InputInterface;
53562 use Symfony\Component\Console\Input\InputOption;
53563 use Symfony\Component\Console\Output\OutputInterface;
53564
53565
53566
53567
53568
53569
53570 class ListCommand extends Command
53571 {
53572
53573
53574
53575 protected function configure()
53576 {
53577 $this
53578 ->setName('list')
53579 ->setDefinition($this->createDefinition())
53580 ->setDescription('Lists commands')
53581 ->setHelp(<<<'EOF'
53582 The <info>%command.name%</info> command lists all commands:
53583
53584   <info>php %command.full_name%</info>
53585
53586 You can also display the commands for a specific namespace:
53587
53588   <info>php %command.full_name% test</info>
53589
53590 You can also output the information in other formats by using the <comment>--format</comment> option:
53591
53592   <info>php %command.full_name% --format=xml</info>
53593
53594 It's also possible to get raw list of commands (useful for embedding command runner):
53595
53596   <info>php %command.full_name% --raw</info>
53597 EOF
53598 )
53599 ;
53600 }
53601
53602
53603
53604
53605 public function getNativeDefinition()
53606 {
53607 return $this->createDefinition();
53608 }
53609
53610
53611
53612
53613 protected function execute(InputInterface $input, OutputInterface $output)
53614 {
53615 if ($input->getOption('xml')) {
53616 @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);
53617
53618 $input->setOption('format', 'xml');
53619 }
53620
53621 $helper = new DescriptorHelper();
53622 $helper->describe($output, $this->getApplication(), array(
53623 'format' => $input->getOption('format'),
53624 'raw_text' => $input->getOption('raw'),
53625 'namespace' => $input->getArgument('namespace'),
53626 ));
53627 }
53628
53629
53630
53631
53632 private function createDefinition()
53633 {
53634 return new InputDefinition(array(
53635 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
53636 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
53637 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
53638 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
53639 ));
53640 }
53641 }
53642 <?php
53643
53644
53645
53646
53647
53648
53649
53650
53651
53652
53653 namespace Symfony\Component\Console;
53654
53655
53656
53657
53658
53659
53660 final class ConsoleEvents
53661 {
53662
53663
53664
53665
53666
53667
53668
53669
53670
53671
53672 const COMMAND = 'console.command';
53673
53674
53675
53676
53677
53678
53679
53680
53681
53682
53683 const TERMINATE = 'console.terminate';
53684
53685
53686
53687
53688
53689
53690
53691
53692
53693
53694
53695 const EXCEPTION = 'console.exception';
53696 }
53697 <?php
53698
53699
53700
53701
53702
53703
53704
53705
53706
53707
53708 namespace Symfony\Component\Console\Descriptor;
53709
53710 use Symfony\Component\Console\Application;
53711 use Symfony\Component\Console\Command\Command;
53712 use Symfony\Component\Console\Exception\CommandNotFoundException;
53713
53714
53715
53716
53717
53718
53719 class ApplicationDescription
53720 {
53721 const GLOBAL_NAMESPACE = '_global';
53722
53723 private $application;
53724 private $namespace;
53725
53726
53727
53728
53729 private $namespaces;
53730
53731
53732
53733
53734 private $commands;
53735
53736
53737
53738
53739 private $aliases;
53740
53741 public function __construct(Application $application, $namespace = null)
53742 {
53743 $this->application = $application;
53744 $this->namespace = $namespace;
53745 }
53746
53747
53748
53749
53750 public function getNamespaces()
53751 {
53752 if (null === $this->namespaces) {
53753 $this->inspectApplication();
53754 }
53755
53756 return $this->namespaces;
53757 }
53758
53759
53760
53761
53762 public function getCommands()
53763 {
53764 if (null === $this->commands) {
53765 $this->inspectApplication();
53766 }
53767
53768 return $this->commands;
53769 }
53770
53771
53772
53773
53774
53775
53776
53777
53778 public function getCommand($name)
53779 {
53780 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
53781 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
53782 }
53783
53784 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
53785 }
53786
53787 private function inspectApplication()
53788 {
53789 $this->commands = array();
53790 $this->namespaces = array();
53791
53792 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
53793 foreach ($this->sortCommands($all) as $namespace => $commands) {
53794 $names = array();
53795
53796
53797 foreach ($commands as $name => $command) {
53798 if (!$command->getName()) {
53799 continue;
53800 }
53801
53802 if ($command->getName() === $name) {
53803 $this->commands[$name] = $command;
53804 } else {
53805 $this->aliases[$name] = $command;
53806 }
53807
53808 $names[] = $name;
53809 }
53810
53811 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
53812 }
53813 }
53814
53815
53816
53817
53818 private function sortCommands(array $commands)
53819 {
53820 $namespacedCommands = array();
53821 $globalCommands = array();
53822 foreach ($commands as $name => $command) {
53823 $key = $this->application->extractNamespace($name, 1);
53824 if (!$key) {
53825 $globalCommands['_global'][$name] = $command;
53826 } else {
53827 $namespacedCommands[$key][$name] = $command;
53828 }
53829 }
53830 ksort($namespacedCommands);
53831 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
53832
53833 foreach ($namespacedCommands as &$commandsSet) {
53834 ksort($commandsSet);
53835 }
53836
53837  unset($commandsSet);
53838
53839 return $namespacedCommands;
53840 }
53841 }
53842 <?php
53843
53844
53845
53846
53847
53848
53849
53850
53851
53852
53853 namespace Symfony\Component\Console\Descriptor;
53854
53855 use Symfony\Component\Console\Application;
53856 use Symfony\Component\Console\Command\Command;
53857 use Symfony\Component\Console\Exception\InvalidArgumentException;
53858 use Symfony\Component\Console\Input\InputArgument;
53859 use Symfony\Component\Console\Input\InputDefinition;
53860 use Symfony\Component\Console\Input\InputOption;
53861 use Symfony\Component\Console\Output\OutputInterface;
53862
53863
53864
53865
53866
53867
53868 abstract class Descriptor implements DescriptorInterface
53869 {
53870
53871
53872
53873 private $output;
53874
53875
53876
53877
53878 public function describe(OutputInterface $output, $object, array $options = array())
53879 {
53880 $this->output = $output;
53881
53882 switch (true) {
53883 case $object instanceof InputArgument:
53884 $this->describeInputArgument($object, $options);
53885 break;
53886 case $object instanceof InputOption:
53887 $this->describeInputOption($object, $options);
53888 break;
53889 case $object instanceof InputDefinition:
53890 $this->describeInputDefinition($object, $options);
53891 break;
53892 case $object instanceof Command:
53893 $this->describeCommand($object, $options);
53894 break;
53895 case $object instanceof Application:
53896 $this->describeApplication($object, $options);
53897 break;
53898 default:
53899 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object)));
53900 }
53901 }
53902
53903
53904
53905
53906
53907
53908
53909 protected function write($content, $decorated = false)
53910 {
53911 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
53912 }
53913
53914
53915
53916
53917
53918
53919 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
53920
53921
53922
53923
53924
53925
53926 abstract protected function describeInputOption(InputOption $option, array $options = array());
53927
53928
53929
53930
53931
53932
53933 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
53934
53935
53936
53937
53938
53939
53940 abstract protected function describeCommand(Command $command, array $options = array());
53941
53942
53943
53944
53945
53946
53947 abstract protected function describeApplication(Application $application, array $options = array());
53948 }
53949 <?php
53950
53951
53952
53953
53954
53955
53956
53957
53958
53959
53960 namespace Symfony\Component\Console\Descriptor;
53961
53962 use Symfony\Component\Console\Output\OutputInterface;
53963
53964
53965
53966
53967
53968
53969 interface DescriptorInterface
53970 {
53971
53972
53973
53974
53975
53976
53977
53978 public function describe(OutputInterface $output, $object, array $options = array());
53979 }
53980 <?php
53981
53982
53983
53984
53985
53986
53987
53988
53989
53990
53991 namespace Symfony\Component\Console\Descriptor;
53992
53993 use Symfony\Component\Console\Application;
53994 use Symfony\Component\Console\Command\Command;
53995 use Symfony\Component\Console\Input\InputArgument;
53996 use Symfony\Component\Console\Input\InputDefinition;
53997 use Symfony\Component\Console\Input\InputOption;
53998
53999
54000
54001
54002
54003
54004
54005
54006 class JsonDescriptor extends Descriptor
54007 {
54008
54009
54010
54011 protected function describeInputArgument(InputArgument $argument, array $options = array())
54012 {
54013 $this->writeData($this->getInputArgumentData($argument), $options);
54014 }
54015
54016
54017
54018
54019 protected function describeInputOption(InputOption $option, array $options = array())
54020 {
54021 $this->writeData($this->getInputOptionData($option), $options);
54022 }
54023
54024
54025
54026
54027 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
54028 {
54029 $this->writeData($this->getInputDefinitionData($definition), $options);
54030 }
54031
54032
54033
54034
54035 protected function describeCommand(Command $command, array $options = array())
54036 {
54037 $this->writeData($this->getCommandData($command), $options);
54038 }
54039
54040
54041
54042
54043 protected function describeApplication(Application $application, array $options = array())
54044 {
54045 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
54046 $description = new ApplicationDescription($application, $describedNamespace);
54047 $commands = array();
54048
54049 foreach ($description->getCommands() as $command) {
54050 $commands[] = $this->getCommandData($command);
54051 }
54052
54053 $data = $describedNamespace
54054 ? array('commands' => $commands, 'namespace' => $describedNamespace)
54055 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
54056
54057 $this->writeData($data, $options);
54058 }
54059
54060
54061
54062
54063
54064
54065 private function writeData(array $data, array $options)
54066 {
54067 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
54068 }
54069
54070
54071
54072
54073 private function getInputArgumentData(InputArgument $argument)
54074 {
54075 return array(
54076 'name' => $argument->getName(),
54077 'is_required' => $argument->isRequired(),
54078 'is_array' => $argument->isArray(),
54079 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
54080 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
54081 );
54082 }
54083
54084
54085
54086
54087 private function getInputOptionData(InputOption $option)
54088 {
54089 return array(
54090 'name' => '--'.$option->getName(),
54091 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
54092 'accept_value' => $option->acceptValue(),
54093 'is_value_required' => $option->isValueRequired(),
54094 'is_multiple' => $option->isArray(),
54095 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
54096 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
54097 );
54098 }
54099
54100
54101
54102
54103 private function getInputDefinitionData(InputDefinition $definition)
54104 {
54105 $inputArguments = array();
54106 foreach ($definition->getArguments() as $name => $argument) {
54107 $inputArguments[$name] = $this->getInputArgumentData($argument);
54108 }
54109
54110 $inputOptions = array();
54111 foreach ($definition->getOptions() as $name => $option) {
54112 $inputOptions[$name] = $this->getInputOptionData($option);
54113 }
54114
54115 return array('arguments' => $inputArguments, 'options' => $inputOptions);
54116 }
54117
54118
54119
54120
54121 private function getCommandData(Command $command)
54122 {
54123 $command->getSynopsis();
54124 $command->mergeApplicationDefinition(false);
54125
54126 return array(
54127 'name' => $command->getName(),
54128 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
54129 'description' => $command->getDescription(),
54130 'help' => $command->getProcessedHelp(),
54131 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
54132 );
54133 }
54134 }
54135 <?php
54136
54137
54138
54139
54140
54141
54142
54143
54144
54145
54146 namespace Symfony\Component\Console\Descriptor;
54147
54148 use Symfony\Component\Console\Application;
54149 use Symfony\Component\Console\Command\Command;
54150 use Symfony\Component\Console\Helper\Helper;
54151 use Symfony\Component\Console\Input\InputArgument;
54152 use Symfony\Component\Console\Input\InputDefinition;
54153 use Symfony\Component\Console\Input\InputOption;
54154
54155
54156
54157
54158
54159
54160
54161
54162 class MarkdownDescriptor extends Descriptor
54163 {
54164
54165
54166
54167 protected function describeInputArgument(InputArgument $argument, array $options = array())
54168 {
54169 $this->write(
54170 '**'.$argument->getName().':**'."\n\n"
54171 .'* Name: '.($argument->getName() ?: '<none>')."\n"
54172 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
54173 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
54174 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
54175 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
54176 );
54177 }
54178
54179
54180
54181
54182 protected function describeInputOption(InputOption $option, array $options = array())
54183 {
54184 $this->write(
54185 '**'.$option->getName().':**'."\n\n"
54186 .'* Name: `--'.$option->getName().'`'."\n"
54187 .'* Shortcut: '.($option->getShortcut() ? '`-'.str_replace('|', '|-', $option->getShortcut()).'`' : '<none>')."\n"
54188 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
54189 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
54190 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
54191 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
54192 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
54193 );
54194 }
54195
54196
54197
54198
54199 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
54200 {
54201 if ($showArguments = \count($definition->getArguments()) > 0) {
54202 $this->write('### Arguments:');
54203 foreach ($definition->getArguments() as $argument) {
54204 $this->write("\n\n");
54205 $this->write($this->describeInputArgument($argument));
54206 }
54207 }
54208
54209 if (\count($definition->getOptions()) > 0) {
54210 if ($showArguments) {
54211 $this->write("\n\n");
54212 }
54213
54214 $this->write('### Options:');
54215 foreach ($definition->getOptions() as $option) {
54216 $this->write("\n\n");
54217 $this->write($this->describeInputOption($option));
54218 }
54219 }
54220 }
54221
54222
54223
54224
54225 protected function describeCommand(Command $command, array $options = array())
54226 {
54227 $command->getSynopsis();
54228 $command->mergeApplicationDefinition(false);
54229
54230 $this->write(
54231 $command->getName()."\n"
54232 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
54233 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
54234 .'* Usage:'."\n\n"
54235 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
54236 return $carry.'  * `'.$usage.'`'."\n";
54237 })
54238 );
54239
54240 if ($help = $command->getProcessedHelp()) {
54241 $this->write("\n");
54242 $this->write($help);
54243 }
54244
54245 if ($command->getNativeDefinition()) {
54246 $this->write("\n\n");
54247 $this->describeInputDefinition($command->getNativeDefinition());
54248 }
54249 }
54250
54251
54252
54253
54254 protected function describeApplication(Application $application, array $options = array())
54255 {
54256 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
54257 $description = new ApplicationDescription($application, $describedNamespace);
54258
54259 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
54260
54261 foreach ($description->getNamespaces() as $namespace) {
54262 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
54263 $this->write("\n\n");
54264 $this->write('**'.$namespace['id'].':**');
54265 }
54266
54267 $this->write("\n\n");
54268 $this->write(implode("\n", array_map(function ($commandName) {
54269 return '* '.$commandName;
54270 }, $namespace['commands'])));
54271 }
54272
54273 foreach ($description->getCommands() as $command) {
54274 $this->write("\n\n");
54275 $this->write($this->describeCommand($command));
54276 }
54277 }
54278 }
54279 <?php
54280
54281
54282
54283
54284
54285
54286
54287
54288
54289
54290 namespace Symfony\Component\Console\Descriptor;
54291
54292 use Symfony\Component\Console\Application;
54293 use Symfony\Component\Console\Command\Command;
54294 use Symfony\Component\Console\Formatter\OutputFormatter;
54295 use Symfony\Component\Console\Helper\Helper;
54296 use Symfony\Component\Console\Input\InputArgument;
54297 use Symfony\Component\Console\Input\InputDefinition;
54298 use Symfony\Component\Console\Input\InputOption;
54299
54300
54301
54302
54303
54304
54305
54306
54307 class TextDescriptor extends Descriptor
54308 {
54309
54310
54311
54312 protected function describeInputArgument(InputArgument $argument, array $options = array())
54313 {
54314 if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
54315 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
54316 } else {
54317 $default = '';
54318 }
54319
54320 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
54321 $spacingWidth = $totalWidth - \strlen($argument->getName());
54322
54323 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
54324 $argument->getName(),
54325 str_repeat(' ', $spacingWidth),
54326
54327  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
54328 $default
54329 ), $options);
54330 }
54331
54332
54333
54334
54335 protected function describeInputOption(InputOption $option, array $options = array())
54336 {
54337 if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
54338 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
54339 } else {
54340 $default = '';
54341 }
54342
54343 $value = '';
54344 if ($option->acceptValue()) {
54345 $value = '='.strtoupper($option->getName());
54346
54347 if ($option->isValueOptional()) {
54348 $value = '['.$value.']';
54349 }
54350 }
54351
54352 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
54353 $synopsis = sprintf('%s%s',
54354 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
54355 sprintf('--%s%s', $option->getName(), $value)
54356 );
54357
54358 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
54359
54360 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
54361 $synopsis,
54362 str_repeat(' ', $spacingWidth),
54363
54364  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
54365 $default,
54366 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
54367 ), $options);
54368 }
54369
54370
54371
54372
54373 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
54374 {
54375 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
54376 foreach ($definition->getArguments() as $argument) {
54377 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
54378 }
54379
54380 if ($definition->getArguments()) {
54381 $this->writeText('<comment>Arguments:</comment>', $options);
54382 $this->writeText("\n");
54383 foreach ($definition->getArguments() as $argument) {
54384 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
54385 $this->writeText("\n");
54386 }
54387 }
54388
54389 if ($definition->getArguments() && $definition->getOptions()) {
54390 $this->writeText("\n");
54391 }
54392
54393 if ($definition->getOptions()) {
54394 $laterOptions = array();
54395
54396 $this->writeText('<comment>Options:</comment>', $options);
54397 foreach ($definition->getOptions() as $option) {
54398 if (\strlen($option->getShortcut()) > 1) {
54399 $laterOptions[] = $option;
54400 continue;
54401 }
54402 $this->writeText("\n");
54403 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
54404 }
54405 foreach ($laterOptions as $option) {
54406 $this->writeText("\n");
54407 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
54408 }
54409 }
54410 }
54411
54412
54413
54414
54415 protected function describeCommand(Command $command, array $options = array())
54416 {
54417 $command->getSynopsis(true);
54418 $command->getSynopsis(false);
54419 $command->mergeApplicationDefinition(false);
54420
54421 $this->writeText('<comment>Usage:</comment>', $options);
54422 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
54423 $this->writeText("\n");
54424 $this->writeText('  '.OutputFormatter::escape($usage), $options);
54425 }
54426 $this->writeText("\n");
54427
54428 $definition = $command->getNativeDefinition();
54429 if ($definition->getOptions() || $definition->getArguments()) {
54430 $this->writeText("\n");
54431 $this->describeInputDefinition($definition, $options);
54432 $this->writeText("\n");
54433 }
54434
54435 if ($help = $command->getProcessedHelp()) {
54436 $this->writeText("\n");
54437 $this->writeText('<comment>Help:</comment>', $options);
54438 $this->writeText("\n");
54439 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
54440 $this->writeText("\n");
54441 }
54442 }
54443
54444
54445
54446
54447 protected function describeApplication(Application $application, array $options = array())
54448 {
54449 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
54450 $description = new ApplicationDescription($application, $describedNamespace);
54451
54452 if (isset($options['raw_text']) && $options['raw_text']) {
54453 $width = $this->getColumnWidth($description->getCommands());
54454
54455 foreach ($description->getCommands() as $command) {
54456 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
54457 $this->writeText("\n");
54458 }
54459 } else {
54460 if ('' != $help = $application->getHelp()) {
54461 $this->writeText("$help\n\n", $options);
54462 }
54463
54464 $this->writeText("<comment>Usage:</comment>\n", $options);
54465 $this->writeText("  command [options] [arguments]\n\n", $options);
54466
54467 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
54468
54469 $this->writeText("\n");
54470 $this->writeText("\n");
54471
54472 $width = $this->getColumnWidth($description->getCommands());
54473
54474 if ($describedNamespace) {
54475 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
54476 } else {
54477 $this->writeText('<comment>Available commands:</comment>', $options);
54478 }
54479
54480
54481  foreach ($description->getNamespaces() as $namespace) {
54482 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
54483 $this->writeText("\n");
54484 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
54485 }
54486
54487 foreach ($namespace['commands'] as $name) {
54488 $this->writeText("\n");
54489 $spacingWidth = $width - Helper::strlen($name);
54490 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
54491 }
54492 }
54493
54494 $this->writeText("\n");
54495 }
54496 }
54497
54498
54499
54500
54501 private function writeText($content, array $options = array())
54502 {
54503 $this->write(
54504 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
54505 isset($options['raw_output']) ? !$options['raw_output'] : true
54506 );
54507 }
54508
54509
54510
54511
54512
54513
54514
54515
54516 private function formatDefaultValue($default)
54517 {
54518 if (INF === $default) {
54519 return 'INF';
54520 }
54521
54522 if (\is_string($default)) {
54523 $default = OutputFormatter::escape($default);
54524 } elseif (\is_array($default)) {
54525 foreach ($default as $key => $value) {
54526 if (\is_string($value)) {
54527 $default[$key] = OutputFormatter::escape($value);
54528 }
54529 }
54530 }
54531
54532 if (\PHP_VERSION_ID < 50400) {
54533 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
54534 }
54535
54536 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
54537 }
54538
54539
54540
54541
54542
54543
54544 private function getColumnWidth(array $commands)
54545 {
54546 $widths = array();
54547
54548 foreach ($commands as $command) {
54549 $widths[] = Helper::strlen($command->getName());
54550 foreach ($command->getAliases() as $alias) {
54551 $widths[] = Helper::strlen($alias);
54552 }
54553 }
54554
54555 return max($widths) + 2;
54556 }
54557
54558
54559
54560
54561
54562
54563 private function calculateTotalWidthForOptions(array $options)
54564 {
54565 $totalWidth = 0;
54566 foreach ($options as $option) {
54567
54568  $nameLength = 1 + max(\strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
54569
54570 if ($option->acceptValue()) {
54571 $valueLength = 1 + Helper::strlen($option->getName()); 
54572  $valueLength += $option->isValueOptional() ? 2 : 0; 
54573
54574 $nameLength += $valueLength;
54575 }
54576 $totalWidth = max($totalWidth, $nameLength);
54577 }
54578
54579 return $totalWidth;
54580 }
54581 }
54582 <?php
54583
54584
54585
54586
54587
54588
54589
54590
54591
54592
54593 namespace Symfony\Component\Console\Descriptor;
54594
54595 use Symfony\Component\Console\Application;
54596 use Symfony\Component\Console\Command\Command;
54597 use Symfony\Component\Console\Input\InputArgument;
54598 use Symfony\Component\Console\Input\InputDefinition;
54599 use Symfony\Component\Console\Input\InputOption;
54600
54601
54602
54603
54604
54605
54606
54607
54608 class XmlDescriptor extends Descriptor
54609 {
54610
54611
54612
54613 public function getInputDefinitionDocument(InputDefinition $definition)
54614 {
54615 $dom = new \DOMDocument('1.0', 'UTF-8');
54616 $dom->appendChild($definitionXML = $dom->createElement('definition'));
54617
54618 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
54619 foreach ($definition->getArguments() as $argument) {
54620 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
54621 }
54622
54623 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
54624 foreach ($definition->getOptions() as $option) {
54625 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
54626 }
54627
54628 return $dom;
54629 }
54630
54631
54632
54633
54634 public function getCommandDocument(Command $command)
54635 {
54636 $dom = new \DOMDocument('1.0', 'UTF-8');
54637 $dom->appendChild($commandXML = $dom->createElement('command'));
54638
54639 $command->getSynopsis();
54640 $command->mergeApplicationDefinition(false);
54641
54642 $commandXML->setAttribute('id', $command->getName());
54643 $commandXML->setAttribute('name', $command->getName());
54644
54645 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
54646
54647 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
54648 $usagesXML->appendChild($dom->createElement('usage', $usage));
54649 }
54650
54651 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
54652 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
54653
54654 $commandXML->appendChild($helpXML = $dom->createElement('help'));
54655 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
54656
54657 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
54658 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
54659
54660 return $dom;
54661 }
54662
54663
54664
54665
54666
54667
54668
54669 public function getApplicationDocument(Application $application, $namespace = null)
54670 {
54671 $dom = new \DOMDocument('1.0', 'UTF-8');
54672 $dom->appendChild($rootXml = $dom->createElement('symfony'));
54673
54674 if ('UNKNOWN' !== $application->getName()) {
54675 $rootXml->setAttribute('name', $application->getName());
54676 if ('UNKNOWN' !== $application->getVersion()) {
54677 $rootXml->setAttribute('version', $application->getVersion());
54678 }
54679 }
54680
54681 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
54682
54683 $description = new ApplicationDescription($application, $namespace);
54684
54685 if ($namespace) {
54686 $commandsXML->setAttribute('namespace', $namespace);
54687 }
54688
54689 foreach ($description->getCommands() as $command) {
54690 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
54691 }
54692
54693 if (!$namespace) {
54694 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
54695
54696 foreach ($description->getNamespaces() as $namespaceDescription) {
54697 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
54698 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
54699
54700 foreach ($namespaceDescription['commands'] as $name) {
54701 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
54702 $commandXML->appendChild($dom->createTextNode($name));
54703 }
54704 }
54705 }
54706
54707 return $dom;
54708 }
54709
54710
54711
54712
54713 protected function describeInputArgument(InputArgument $argument, array $options = array())
54714 {
54715 $this->writeDocument($this->getInputArgumentDocument($argument));
54716 }
54717
54718
54719
54720
54721 protected function describeInputOption(InputOption $option, array $options = array())
54722 {
54723 $this->writeDocument($this->getInputOptionDocument($option));
54724 }
54725
54726
54727
54728
54729 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
54730 {
54731 $this->writeDocument($this->getInputDefinitionDocument($definition));
54732 }
54733
54734
54735
54736
54737 protected function describeCommand(Command $command, array $options = array())
54738 {
54739 $this->writeDocument($this->getCommandDocument($command));
54740 }
54741
54742
54743
54744
54745 protected function describeApplication(Application $application, array $options = array())
54746 {
54747 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
54748 }
54749
54750
54751
54752
54753 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
54754 {
54755 foreach ($importedParent->childNodes as $childNode) {
54756 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
54757 }
54758 }
54759
54760
54761
54762
54763
54764
54765 private function writeDocument(\DOMDocument $dom)
54766 {
54767 $dom->formatOutput = true;
54768 $this->write($dom->saveXML());
54769 }
54770
54771
54772
54773
54774 private function getInputArgumentDocument(InputArgument $argument)
54775 {
54776 $dom = new \DOMDocument('1.0', 'UTF-8');
54777
54778 $dom->appendChild($objectXML = $dom->createElement('argument'));
54779 $objectXML->setAttribute('name', $argument->getName());
54780 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
54781 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
54782 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
54783 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
54784
54785 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
54786 $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
54787 foreach ($defaults as $default) {
54788 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
54789 $defaultXML->appendChild($dom->createTextNode($default));
54790 }
54791
54792 return $dom;
54793 }
54794
54795
54796
54797
54798 private function getInputOptionDocument(InputOption $option)
54799 {
54800 $dom = new \DOMDocument('1.0', 'UTF-8');
54801
54802 $dom->appendChild($objectXML = $dom->createElement('option'));
54803 $objectXML->setAttribute('name', '--'.$option->getName());
54804 $pos = strpos($option->getShortcut(), '|');
54805 if (false !== $pos) {
54806 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
54807 $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
54808 } else {
54809 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
54810 }
54811 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
54812 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
54813 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
54814 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
54815 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
54816
54817 if ($option->acceptValue()) {
54818 $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
54819 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
54820
54821 if (!empty($defaults)) {
54822 foreach ($defaults as $default) {
54823 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
54824 $defaultXML->appendChild($dom->createTextNode($default));
54825 }
54826 }
54827 }
54828
54829 return $dom;
54830 }
54831 }
54832 <?php
54833
54834
54835
54836
54837
54838
54839
54840
54841
54842
54843 namespace Symfony\Component\Console\Event;
54844
54845
54846
54847
54848
54849
54850 class ConsoleCommandEvent extends ConsoleEvent
54851 {
54852
54853
54854
54855 const RETURN_CODE_DISABLED = 113;
54856
54857
54858
54859
54860 private $commandShouldRun = true;
54861
54862
54863
54864
54865
54866
54867 public function disableCommand()
54868 {
54869 return $this->commandShouldRun = false;
54870 }
54871
54872
54873
54874
54875
54876
54877 public function enableCommand()
54878 {
54879 return $this->commandShouldRun = true;
54880 }
54881
54882
54883
54884
54885
54886
54887 public function commandShouldRun()
54888 {
54889 return $this->commandShouldRun;
54890 }
54891 }
54892 <?php
54893
54894
54895
54896
54897
54898
54899
54900
54901
54902
54903 namespace Symfony\Component\Console\Event;
54904
54905 use Symfony\Component\Console\Command\Command;
54906 use Symfony\Component\Console\Input\InputInterface;
54907 use Symfony\Component\Console\Output\OutputInterface;
54908 use Symfony\Component\EventDispatcher\Event;
54909
54910
54911
54912
54913
54914
54915 class ConsoleEvent extends Event
54916 {
54917 protected $command;
54918
54919 private $input;
54920 private $output;
54921
54922 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
54923 {
54924 $this->command = $command;
54925 $this->input = $input;
54926 $this->output = $output;
54927 }
54928
54929
54930
54931
54932
54933
54934 public function getCommand()
54935 {
54936 return $this->command;
54937 }
54938
54939
54940
54941
54942
54943
54944 public function getInput()
54945 {
54946 return $this->input;
54947 }
54948
54949
54950
54951
54952
54953
54954 public function getOutput()
54955 {
54956 return $this->output;
54957 }
54958 }
54959 <?php
54960
54961
54962
54963
54964
54965
54966
54967
54968
54969
54970 namespace Symfony\Component\Console\Event;
54971
54972 use Symfony\Component\Console\Command\Command;
54973 use Symfony\Component\Console\Input\InputInterface;
54974 use Symfony\Component\Console\Output\OutputInterface;
54975
54976
54977
54978
54979
54980
54981 class ConsoleExceptionEvent extends ConsoleEvent
54982 {
54983 private $exception;
54984 private $exitCode;
54985
54986 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
54987 {
54988 parent::__construct($command, $input, $output);
54989
54990 $this->setException($exception);
54991 $this->exitCode = (int) $exitCode;
54992 }
54993
54994
54995
54996
54997
54998
54999 public function getException()
55000 {
55001 return $this->exception;
55002 }
55003
55004
55005
55006
55007
55008
55009
55010
55011 public function setException(\Exception $exception)
55012 {
55013 $this->exception = $exception;
55014 }
55015
55016
55017
55018
55019
55020
55021 public function getExitCode()
55022 {
55023 return $this->exitCode;
55024 }
55025 }
55026 <?php
55027
55028
55029
55030
55031
55032
55033
55034
55035
55036
55037 namespace Symfony\Component\Console\Event;
55038
55039 use Symfony\Component\Console\Command\Command;
55040 use Symfony\Component\Console\Input\InputInterface;
55041 use Symfony\Component\Console\Output\OutputInterface;
55042
55043
55044
55045
55046
55047
55048 class ConsoleTerminateEvent extends ConsoleEvent
55049 {
55050
55051
55052
55053
55054
55055 private $exitCode;
55056
55057 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
55058 {
55059 parent::__construct($command, $input, $output);
55060
55061 $this->setExitCode($exitCode);
55062 }
55063
55064
55065
55066
55067
55068
55069 public function setExitCode($exitCode)
55070 {
55071 $this->exitCode = (int) $exitCode;
55072 }
55073
55074
55075
55076
55077
55078
55079 public function getExitCode()
55080 {
55081 return $this->exitCode;
55082 }
55083 }
55084 <?php
55085
55086
55087
55088
55089
55090
55091
55092
55093
55094
55095 namespace Symfony\Component\Console\Exception;
55096
55097
55098
55099
55100
55101
55102 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
55103 {
55104 private $alternatives;
55105
55106
55107
55108
55109
55110
55111
55112 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
55113 {
55114 parent::__construct($message, $code, $previous);
55115
55116 $this->alternatives = $alternatives;
55117 }
55118
55119
55120
55121
55122 public function getAlternatives()
55123 {
55124 return $this->alternatives;
55125 }
55126 }
55127 <?php
55128
55129
55130
55131
55132
55133
55134
55135
55136
55137
55138 namespace Symfony\Component\Console\Exception;
55139
55140
55141
55142
55143
55144
55145 interface ExceptionInterface
55146 {
55147 }
55148 <?php
55149
55150
55151
55152
55153
55154
55155
55156
55157
55158
55159 namespace Symfony\Component\Console\Exception;
55160
55161
55162
55163
55164 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
55165 {
55166 }
55167 <?php
55168
55169
55170
55171
55172
55173
55174
55175
55176
55177
55178 namespace Symfony\Component\Console\Exception;
55179
55180
55181
55182
55183
55184
55185 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
55186 {
55187 }
55188 <?php
55189
55190
55191
55192
55193
55194
55195
55196
55197
55198
55199 namespace Symfony\Component\Console\Exception;
55200
55201
55202
55203
55204 class LogicException extends \LogicException implements ExceptionInterface
55205 {
55206 }
55207 <?php
55208
55209
55210
55211
55212
55213
55214
55215
55216
55217
55218 namespace Symfony\Component\Console\Exception;
55219
55220
55221
55222
55223 class RuntimeException extends \RuntimeException implements ExceptionInterface
55224 {
55225 }
55226 <?php
55227
55228
55229
55230
55231
55232
55233
55234
55235
55236
55237 namespace Symfony\Component\Console\Formatter;
55238
55239 use Symfony\Component\Console\Exception\InvalidArgumentException;
55240
55241
55242
55243
55244
55245
55246 class OutputFormatter implements OutputFormatterInterface
55247 {
55248 private $decorated;
55249 private $styles = array();
55250 private $styleStack;
55251
55252
55253
55254
55255
55256
55257
55258
55259 public static function escape($text)
55260 {
55261 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
55262
55263 return self::escapeTrailingBackslash($text);
55264 }
55265
55266
55267
55268
55269
55270
55271
55272
55273
55274
55275 public static function escapeTrailingBackslash($text)
55276 {
55277 if ('\\' === substr($text, -1)) {
55278 $len = \strlen($text);
55279 $text = rtrim($text, '\\');
55280 $text = str_replace("\0", '', $text);
55281 $text .= str_repeat("\0", $len - \strlen($text));
55282 }
55283
55284 return $text;
55285 }
55286
55287
55288
55289
55290
55291
55292
55293 public function __construct($decorated = false, array $styles = array())
55294 {
55295 $this->decorated = (bool) $decorated;
55296
55297 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
55298 $this->setStyle('info', new OutputFormatterStyle('green'));
55299 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
55300 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
55301
55302 foreach ($styles as $name => $style) {
55303 $this->setStyle($name, $style);
55304 }
55305
55306 $this->styleStack = new OutputFormatterStyleStack();
55307 }
55308
55309
55310
55311
55312 public function setDecorated($decorated)
55313 {
55314 $this->decorated = (bool) $decorated;
55315 }
55316
55317
55318
55319
55320 public function isDecorated()
55321 {
55322 return $this->decorated;
55323 }
55324
55325
55326
55327
55328 public function setStyle($name, OutputFormatterStyleInterface $style)
55329 {
55330 $this->styles[strtolower($name)] = $style;
55331 }
55332
55333
55334
55335
55336 public function hasStyle($name)
55337 {
55338 return isset($this->styles[strtolower($name)]);
55339 }
55340
55341
55342
55343
55344 public function getStyle($name)
55345 {
55346 if (!$this->hasStyle($name)) {
55347 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
55348 }
55349
55350 return $this->styles[strtolower($name)];
55351 }
55352
55353
55354
55355
55356 public function format($message)
55357 {
55358 $message = (string) $message;
55359 $offset = 0;
55360 $output = '';
55361 $tagRegex = '[a-z][a-z0-9_=;-]*+';
55362 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
55363 foreach ($matches[0] as $i => $match) {
55364 $pos = $match[1];
55365 $text = $match[0];
55366
55367 if (0 != $pos && '\\' == $message[$pos - 1]) {
55368 continue;
55369 }
55370
55371
55372  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
55373 $offset = $pos + \strlen($text);
55374
55375
55376  if ($open = '/' != $text[1]) {
55377 $tag = $matches[1][$i][0];
55378 } else {
55379 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
55380 }
55381
55382 if (!$open && !$tag) {
55383
55384  $this->styleStack->pop();
55385 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
55386 $output .= $this->applyCurrentStyle($text);
55387 } elseif ($open) {
55388 $this->styleStack->push($style);
55389 } else {
55390 $this->styleStack->pop($style);
55391 }
55392 }
55393
55394 $output .= $this->applyCurrentStyle(substr($message, $offset));
55395
55396 if (false !== strpos($output, "\0")) {
55397 return strtr($output, array("\0" => '\\', '\\<' => '<'));
55398 }
55399
55400 return str_replace('\\<', '<', $output);
55401 }
55402
55403
55404
55405
55406 public function getStyleStack()
55407 {
55408 return $this->styleStack;
55409 }
55410
55411
55412
55413
55414
55415
55416
55417
55418 private function createStyleFromString($string)
55419 {
55420 if (isset($this->styles[$string])) {
55421 return $this->styles[$string];
55422 }
55423
55424 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
55425 return false;
55426 }
55427
55428 $style = new OutputFormatterStyle();
55429 foreach ($matches as $match) {
55430 array_shift($match);
55431
55432 if ('fg' == $match[0]) {
55433 $style->setForeground($match[1]);
55434 } elseif ('bg' == $match[0]) {
55435 $style->setBackground($match[1]);
55436 } else {
55437 try {
55438 $style->setOption($match[1]);
55439 } catch (\InvalidArgumentException $e) {
55440 return false;
55441 }
55442 }
55443 }
55444
55445 return $style;
55446 }
55447
55448
55449
55450
55451
55452
55453
55454
55455 private function applyCurrentStyle($text)
55456 {
55457 return $this->isDecorated() && \strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
55458 }
55459 }
55460 <?php
55461
55462
55463
55464
55465
55466
55467
55468
55469
55470
55471 namespace Symfony\Component\Console\Formatter;
55472
55473
55474
55475
55476
55477
55478 interface OutputFormatterInterface
55479 {
55480
55481
55482
55483
55484
55485 public function setDecorated($decorated);
55486
55487
55488
55489
55490
55491
55492 public function isDecorated();
55493
55494
55495
55496
55497
55498
55499
55500 public function setStyle($name, OutputFormatterStyleInterface $style);
55501
55502
55503
55504
55505
55506
55507
55508
55509 public function hasStyle($name);
55510
55511
55512
55513
55514
55515
55516
55517
55518
55519
55520 public function getStyle($name);
55521
55522
55523
55524
55525
55526
55527
55528
55529 public function format($message);
55530 }
55531 <?php
55532
55533
55534
55535
55536
55537
55538
55539
55540
55541
55542 namespace Symfony\Component\Console\Formatter;
55543
55544 use Symfony\Component\Console\Exception\InvalidArgumentException;
55545
55546
55547
55548
55549
55550
55551 class OutputFormatterStyle implements OutputFormatterStyleInterface
55552 {
55553 private static $availableForegroundColors = array(
55554 'black' => array('set' => 30, 'unset' => 39),
55555 'red' => array('set' => 31, 'unset' => 39),
55556 'green' => array('set' => 32, 'unset' => 39),
55557 'yellow' => array('set' => 33, 'unset' => 39),
55558 'blue' => array('set' => 34, 'unset' => 39),
55559 'magenta' => array('set' => 35, 'unset' => 39),
55560 'cyan' => array('set' => 36, 'unset' => 39),
55561 'white' => array('set' => 37, 'unset' => 39),
55562 'default' => array('set' => 39, 'unset' => 39),
55563 );
55564 private static $availableBackgroundColors = array(
55565 'black' => array('set' => 40, 'unset' => 49),
55566 'red' => array('set' => 41, 'unset' => 49),
55567 'green' => array('set' => 42, 'unset' => 49),
55568 'yellow' => array('set' => 43, 'unset' => 49),
55569 'blue' => array('set' => 44, 'unset' => 49),
55570 'magenta' => array('set' => 45, 'unset' => 49),
55571 'cyan' => array('set' => 46, 'unset' => 49),
55572 'white' => array('set' => 47, 'unset' => 49),
55573 'default' => array('set' => 49, 'unset' => 49),
55574 );
55575 private static $availableOptions = array(
55576 'bold' => array('set' => 1, 'unset' => 22),
55577 'underscore' => array('set' => 4, 'unset' => 24),
55578 'blink' => array('set' => 5, 'unset' => 25),
55579 'reverse' => array('set' => 7, 'unset' => 27),
55580 'conceal' => array('set' => 8, 'unset' => 28),
55581 );
55582
55583 private $foreground;
55584 private $background;
55585 private $options = array();
55586
55587
55588
55589
55590
55591
55592
55593
55594 public function __construct($foreground = null, $background = null, array $options = array())
55595 {
55596 if (null !== $foreground) {
55597 $this->setForeground($foreground);
55598 }
55599 if (null !== $background) {
55600 $this->setBackground($background);
55601 }
55602 if (\count($options)) {
55603 $this->setOptions($options);
55604 }
55605 }
55606
55607
55608
55609
55610
55611
55612
55613
55614 public function setForeground($color = null)
55615 {
55616 if (null === $color) {
55617 $this->foreground = null;
55618
55619 return;
55620 }
55621
55622 if (!isset(static::$availableForegroundColors[$color])) {
55623 throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors))));
55624 }
55625
55626 $this->foreground = static::$availableForegroundColors[$color];
55627 }
55628
55629
55630
55631
55632
55633
55634
55635
55636 public function setBackground($color = null)
55637 {
55638 if (null === $color) {
55639 $this->background = null;
55640
55641 return;
55642 }
55643
55644 if (!isset(static::$availableBackgroundColors[$color])) {
55645 throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors))));
55646 }
55647
55648 $this->background = static::$availableBackgroundColors[$color];
55649 }
55650
55651
55652
55653
55654
55655
55656
55657
55658 public function setOption($option)
55659 {
55660 if (!isset(static::$availableOptions[$option])) {
55661 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
55662 }
55663
55664 if (!\in_array(static::$availableOptions[$option], $this->options)) {
55665 $this->options[] = static::$availableOptions[$option];
55666 }
55667 }
55668
55669
55670
55671
55672
55673
55674
55675
55676 public function unsetOption($option)
55677 {
55678 if (!isset(static::$availableOptions[$option])) {
55679 throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions))));
55680 }
55681
55682 $pos = array_search(static::$availableOptions[$option], $this->options);
55683 if (false !== $pos) {
55684 unset($this->options[$pos]);
55685 }
55686 }
55687
55688
55689
55690
55691 public function setOptions(array $options)
55692 {
55693 $this->options = array();
55694
55695 foreach ($options as $option) {
55696 $this->setOption($option);
55697 }
55698 }
55699
55700
55701
55702
55703
55704
55705
55706
55707 public function apply($text)
55708 {
55709 $setCodes = array();
55710 $unsetCodes = array();
55711
55712 if (null !== $this->foreground) {
55713 $setCodes[] = $this->foreground['set'];
55714 $unsetCodes[] = $this->foreground['unset'];
55715 }
55716 if (null !== $this->background) {
55717 $setCodes[] = $this->background['set'];
55718 $unsetCodes[] = $this->background['unset'];
55719 }
55720 if (\count($this->options)) {
55721 foreach ($this->options as $option) {
55722 $setCodes[] = $option['set'];
55723 $unsetCodes[] = $option['unset'];
55724 }
55725 }
55726
55727 if (0 === \count($setCodes)) {
55728 return $text;
55729 }
55730
55731 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
55732 }
55733 }
55734 <?php
55735
55736
55737
55738
55739
55740
55741
55742
55743
55744
55745 namespace Symfony\Component\Console\Formatter;
55746
55747
55748
55749
55750
55751
55752 interface OutputFormatterStyleInterface
55753 {
55754
55755
55756
55757
55758
55759 public function setForeground($color = null);
55760
55761
55762
55763
55764
55765
55766 public function setBackground($color = null);
55767
55768
55769
55770
55771
55772
55773 public function setOption($option);
55774
55775
55776
55777
55778
55779
55780 public function unsetOption($option);
55781
55782
55783
55784
55785 public function setOptions(array $options);
55786
55787
55788
55789
55790
55791
55792
55793
55794 public function apply($text);
55795 }
55796 <?php
55797
55798
55799
55800
55801
55802
55803
55804
55805
55806
55807 namespace Symfony\Component\Console\Formatter;
55808
55809 use Symfony\Component\Console\Exception\InvalidArgumentException;
55810
55811
55812
55813
55814 class OutputFormatterStyleStack
55815 {
55816
55817
55818
55819 private $styles;
55820
55821 private $emptyStyle;
55822
55823 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
55824 {
55825 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
55826 $this->reset();
55827 }
55828
55829
55830
55831
55832 public function reset()
55833 {
55834 $this->styles = array();
55835 }
55836
55837
55838
55839
55840 public function push(OutputFormatterStyleInterface $style)
55841 {
55842 $this->styles[] = $style;
55843 }
55844
55845
55846
55847
55848
55849
55850
55851
55852 public function pop(OutputFormatterStyleInterface $style = null)
55853 {
55854 if (empty($this->styles)) {
55855 return $this->emptyStyle;
55856 }
55857
55858 if (null === $style) {
55859 return array_pop($this->styles);
55860 }
55861
55862 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
55863 if ($style->apply('') === $stackedStyle->apply('')) {
55864 $this->styles = \array_slice($this->styles, 0, $index);
55865
55866 return $stackedStyle;
55867 }
55868 }
55869
55870 throw new InvalidArgumentException('Incorrectly nested style tag found.');
55871 }
55872
55873
55874
55875
55876
55877
55878 public function getCurrent()
55879 {
55880 if (empty($this->styles)) {
55881 return $this->emptyStyle;
55882 }
55883
55884 return $this->styles[\count($this->styles) - 1];
55885 }
55886
55887
55888
55889
55890 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
55891 {
55892 $this->emptyStyle = $emptyStyle;
55893
55894 return $this;
55895 }
55896
55897
55898
55899
55900 public function getEmptyStyle()
55901 {
55902 return $this->emptyStyle;
55903 }
55904 }
55905 <?php
55906
55907
55908
55909
55910
55911
55912
55913
55914
55915
55916 namespace Symfony\Component\Console\Helper;
55917
55918
55919
55920
55921
55922
55923
55924
55925 class DebugFormatterHelper extends Helper
55926 {
55927 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
55928 private $started = array();
55929 private $count = -1;
55930
55931
55932
55933
55934
55935
55936
55937
55938
55939
55940 public function start($id, $message, $prefix = 'RUN')
55941 {
55942 $this->started[$id] = array('border' => ++$this->count % \count($this->colors));
55943
55944 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
55945 }
55946
55947
55948
55949
55950
55951
55952
55953
55954
55955
55956
55957
55958 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
55959 {
55960 $message = '';
55961
55962 if ($error) {
55963 if (isset($this->started[$id]['out'])) {
55964 $message .= "\n";
55965 unset($this->started[$id]['out']);
55966 }
55967 if (!isset($this->started[$id]['err'])) {
55968 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
55969 $this->started[$id]['err'] = true;
55970 }
55971
55972 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
55973 } else {
55974 if (isset($this->started[$id]['err'])) {
55975 $message .= "\n";
55976 unset($this->started[$id]['err']);
55977 }
55978 if (!isset($this->started[$id]['out'])) {
55979 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
55980 $this->started[$id]['out'] = true;
55981 }
55982
55983 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
55984 }
55985
55986 return $message;
55987 }
55988
55989
55990
55991
55992
55993
55994
55995
55996
55997
55998
55999 public function stop($id, $message, $successful, $prefix = 'RES')
56000 {
56001 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
56002
56003 if ($successful) {
56004 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
56005 }
56006
56007 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
56008
56009 unset($this->started[$id]['out'], $this->started[$id]['err']);
56010
56011 return $message;
56012 }
56013
56014
56015
56016
56017
56018
56019 private function getBorder($id)
56020 {
56021 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
56022 }
56023
56024
56025
56026
56027 public function getName()
56028 {
56029 return 'debug_formatter';
56030 }
56031 }
56032 <?php
56033
56034
56035
56036
56037
56038
56039
56040
56041
56042
56043 namespace Symfony\Component\Console\Helper;
56044
56045 use Symfony\Component\Console\Descriptor\DescriptorInterface;
56046 use Symfony\Component\Console\Descriptor\JsonDescriptor;
56047 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
56048 use Symfony\Component\Console\Descriptor\TextDescriptor;
56049 use Symfony\Component\Console\Descriptor\XmlDescriptor;
56050 use Symfony\Component\Console\Exception\InvalidArgumentException;
56051 use Symfony\Component\Console\Output\OutputInterface;
56052
56053
56054
56055
56056
56057
56058 class DescriptorHelper extends Helper
56059 {
56060
56061
56062
56063 private $descriptors = array();
56064
56065 public function __construct()
56066 {
56067 $this
56068 ->register('txt', new TextDescriptor())
56069 ->register('xml', new XmlDescriptor())
56070 ->register('json', new JsonDescriptor())
56071 ->register('md', new MarkdownDescriptor())
56072 ;
56073 }
56074
56075
56076
56077
56078
56079
56080
56081
56082
56083
56084
56085
56086
56087
56088 public function describe(OutputInterface $output, $object, array $options = array())
56089 {
56090 $options = array_merge(array(
56091 'raw_text' => false,
56092 'format' => 'txt',
56093 ), $options);
56094
56095 if (!isset($this->descriptors[$options['format']])) {
56096 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
56097 }
56098
56099 $descriptor = $this->descriptors[$options['format']];
56100 $descriptor->describe($output, $object, $options);
56101 }
56102
56103
56104
56105
56106
56107
56108
56109
56110
56111 public function register($format, DescriptorInterface $descriptor)
56112 {
56113 $this->descriptors[$format] = $descriptor;
56114
56115 return $this;
56116 }
56117
56118
56119
56120
56121 public function getName()
56122 {
56123 return 'descriptor';
56124 }
56125 }
56126 <?php
56127
56128
56129
56130
56131
56132
56133
56134
56135
56136
56137 namespace Symfony\Component\Console\Helper;
56138
56139 use Symfony\Component\Console\Exception\InvalidArgumentException;
56140 use Symfony\Component\Console\Exception\RuntimeException;
56141 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
56142 use Symfony\Component\Console\Output\ConsoleOutputInterface;
56143 use Symfony\Component\Console\Output\OutputInterface;
56144
56145
56146
56147
56148
56149
56150
56151
56152
56153 class DialogHelper extends InputAwareHelper
56154 {
56155 private $inputStream;
56156 private static $shell;
56157 private static $stty;
56158
56159 public function __construct($triggerDeprecationError = true)
56160 {
56161 if ($triggerDeprecationError) {
56162 @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);
56163 }
56164 }
56165
56166
56167
56168
56169
56170
56171
56172
56173
56174
56175
56176
56177
56178
56179
56180
56181 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
56182 {
56183 if ($output instanceof ConsoleOutputInterface) {
56184 $output = $output->getErrorOutput();
56185 }
56186
56187 $width = max(array_map('strlen', array_keys($choices)));
56188
56189 $messages = (array) $question;
56190 foreach ($choices as $key => $value) {
56191 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
56192 }
56193
56194 $output->writeln($messages);
56195
56196 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
56197
56198  $selectedChoices = str_replace(' ', '', $picked);
56199
56200 if ($multiselect) {
56201
56202  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
56203 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
56204 }
56205 $selectedChoices = explode(',', $selectedChoices);
56206 } else {
56207 $selectedChoices = array($picked);
56208 }
56209
56210 $multiselectChoices = array();
56211
56212 foreach ($selectedChoices as $value) {
56213 if (empty($choices[$value])) {
56214 throw new InvalidArgumentException(sprintf($errorMessage, $value));
56215 }
56216 $multiselectChoices[] = $value;
56217 }
56218
56219 if ($multiselect) {
56220 return $multiselectChoices;
56221 }
56222
56223 return $picked;
56224 }, $attempts, $default);
56225
56226 return $result;
56227 }
56228
56229
56230
56231
56232
56233
56234
56235
56236
56237
56238
56239
56240
56241 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
56242 {
56243 if ($this->input && !$this->input->isInteractive()) {
56244 return $default;
56245 }
56246
56247 if ($output instanceof ConsoleOutputInterface) {
56248 $output = $output->getErrorOutput();
56249 }
56250
56251 $output->write($question);
56252
56253 $inputStream = $this->inputStream ?: STDIN;
56254
56255 if (null === $autocomplete || !$this->hasSttyAvailable()) {
56256 $ret = fgets($inputStream, 4096);
56257 if (false === $ret) {
56258 throw new RuntimeException('Aborted');
56259 }
56260 $ret = trim($ret);
56261 } else {
56262 $ret = '';
56263
56264 $i = 0;
56265 $ofs = -1;
56266 $matches = $autocomplete;
56267 $numMatches = \count($matches);
56268
56269 $sttyMode = shell_exec('stty -g');
56270
56271
56272  shell_exec('stty -icanon -echo');
56273
56274
56275  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
56276
56277
56278  while (!feof($inputStream)) {
56279 $c = fread($inputStream, 1);
56280
56281
56282  if ("\177" === $c) {
56283 if (0 === $numMatches && 0 !== $i) {
56284 --$i;
56285
56286  $output->write("\033[1D");
56287 }
56288
56289 if (0 === $i) {
56290 $ofs = -1;
56291 $matches = $autocomplete;
56292 $numMatches = \count($matches);
56293 } else {
56294 $numMatches = 0;
56295 }
56296
56297
56298  $ret = substr($ret, 0, $i);
56299 } elseif ("\033" === $c) {
56300
56301  $c .= fread($inputStream, 2);
56302
56303
56304  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
56305 if ('A' === $c[2] && -1 === $ofs) {
56306 $ofs = 0;
56307 }
56308
56309 if (0 === $numMatches) {
56310 continue;
56311 }
56312
56313 $ofs += ('A' === $c[2]) ? -1 : 1;
56314 $ofs = ($numMatches + $ofs) % $numMatches;
56315 }
56316 } elseif (\ord($c) < 32) {
56317 if ("\t" === $c || "\n" === $c) {
56318 if ($numMatches > 0 && -1 !== $ofs) {
56319 $ret = $matches[$ofs];
56320
56321  $output->write(substr($ret, $i));
56322 $i = \strlen($ret);
56323 }
56324
56325 if ("\n" === $c) {
56326 $output->write($c);
56327 break;
56328 }
56329
56330 $numMatches = 0;
56331 }
56332
56333 continue;
56334 } else {
56335 $output->write($c);
56336 $ret .= $c;
56337 ++$i;
56338
56339 $numMatches = 0;
56340 $ofs = 0;
56341
56342 foreach ($autocomplete as $value) {
56343
56344  if (0 === strpos($value, $ret) && $i !== \strlen($value)) {
56345 $matches[$numMatches++] = $value;
56346 }
56347 }
56348 }
56349
56350
56351  $output->write("\033[K");
56352
56353 if ($numMatches > 0 && -1 !== $ofs) {
56354
56355  $output->write("\0337");
56356
56357  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
56358
56359  $output->write("\0338");
56360 }
56361 }
56362
56363
56364  shell_exec(sprintf('stty %s', $sttyMode));
56365 }
56366
56367 return \strlen($ret) > 0 ? $ret : $default;
56368 }
56369
56370
56371
56372
56373
56374
56375
56376
56377
56378
56379
56380
56381 public function askConfirmation(OutputInterface $output, $question, $default = true)
56382 {
56383 $answer = 'z';
56384 while ($answer && !\in_array(strtolower($answer[0]), array('y', 'n'))) {
56385 $answer = $this->ask($output, $question);
56386 }
56387
56388 if (false === $default) {
56389 return $answer && 'y' == strtolower($answer[0]);
56390 }
56391
56392 return !$answer || 'y' == strtolower($answer[0]);
56393 }
56394
56395
56396
56397
56398
56399
56400
56401
56402
56403
56404
56405
56406 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
56407 {
56408 if ($output instanceof ConsoleOutputInterface) {
56409 $output = $output->getErrorOutput();
56410 }
56411
56412 if ('\\' === \DIRECTORY_SEPARATOR) {
56413 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
56414
56415
56416  if ('phar:' === substr(__FILE__, 0, 5)) {
56417 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
56418 copy($exe, $tmpExe);
56419 $exe = $tmpExe;
56420 }
56421
56422 $output->write($question);
56423 $value = rtrim(shell_exec($exe));
56424 $output->writeln('');
56425
56426 if (isset($tmpExe)) {
56427 unlink($tmpExe);
56428 }
56429
56430 return $value;
56431 }
56432
56433 if ($this->hasSttyAvailable()) {
56434 $output->write($question);
56435
56436 $sttyMode = shell_exec('stty -g');
56437
56438 shell_exec('stty -echo');
56439 $value = fgets($this->inputStream ?: STDIN, 4096);
56440 shell_exec(sprintf('stty %s', $sttyMode));
56441
56442 if (false === $value) {
56443 throw new RuntimeException('Aborted');
56444 }
56445
56446 $value = trim($value);
56447 $output->writeln('');
56448
56449 return $value;
56450 }
56451
56452 if (false !== $shell = $this->getShell()) {
56453 $output->write($question);
56454 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
56455 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
56456 $value = rtrim(shell_exec($command));
56457 $output->writeln('');
56458
56459 return $value;
56460 }
56461
56462 if ($fallback) {
56463 return $this->ask($output, $question);
56464 }
56465
56466 throw new RuntimeException('Unable to hide the response');
56467 }
56468
56469
56470
56471
56472
56473
56474
56475
56476
56477
56478
56479
56480
56481
56482
56483
56484
56485
56486
56487 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
56488 {
56489 $that = $this;
56490
56491 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
56492 return $that->ask($output, $question, $default, $autocomplete);
56493 };
56494
56495 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
56496 }
56497
56498
56499
56500
56501
56502
56503
56504
56505
56506
56507
56508
56509
56510
56511
56512
56513
56514
56515
56516 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
56517 {
56518 $that = $this;
56519
56520 $interviewer = function () use ($output, $question, $fallback, $that) {
56521 return $that->askHiddenResponse($output, $question, $fallback);
56522 };
56523
56524 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
56525 }
56526
56527
56528
56529
56530
56531
56532
56533
56534 public function setInputStream($stream)
56535 {
56536 $this->inputStream = $stream;
56537 }
56538
56539
56540
56541
56542
56543
56544 public function getInputStream()
56545 {
56546 return $this->inputStream;
56547 }
56548
56549
56550
56551
56552 public function getName()
56553 {
56554 return 'dialog';
56555 }
56556
56557
56558
56559
56560
56561
56562 private function getShell()
56563 {
56564 if (null !== self::$shell) {
56565 return self::$shell;
56566 }
56567
56568 self::$shell = false;
56569
56570 if (file_exists('/usr/bin/env')) {
56571
56572  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
56573 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
56574 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
56575 self::$shell = $sh;
56576 break;
56577 }
56578 }
56579 }
56580
56581 return self::$shell;
56582 }
56583
56584 private function hasSttyAvailable()
56585 {
56586 if (null !== self::$stty) {
56587 return self::$stty;
56588 }
56589
56590 exec('stty 2>&1', $output, $exitcode);
56591
56592 return self::$stty = 0 === $exitcode;
56593 }
56594
56595
56596
56597
56598
56599
56600
56601
56602
56603
56604
56605
56606
56607 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
56608 {
56609 if ($output instanceof ConsoleOutputInterface) {
56610 $output = $output->getErrorOutput();
56611 }
56612
56613 $e = null;
56614 while (false === $attempts || $attempts--) {
56615 if (null !== $e) {
56616 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
56617 }
56618
56619 try {
56620 return \call_user_func($validator, $interviewer());
56621 } catch (\Exception $e) {
56622 }
56623 }
56624
56625 throw $e;
56626 }
56627 }
56628 <?php
56629
56630
56631
56632
56633
56634
56635
56636
56637
56638
56639 namespace Symfony\Component\Console\Helper;
56640
56641 use Symfony\Component\Console\Formatter\OutputFormatter;
56642
56643
56644
56645
56646
56647
56648 class FormatterHelper extends Helper
56649 {
56650
56651
56652
56653
56654
56655
56656
56657
56658
56659 public function formatSection($section, $message, $style = 'info')
56660 {
56661 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
56662 }
56663
56664
56665
56666
56667
56668
56669
56670
56671
56672
56673 public function formatBlock($messages, $style, $large = false)
56674 {
56675 if (!\is_array($messages)) {
56676 $messages = array($messages);
56677 }
56678
56679 $len = 0;
56680 $lines = array();
56681 foreach ($messages as $message) {
56682 $message = OutputFormatter::escape($message);
56683 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
56684 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
56685 }
56686
56687 $messages = $large ? array(str_repeat(' ', $len)) : array();
56688 for ($i = 0; isset($lines[$i]); ++$i) {
56689 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
56690 }
56691 if ($large) {
56692 $messages[] = str_repeat(' ', $len);
56693 }
56694
56695 for ($i = 0; isset($messages[$i]); ++$i) {
56696 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
56697 }
56698
56699 return implode("\n", $messages);
56700 }
56701
56702
56703
56704
56705 public function getName()
56706 {
56707 return 'formatter';
56708 }
56709 }
56710 <?php
56711
56712
56713
56714
56715
56716
56717
56718
56719
56720
56721 namespace Symfony\Component\Console\Helper;
56722
56723 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
56724
56725
56726
56727
56728
56729
56730 abstract class Helper implements HelperInterface
56731 {
56732 protected $helperSet = null;
56733
56734
56735
56736
56737 public function setHelperSet(HelperSet $helperSet = null)
56738 {
56739 $this->helperSet = $helperSet;
56740 }
56741
56742
56743
56744
56745 public function getHelperSet()
56746 {
56747 return $this->helperSet;
56748 }
56749
56750
56751
56752
56753
56754
56755
56756
56757 public static function strlen($string)
56758 {
56759 if (false === $encoding = mb_detect_encoding($string, null, true)) {
56760 return \strlen($string);
56761 }
56762
56763 return mb_strwidth($string, $encoding);
56764 }
56765
56766 public static function formatTime($secs)
56767 {
56768 static $timeFormats = array(
56769 array(0, '< 1 sec'),
56770 array(1, '1 sec'),
56771 array(2, 'secs', 1),
56772 array(60, '1 min'),
56773 array(120, 'mins', 60),
56774 array(3600, '1 hr'),
56775 array(7200, 'hrs', 3600),
56776 array(86400, '1 day'),
56777 array(172800, 'days', 86400),
56778 );
56779
56780 foreach ($timeFormats as $index => $format) {
56781 if ($secs >= $format[0]) {
56782 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
56783 || $index == \count($timeFormats) - 1
56784 ) {
56785 if (2 == \count($format)) {
56786 return $format[1];
56787 }
56788
56789 return floor($secs / $format[2]).' '.$format[1];
56790 }
56791 }
56792 }
56793 }
56794
56795 public static function formatMemory($memory)
56796 {
56797 if ($memory >= 1024 * 1024 * 1024) {
56798 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
56799 }
56800
56801 if ($memory >= 1024 * 1024) {
56802 return sprintf('%.1f MiB', $memory / 1024 / 1024);
56803 }
56804
56805 if ($memory >= 1024) {
56806 return sprintf('%d KiB', $memory / 1024);
56807 }
56808
56809 return sprintf('%d B', $memory);
56810 }
56811
56812 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
56813 {
56814 return self::strlen(self::removeDecoration($formatter, $string));
56815 }
56816
56817 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
56818 {
56819 $isDecorated = $formatter->isDecorated();
56820 $formatter->setDecorated(false);
56821
56822  $string = $formatter->format($string);
56823
56824  $string = preg_replace("/\033\[[^m]*m/", '', $string);
56825 $formatter->setDecorated($isDecorated);
56826
56827 return $string;
56828 }
56829 }
56830 <?php
56831
56832
56833
56834
56835
56836
56837
56838
56839
56840
56841 namespace Symfony\Component\Console\Helper;
56842
56843
56844
56845
56846
56847
56848 interface HelperInterface
56849 {
56850
56851
56852
56853 public function setHelperSet(HelperSet $helperSet = null);
56854
56855
56856
56857
56858
56859
56860 public function getHelperSet();
56861
56862
56863
56864
56865
56866
56867 public function getName();
56868 }
56869 <?php
56870
56871
56872
56873
56874
56875
56876
56877
56878
56879
56880 namespace Symfony\Component\Console\Helper;
56881
56882 use Symfony\Component\Console\Command\Command;
56883 use Symfony\Component\Console\Exception\InvalidArgumentException;
56884
56885
56886
56887
56888
56889
56890 class HelperSet implements \IteratorAggregate
56891 {
56892
56893
56894
56895 private $helpers = array();
56896 private $command;
56897
56898
56899
56900
56901 public function __construct(array $helpers = array())
56902 {
56903 foreach ($helpers as $alias => $helper) {
56904 $this->set($helper, \is_int($alias) ? null : $alias);
56905 }
56906 }
56907
56908
56909
56910
56911
56912
56913
56914 public function set(HelperInterface $helper, $alias = null)
56915 {
56916 $this->helpers[$helper->getName()] = $helper;
56917 if (null !== $alias) {
56918 $this->helpers[$alias] = $helper;
56919 }
56920
56921 $helper->setHelperSet($this);
56922 }
56923
56924
56925
56926
56927
56928
56929
56930
56931 public function has($name)
56932 {
56933 return isset($this->helpers[$name]);
56934 }
56935
56936
56937
56938
56939
56940
56941
56942
56943
56944
56945 public function get($name)
56946 {
56947 if (!$this->has($name)) {
56948 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
56949 }
56950
56951 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
56952 @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);
56953 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
56954 @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);
56955 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
56956 @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);
56957 }
56958
56959 return $this->helpers[$name];
56960 }
56961
56962 public function setCommand(Command $command = null)
56963 {
56964 $this->command = $command;
56965 }
56966
56967
56968
56969
56970
56971
56972 public function getCommand()
56973 {
56974 return $this->command;
56975 }
56976
56977
56978
56979
56980 public function getIterator()
56981 {
56982 return new \ArrayIterator($this->helpers);
56983 }
56984 }
56985 <?php
56986
56987
56988
56989
56990
56991
56992
56993
56994
56995
56996 namespace Symfony\Component\Console\Helper;
56997
56998 use Symfony\Component\Console\Input\InputAwareInterface;
56999 use Symfony\Component\Console\Input\InputInterface;
57000
57001
57002
57003
57004
57005
57006 abstract class InputAwareHelper extends Helper implements InputAwareInterface
57007 {
57008 protected $input;
57009
57010
57011
57012
57013 public function setInput(InputInterface $input)
57014 {
57015 $this->input = $input;
57016 }
57017 }
57018 <?php
57019
57020
57021
57022
57023
57024
57025
57026
57027
57028
57029 namespace Symfony\Component\Console\Helper;
57030
57031 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57032 use Symfony\Component\Console\Output\OutputInterface;
57033 use Symfony\Component\Process\Exception\ProcessFailedException;
57034 use Symfony\Component\Process\Process;
57035 use Symfony\Component\Process\ProcessBuilder;
57036
57037
57038
57039
57040
57041
57042 class ProcessHelper extends Helper
57043 {
57044
57045
57046
57047
57048
57049
57050
57051
57052
57053
57054
57055
57056 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
57057 {
57058 if ($output instanceof ConsoleOutputInterface) {
57059 $output = $output->getErrorOutput();
57060 }
57061
57062 $formatter = $this->getHelperSet()->get('debug_formatter');
57063
57064 if (\is_array($cmd)) {
57065 $process = ProcessBuilder::create($cmd)->getProcess();
57066 } elseif ($cmd instanceof Process) {
57067 $process = $cmd;
57068 } else {
57069 $process = new Process($cmd);
57070 }
57071
57072 if ($verbosity <= $output->getVerbosity()) {
57073 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
57074 }
57075
57076 if ($output->isDebug()) {
57077 $callback = $this->wrapCallback($output, $process, $callback);
57078 }
57079
57080 $process->run($callback);
57081
57082 if ($verbosity <= $output->getVerbosity()) {
57083 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
57084 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
57085 }
57086
57087 if (!$process->isSuccessful() && null !== $error) {
57088 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
57089 }
57090
57091 return $process;
57092 }
57093
57094
57095
57096
57097
57098
57099
57100
57101
57102
57103
57104
57105
57106
57107
57108
57109
57110
57111
57112 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
57113 {
57114 $process = $this->run($output, $cmd, $error, $callback);
57115
57116 if (!$process->isSuccessful()) {
57117 throw new ProcessFailedException($process);
57118 }
57119
57120 return $process;
57121 }
57122
57123
57124
57125
57126
57127
57128
57129
57130
57131
57132 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
57133 {
57134 if ($output instanceof ConsoleOutputInterface) {
57135 $output = $output->getErrorOutput();
57136 }
57137
57138 $formatter = $this->getHelperSet()->get('debug_formatter');
57139
57140 $that = $this;
57141
57142 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
57143 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
57144
57145 if (null !== $callback) {
57146 \call_user_func($callback, $type, $buffer);
57147 }
57148 };
57149 }
57150
57151
57152
57153
57154
57155
57156 public function escapeString($str)
57157 {
57158 return str_replace('<', '\\<', $str);
57159 }
57160
57161
57162
57163
57164 public function getName()
57165 {
57166 return 'process';
57167 }
57168 }
57169 <?php
57170
57171
57172
57173
57174
57175
57176
57177
57178
57179
57180 namespace Symfony\Component\Console\Helper;
57181
57182 use Symfony\Component\Console\Exception\LogicException;
57183 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57184 use Symfony\Component\Console\Output\OutputInterface;
57185
57186
57187
57188
57189
57190
57191
57192 class ProgressBar
57193 {
57194 private $barWidth = 28;
57195 private $barChar;
57196 private $emptyBarChar = '-';
57197 private $progressChar = '>';
57198 private $format;
57199 private $internalFormat;
57200 private $redrawFreq = 1;
57201 private $output;
57202 private $step = 0;
57203 private $max;
57204 private $startTime;
57205 private $stepWidth;
57206 private $percent = 0.0;
57207 private $formatLineCount;
57208 private $messages = array();
57209 private $overwrite = true;
57210 private $firstRun = true;
57211
57212 private static $formatters;
57213 private static $formats;
57214
57215
57216
57217
57218
57219 public function __construct(OutputInterface $output, $max = 0)
57220 {
57221 if ($output instanceof ConsoleOutputInterface) {
57222 $output = $output->getErrorOutput();
57223 }
57224
57225 $this->output = $output;
57226 $this->setMaxSteps($max);
57227
57228 if (!$this->output->isDecorated()) {
57229
57230  $this->overwrite = false;
57231
57232
57233  $this->setRedrawFrequency($max / 10);
57234 }
57235
57236 $this->startTime = time();
57237 }
57238
57239
57240
57241
57242
57243
57244
57245
57246
57247 public static function setPlaceholderFormatterDefinition($name, $callable)
57248 {
57249 if (!self::$formatters) {
57250 self::$formatters = self::initPlaceholderFormatters();
57251 }
57252
57253 self::$formatters[$name] = $callable;
57254 }
57255
57256
57257
57258
57259
57260
57261
57262
57263 public static function getPlaceholderFormatterDefinition($name)
57264 {
57265 if (!self::$formatters) {
57266 self::$formatters = self::initPlaceholderFormatters();
57267 }
57268
57269 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
57270 }
57271
57272
57273
57274
57275
57276
57277
57278
57279
57280 public static function setFormatDefinition($name, $format)
57281 {
57282 if (!self::$formats) {
57283 self::$formats = self::initFormats();
57284 }
57285
57286 self::$formats[$name] = $format;
57287 }
57288
57289
57290
57291
57292
57293
57294
57295
57296 public static function getFormatDefinition($name)
57297 {
57298 if (!self::$formats) {
57299 self::$formats = self::initFormats();
57300 }
57301
57302 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
57303 }
57304
57305
57306
57307
57308
57309
57310
57311
57312
57313
57314
57315 public function setMessage($message, $name = 'message')
57316 {
57317 $this->messages[$name] = $message;
57318 }
57319
57320 public function getMessage($name = 'message')
57321 {
57322 return $this->messages[$name];
57323 }
57324
57325
57326
57327
57328
57329
57330 public function getStartTime()
57331 {
57332 return $this->startTime;
57333 }
57334
57335
57336
57337
57338
57339
57340 public function getMaxSteps()
57341 {
57342 return $this->max;
57343 }
57344
57345
57346
57347
57348
57349
57350
57351
57352 public function getStep()
57353 {
57354 @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);
57355
57356 return $this->getProgress();
57357 }
57358
57359
57360
57361
57362
57363
57364 public function getProgress()
57365 {
57366 return $this->step;
57367 }
57368
57369
57370
57371
57372
57373
57374
57375
57376 public function getStepWidth()
57377 {
57378 return $this->stepWidth;
57379 }
57380
57381
57382
57383
57384
57385
57386 public function getProgressPercent()
57387 {
57388 return $this->percent;
57389 }
57390
57391
57392
57393
57394
57395
57396 public function setBarWidth($size)
57397 {
57398 $this->barWidth = (int) $size;
57399 }
57400
57401
57402
57403
57404
57405
57406 public function getBarWidth()
57407 {
57408 return $this->barWidth;
57409 }
57410
57411
57412
57413
57414
57415
57416 public function setBarCharacter($char)
57417 {
57418 $this->barChar = $char;
57419 }
57420
57421
57422
57423
57424
57425
57426 public function getBarCharacter()
57427 {
57428 if (null === $this->barChar) {
57429 return $this->max ? '=' : $this->emptyBarChar;
57430 }
57431
57432 return $this->barChar;
57433 }
57434
57435
57436
57437
57438
57439
57440 public function setEmptyBarCharacter($char)
57441 {
57442 $this->emptyBarChar = $char;
57443 }
57444
57445
57446
57447
57448
57449
57450 public function getEmptyBarCharacter()
57451 {
57452 return $this->emptyBarChar;
57453 }
57454
57455
57456
57457
57458
57459
57460 public function setProgressCharacter($char)
57461 {
57462 $this->progressChar = $char;
57463 }
57464
57465
57466
57467
57468
57469
57470 public function getProgressCharacter()
57471 {
57472 return $this->progressChar;
57473 }
57474
57475
57476
57477
57478
57479
57480 public function setFormat($format)
57481 {
57482 $this->format = null;
57483 $this->internalFormat = $format;
57484 }
57485
57486
57487
57488
57489
57490
57491 public function setRedrawFrequency($freq)
57492 {
57493 $this->redrawFreq = max((int) $freq, 1);
57494 }
57495
57496
57497
57498
57499
57500
57501 public function start($max = null)
57502 {
57503 $this->startTime = time();
57504 $this->step = 0;
57505 $this->percent = 0.0;
57506
57507 if (null !== $max) {
57508 $this->setMaxSteps($max);
57509 }
57510
57511 $this->display();
57512 }
57513
57514
57515
57516
57517
57518
57519
57520
57521 public function advance($step = 1)
57522 {
57523 $this->setProgress($this->step + $step);
57524 }
57525
57526
57527
57528
57529
57530
57531
57532
57533
57534
57535 public function setCurrent($step)
57536 {
57537 @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);
57538
57539 $this->setProgress($step);
57540 }
57541
57542
57543
57544
57545
57546
57547 public function setOverwrite($overwrite)
57548 {
57549 $this->overwrite = (bool) $overwrite;
57550 }
57551
57552
57553
57554
57555
57556
57557
57558
57559 public function setProgress($step)
57560 {
57561 $step = (int) $step;
57562 if ($step < $this->step) {
57563 throw new LogicException('You can\'t regress the progress bar.');
57564 }
57565
57566 if ($this->max && $step > $this->max) {
57567 $this->max = $step;
57568 }
57569
57570 $prevPeriod = (int) ($this->step / $this->redrawFreq);
57571 $currPeriod = (int) ($step / $this->redrawFreq);
57572 $this->step = $step;
57573 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
57574 if ($prevPeriod !== $currPeriod || $this->max === $step) {
57575 $this->display();
57576 }
57577 }
57578
57579
57580
57581
57582 public function finish()
57583 {
57584 if (!$this->max) {
57585 $this->max = $this->step;
57586 }
57587
57588 if ($this->step === $this->max && !$this->overwrite) {
57589
57590  return;
57591 }
57592
57593 $this->setProgress($this->max);
57594 }
57595
57596
57597
57598
57599 public function display()
57600 {
57601 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
57602 return;
57603 }
57604
57605 if (null === $this->format) {
57606 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
57607 }
57608
57609
57610  $self = $this;
57611 $output = $this->output;
57612 $messages = $this->messages;
57613 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
57614 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
57615 $text = \call_user_func($formatter, $self, $output);
57616 } elseif (isset($messages[$matches[1]])) {
57617 $text = $messages[$matches[1]];
57618 } else {
57619 return $matches[0];
57620 }
57621
57622 if (isset($matches[2])) {
57623 $text = sprintf('%'.$matches[2], $text);
57624 }
57625
57626 return $text;
57627 }, $this->format));
57628 }
57629
57630
57631
57632
57633
57634
57635
57636
57637 public function clear()
57638 {
57639 if (!$this->overwrite) {
57640 return;
57641 }
57642
57643 if (null === $this->format) {
57644 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
57645 }
57646
57647 $this->overwrite('');
57648 }
57649
57650
57651
57652
57653
57654
57655 private function setRealFormat($format)
57656 {
57657
57658  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
57659 $this->format = self::getFormatDefinition($format.'_nomax');
57660 } elseif (null !== self::getFormatDefinition($format)) {
57661 $this->format = self::getFormatDefinition($format);
57662 } else {
57663 $this->format = $format;
57664 }
57665
57666 $this->formatLineCount = substr_count($this->format, "\n");
57667 }
57668
57669
57670
57671
57672
57673
57674 private function setMaxSteps($max)
57675 {
57676 $this->max = max(0, (int) $max);
57677 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
57678 }
57679
57680
57681
57682
57683
57684
57685 private function overwrite($message)
57686 {
57687 if ($this->overwrite) {
57688 if (!$this->firstRun) {
57689
57690  $this->output->write("\x0D");
57691
57692
57693  $this->output->write("\x1B[2K");
57694
57695
57696  if ($this->formatLineCount > 0) {
57697 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
57698 }
57699 }
57700 } elseif ($this->step > 0) {
57701 $this->output->writeln('');
57702 }
57703
57704 $this->firstRun = false;
57705
57706 $this->output->write($message);
57707 }
57708
57709 private function determineBestFormat()
57710 {
57711 switch ($this->output->getVerbosity()) {
57712
57713  case OutputInterface::VERBOSITY_VERBOSE:
57714 return $this->max ? 'verbose' : 'verbose_nomax';
57715 case OutputInterface::VERBOSITY_VERY_VERBOSE:
57716 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
57717 case OutputInterface::VERBOSITY_DEBUG:
57718 return $this->max ? 'debug' : 'debug_nomax';
57719 default:
57720 return $this->max ? 'normal' : 'normal_nomax';
57721 }
57722 }
57723
57724 private static function initPlaceholderFormatters()
57725 {
57726 return array(
57727 'bar' => function (ProgressBar $bar, OutputInterface $output) {
57728 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
57729 $display = str_repeat($bar->getBarCharacter(), $completeBars);
57730 if ($completeBars < $bar->getBarWidth()) {
57731 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
57732 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
57733 }
57734
57735 return $display;
57736 },
57737 'elapsed' => function (ProgressBar $bar) {
57738 return Helper::formatTime(time() - $bar->getStartTime());
57739 },
57740 'remaining' => function (ProgressBar $bar) {
57741 if (!$bar->getMaxSteps()) {
57742 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
57743 }
57744
57745 if (!$bar->getProgress()) {
57746 $remaining = 0;
57747 } else {
57748 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
57749 }
57750
57751 return Helper::formatTime($remaining);
57752 },
57753 'estimated' => function (ProgressBar $bar) {
57754 if (!$bar->getMaxSteps()) {
57755 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
57756 }
57757
57758 if (!$bar->getProgress()) {
57759 $estimated = 0;
57760 } else {
57761 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
57762 }
57763
57764 return Helper::formatTime($estimated);
57765 },
57766 'memory' => function (ProgressBar $bar) {
57767 return Helper::formatMemory(memory_get_usage(true));
57768 },
57769 'current' => function (ProgressBar $bar) {
57770 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
57771 },
57772 'max' => function (ProgressBar $bar) {
57773 return $bar->getMaxSteps();
57774 },
57775 'percent' => function (ProgressBar $bar) {
57776 return floor($bar->getProgressPercent() * 100);
57777 },
57778 );
57779 }
57780
57781 private static function initFormats()
57782 {
57783 return array(
57784 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
57785 'normal_nomax' => ' %current% [%bar%]',
57786
57787 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
57788 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
57789
57790 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
57791 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
57792
57793 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
57794 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
57795 );
57796 }
57797 }
57798 <?php
57799
57800
57801
57802
57803
57804
57805
57806
57807
57808
57809 namespace Symfony\Component\Console\Helper;
57810
57811 use Symfony\Component\Console\Exception\LogicException;
57812 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57813 use Symfony\Component\Console\Output\NullOutput;
57814 use Symfony\Component\Console\Output\OutputInterface;
57815
57816
57817
57818
57819
57820
57821
57822
57823
57824
57825 class ProgressHelper extends Helper
57826 {
57827 const FORMAT_QUIET = ' %percent%%';
57828 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
57829 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
57830 const FORMAT_QUIET_NOMAX = ' %current%';
57831 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
57832 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
57833
57834
57835  private $barWidth = 28;
57836 private $barChar = '=';
57837 private $emptyBarChar = '-';
57838 private $progressChar = '>';
57839 private $format = null;
57840 private $redrawFreq = 1;
57841
57842 private $lastMessagesLength;
57843 private $barCharOriginal;
57844
57845
57846
57847
57848 private $output;
57849
57850
57851
57852
57853
57854
57855 private $current;
57856
57857
57858
57859
57860
57861
57862 private $max;
57863
57864
57865
57866
57867
57868
57869 private $startTime;
57870
57871
57872
57873
57874
57875
57876 private $defaultFormatVars = array(
57877 'current',
57878 'max',
57879 'bar',
57880 'percent',
57881 'elapsed',
57882 );
57883
57884
57885
57886
57887
57888
57889 private $formatVars;
57890
57891
57892
57893
57894
57895
57896 private $widths = array(
57897 'current' => 4,
57898 'max' => 4,
57899 'percent' => 3,
57900 'elapsed' => 6,
57901 );
57902
57903
57904
57905
57906
57907
57908 private $timeFormats = array(
57909 array(0, '???'),
57910 array(2, '1 sec'),
57911 array(59, 'secs', 1),
57912 array(60, '1 min'),
57913 array(3600, 'mins', 60),
57914 array(5400, '1 hr'),
57915 array(86400, 'hrs', 3600),
57916 array(129600, '1 day'),
57917 array(604800, 'days', 86400),
57918 );
57919
57920 public function __construct($triggerDeprecationError = true)
57921 {
57922 if ($triggerDeprecationError) {
57923 @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);
57924 }
57925 }
57926
57927
57928
57929
57930
57931
57932 public function setBarWidth($size)
57933 {
57934 $this->barWidth = (int) $size;
57935 }
57936
57937
57938
57939
57940
57941
57942 public function setBarCharacter($char)
57943 {
57944 $this->barChar = $char;
57945 }
57946
57947
57948
57949
57950
57951
57952 public function setEmptyBarCharacter($char)
57953 {
57954 $this->emptyBarChar = $char;
57955 }
57956
57957
57958
57959
57960
57961
57962 public function setProgressCharacter($char)
57963 {
57964 $this->progressChar = $char;
57965 }
57966
57967
57968
57969
57970
57971
57972 public function setFormat($format)
57973 {
57974 $this->format = $format;
57975 }
57976
57977
57978
57979
57980
57981
57982 public function setRedrawFrequency($freq)
57983 {
57984 $this->redrawFreq = (int) $freq;
57985 }
57986
57987
57988
57989
57990
57991
57992
57993 public function start(OutputInterface $output, $max = null)
57994 {
57995 if ($output instanceof ConsoleOutputInterface) {
57996 $output = $output->getErrorOutput();
57997 }
57998
57999 $this->startTime = time();
58000 $this->current = 0;
58001 $this->max = (int) $max;
58002
58003
58004  $this->output = $output->isDecorated() ? $output : new NullOutput();
58005 $this->lastMessagesLength = 0;
58006 $this->barCharOriginal = '';
58007
58008 if (null === $this->format) {
58009 switch ($output->getVerbosity()) {
58010 case OutputInterface::VERBOSITY_QUIET:
58011 $this->format = self::FORMAT_QUIET_NOMAX;
58012 if ($this->max > 0) {
58013 $this->format = self::FORMAT_QUIET;
58014 }
58015 break;
58016 case OutputInterface::VERBOSITY_VERBOSE:
58017 case OutputInterface::VERBOSITY_VERY_VERBOSE:
58018 case OutputInterface::VERBOSITY_DEBUG:
58019 $this->format = self::FORMAT_VERBOSE_NOMAX;
58020 if ($this->max > 0) {
58021 $this->format = self::FORMAT_VERBOSE;
58022 }
58023 break;
58024 default:
58025 $this->format = self::FORMAT_NORMAL_NOMAX;
58026 if ($this->max > 0) {
58027 $this->format = self::FORMAT_NORMAL;
58028 }
58029 break;
58030 }
58031 }
58032
58033 $this->initialize();
58034 }
58035
58036
58037
58038
58039
58040
58041
58042
58043
58044 public function advance($step = 1, $redraw = false)
58045 {
58046 $this->setCurrent($this->current + $step, $redraw);
58047 }
58048
58049
58050
58051
58052
58053
58054
58055
58056
58057 public function setCurrent($current, $redraw = false)
58058 {
58059 if (null === $this->startTime) {
58060 throw new LogicException('You must start the progress bar before calling setCurrent().');
58061 }
58062
58063 $current = (int) $current;
58064
58065 if ($current < $this->current) {
58066 throw new LogicException('You can\'t regress the progress bar');
58067 }
58068
58069 if (0 === $this->current) {
58070 $redraw = true;
58071 }
58072
58073 $prevPeriod = (int) ($this->current / $this->redrawFreq);
58074
58075 $this->current = $current;
58076
58077 $currPeriod = (int) ($this->current / $this->redrawFreq);
58078 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
58079 $this->display();
58080 }
58081 }
58082
58083
58084
58085
58086
58087
58088
58089
58090 public function display($finish = false)
58091 {
58092 if (null === $this->startTime) {
58093 throw new LogicException('You must start the progress bar before calling display().');
58094 }
58095
58096 $message = $this->format;
58097 foreach ($this->generate($finish) as $name => $value) {
58098 $message = str_replace("%{$name}%", $value, $message);
58099 }
58100 $this->overwrite($this->output, $message);
58101 }
58102
58103
58104
58105
58106
58107
58108
58109
58110 public function clear()
58111 {
58112 $this->overwrite($this->output, '');
58113 }
58114
58115
58116
58117
58118 public function finish()
58119 {
58120 if (null === $this->startTime) {
58121 throw new LogicException('You must start the progress bar before calling finish().');
58122 }
58123
58124 if (null !== $this->startTime) {
58125 if (!$this->max) {
58126 $this->barChar = $this->barCharOriginal;
58127 $this->display(true);
58128 }
58129 $this->startTime = null;
58130 $this->output->writeln('');
58131 $this->output = null;
58132 }
58133 }
58134
58135
58136
58137
58138 private function initialize()
58139 {
58140 $this->formatVars = array();
58141 foreach ($this->defaultFormatVars as $var) {
58142 if (false !== strpos($this->format, "%{$var}%")) {
58143 $this->formatVars[$var] = true;
58144 }
58145 }
58146
58147 if ($this->max > 0) {
58148 $this->widths['max'] = $this->strlen($this->max);
58149 $this->widths['current'] = $this->widths['max'];
58150 } else {
58151 $this->barCharOriginal = $this->barChar;
58152 $this->barChar = $this->emptyBarChar;
58153 }
58154 }
58155
58156
58157
58158
58159
58160
58161
58162
58163 private function generate($finish = false)
58164 {
58165 $vars = array();
58166 $percent = 0;
58167 if ($this->max > 0) {
58168 $percent = (float) $this->current / $this->max;
58169 }
58170
58171 if (isset($this->formatVars['bar'])) {
58172 if ($this->max > 0) {
58173 $completeBars = floor($percent * $this->barWidth);
58174 } else {
58175 if (!$finish) {
58176 $completeBars = floor($this->current % $this->barWidth);
58177 } else {
58178 $completeBars = $this->barWidth;
58179 }
58180 }
58181
58182 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
58183 $bar = str_repeat($this->barChar, $completeBars);
58184 if ($completeBars < $this->barWidth) {
58185 $bar .= $this->progressChar;
58186 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
58187 }
58188
58189 $vars['bar'] = $bar;
58190 }
58191
58192 if (isset($this->formatVars['elapsed'])) {
58193 $elapsed = time() - $this->startTime;
58194 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
58195 }
58196
58197 if (isset($this->formatVars['current'])) {
58198 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
58199 }
58200
58201 if (isset($this->formatVars['max'])) {
58202 $vars['max'] = $this->max;
58203 }
58204
58205 if (isset($this->formatVars['percent'])) {
58206 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
58207 }
58208
58209 return $vars;
58210 }
58211
58212
58213
58214
58215
58216
58217
58218
58219 private function humaneTime($secs)
58220 {
58221 $text = '';
58222 foreach ($this->timeFormats as $format) {
58223 if ($secs < $format[0]) {
58224 if (2 == \count($format)) {
58225 $text = $format[1];
58226 break;
58227 } else {
58228 $text = ceil($secs / $format[2]).' '.$format[1];
58229 break;
58230 }
58231 }
58232 }
58233
58234 return $text;
58235 }
58236
58237
58238
58239
58240
58241
58242
58243 private function overwrite(OutputInterface $output, $message)
58244 {
58245 $length = $this->strlen($message);
58246
58247
58248  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
58249 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
58250 }
58251
58252
58253  $output->write("\x0D");
58254 $output->write($message);
58255
58256 $this->lastMessagesLength = $this->strlen($message);
58257 }
58258
58259
58260
58261
58262 public function getName()
58263 {
58264 return 'progress';
58265 }
58266 }
58267 <?php
58268
58269
58270
58271
58272
58273
58274
58275
58276
58277
58278 namespace Symfony\Component\Console\Helper;
58279
58280 use Symfony\Component\Console\Exception\InvalidArgumentException;
58281 use Symfony\Component\Console\Exception\LogicException;
58282 use Symfony\Component\Console\Output\OutputInterface;
58283
58284
58285
58286
58287 class ProgressIndicator
58288 {
58289 private $output;
58290 private $startTime;
58291 private $format;
58292 private $message;
58293 private $indicatorValues;
58294 private $indicatorCurrent;
58295 private $indicatorChangeInterval;
58296 private $indicatorUpdateTime;
58297 private $started = false;
58298
58299 private static $formatters;
58300 private static $formats;
58301
58302
58303
58304
58305
58306
58307
58308 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
58309 {
58310 $this->output = $output;
58311
58312 if (null === $format) {
58313 $format = $this->determineBestFormat();
58314 }
58315
58316 if (null === $indicatorValues) {
58317 $indicatorValues = array('-', '\\', '|', '/');
58318 }
58319
58320 $indicatorValues = array_values($indicatorValues);
58321
58322 if (2 > \count($indicatorValues)) {
58323 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
58324 }
58325
58326 $this->format = self::getFormatDefinition($format);
58327 $this->indicatorChangeInterval = $indicatorChangeInterval;
58328 $this->indicatorValues = $indicatorValues;
58329 $this->startTime = time();
58330 }
58331
58332
58333
58334
58335
58336
58337 public function setMessage($message)
58338 {
58339 $this->message = $message;
58340
58341 $this->display();
58342 }
58343
58344
58345
58346
58347
58348
58349
58350
58351 public function getMessage()
58352 {
58353 return $this->message;
58354 }
58355
58356
58357
58358
58359
58360
58361
58362
58363 public function getStartTime()
58364 {
58365 return $this->startTime;
58366 }
58367
58368
58369
58370
58371
58372
58373
58374
58375 public function getCurrentValue()
58376 {
58377 return $this->indicatorValues[$this->indicatorCurrent % \count($this->indicatorValues)];
58378 }
58379
58380
58381
58382
58383
58384
58385 public function start($message)
58386 {
58387 if ($this->started) {
58388 throw new LogicException('Progress indicator already started.');
58389 }
58390
58391 $this->message = $message;
58392 $this->started = true;
58393 $this->startTime = time();
58394 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
58395 $this->indicatorCurrent = 0;
58396
58397 $this->display();
58398 }
58399
58400
58401
58402
58403 public function advance()
58404 {
58405 if (!$this->started) {
58406 throw new LogicException('Progress indicator has not yet been started.');
58407 }
58408
58409 if (!$this->output->isDecorated()) {
58410 return;
58411 }
58412
58413 $currentTime = $this->getCurrentTimeInMilliseconds();
58414
58415 if ($currentTime < $this->indicatorUpdateTime) {
58416 return;
58417 }
58418
58419 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
58420 ++$this->indicatorCurrent;
58421
58422 $this->display();
58423 }
58424
58425
58426
58427
58428
58429
58430 public function finish($message)
58431 {
58432 if (!$this->started) {
58433 throw new LogicException('Progress indicator has not yet been started.');
58434 }
58435
58436 $this->message = $message;
58437 $this->display();
58438 $this->output->writeln('');
58439 $this->started = false;
58440 }
58441
58442
58443
58444
58445
58446
58447
58448
58449 public static function getFormatDefinition($name)
58450 {
58451 if (!self::$formats) {
58452 self::$formats = self::initFormats();
58453 }
58454
58455 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
58456 }
58457
58458
58459
58460
58461
58462
58463
58464
58465
58466 public static function setPlaceholderFormatterDefinition($name, $callable)
58467 {
58468 if (!self::$formatters) {
58469 self::$formatters = self::initPlaceholderFormatters();
58470 }
58471
58472 self::$formatters[$name] = $callable;
58473 }
58474
58475
58476
58477
58478
58479
58480
58481
58482 public static function getPlaceholderFormatterDefinition($name)
58483 {
58484 if (!self::$formatters) {
58485 self::$formatters = self::initPlaceholderFormatters();
58486 }
58487
58488 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
58489 }
58490
58491 private function display()
58492 {
58493 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
58494 return;
58495 }
58496
58497 $self = $this;
58498
58499 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
58500 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
58501 return \call_user_func($formatter, $self);
58502 }
58503
58504 return $matches[0];
58505 }, $this->format));
58506 }
58507
58508 private function determineBestFormat()
58509 {
58510 switch ($this->output->getVerbosity()) {
58511
58512  case OutputInterface::VERBOSITY_VERBOSE:
58513 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
58514 case OutputInterface::VERBOSITY_VERY_VERBOSE:
58515 case OutputInterface::VERBOSITY_DEBUG:
58516 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
58517 default:
58518 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
58519 }
58520 }
58521
58522
58523
58524
58525
58526
58527 private function overwrite($message)
58528 {
58529 if ($this->output->isDecorated()) {
58530 $this->output->write("\x0D\x1B[2K");
58531 $this->output->write($message);
58532 } else {
58533 $this->output->writeln($message);
58534 }
58535 }
58536
58537 private function getCurrentTimeInMilliseconds()
58538 {
58539 return round(microtime(true) * 1000);
58540 }
58541
58542 private static function initPlaceholderFormatters()
58543 {
58544 return array(
58545 'indicator' => function (ProgressIndicator $indicator) {
58546 return $indicator->getCurrentValue();
58547 },
58548 'message' => function (ProgressIndicator $indicator) {
58549 return $indicator->getMessage();
58550 },
58551 'elapsed' => function (ProgressIndicator $indicator) {
58552 return Helper::formatTime(time() - $indicator->getStartTime());
58553 },
58554 'memory' => function () {
58555 return Helper::formatMemory(memory_get_usage(true));
58556 },
58557 );
58558 }
58559
58560 private static function initFormats()
58561 {
58562 return array(
58563 'normal' => ' %indicator% %message%',
58564 'normal_no_ansi' => ' %message%',
58565
58566 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
58567 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
58568
58569 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
58570 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
58571 );
58572 }
58573 }
58574 <?php
58575
58576
58577
58578
58579
58580
58581
58582
58583
58584
58585 namespace Symfony\Component\Console\Helper;
58586
58587 use Symfony\Component\Console\Exception\InvalidArgumentException;
58588 use Symfony\Component\Console\Exception\RuntimeException;
58589 use Symfony\Component\Console\Formatter\OutputFormatter;
58590 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
58591 use Symfony\Component\Console\Input\InputInterface;
58592 use Symfony\Component\Console\Output\ConsoleOutputInterface;
58593 use Symfony\Component\Console\Output\OutputInterface;
58594 use Symfony\Component\Console\Question\ChoiceQuestion;
58595 use Symfony\Component\Console\Question\Question;
58596
58597
58598
58599
58600
58601
58602 class QuestionHelper extends Helper
58603 {
58604 private $inputStream;
58605 private static $shell;
58606 private static $stty;
58607
58608
58609
58610
58611
58612
58613
58614
58615 public function ask(InputInterface $input, OutputInterface $output, Question $question)
58616 {
58617 if ($output instanceof ConsoleOutputInterface) {
58618 $output = $output->getErrorOutput();
58619 }
58620
58621 if (!$input->isInteractive()) {
58622 $default = $question->getDefault();
58623
58624 if (null !== $default && $question instanceof ChoiceQuestion) {
58625 $choices = $question->getChoices();
58626
58627 if (!$question->isMultiselect()) {
58628 return isset($choices[$default]) ? $choices[$default] : $default;
58629 }
58630
58631 $default = explode(',', $default);
58632 foreach ($default as $k => $v) {
58633 $v = trim($v);
58634 $default[$k] = isset($choices[$v]) ? $choices[$v] : $v;
58635 }
58636 }
58637
58638 return $default;
58639 }
58640
58641 if (!$question->getValidator()) {
58642 return $this->doAsk($output, $question);
58643 }
58644
58645 $that = $this;
58646
58647 $interviewer = function () use ($output, $question, $that) {
58648 return $that->doAsk($output, $question);
58649 };
58650
58651 return $this->validateAttempts($interviewer, $output, $question);
58652 }
58653
58654
58655
58656
58657
58658
58659
58660
58661
58662
58663 public function setInputStream($stream)
58664 {
58665 if (!\is_resource($stream)) {
58666 throw new InvalidArgumentException('Input stream must be a valid resource.');
58667 }
58668
58669 $this->inputStream = $stream;
58670 }
58671
58672
58673
58674
58675
58676
58677 public function getInputStream()
58678 {
58679 return $this->inputStream;
58680 }
58681
58682
58683
58684
58685 public function getName()
58686 {
58687 return 'question';
58688 }
58689
58690
58691
58692
58693
58694
58695
58696
58697
58698
58699 public function doAsk(OutputInterface $output, Question $question)
58700 {
58701 $this->writePrompt($output, $question);
58702
58703 $inputStream = $this->inputStream ?: STDIN;
58704 $autocomplete = $question->getAutocompleterValues();
58705
58706 if (null === $autocomplete || !$this->hasSttyAvailable()) {
58707 $ret = false;
58708 if ($question->isHidden()) {
58709 try {
58710 $ret = trim($this->getHiddenResponse($output, $inputStream));
58711 } catch (RuntimeException $e) {
58712 if (!$question->isHiddenFallback()) {
58713 throw $e;
58714 }
58715 }
58716 }
58717
58718 if (false === $ret) {
58719 $ret = fgets($inputStream, 4096);
58720 if (false === $ret) {
58721 throw new RuntimeException('Aborted');
58722 }
58723 $ret = trim($ret);
58724 }
58725 } else {
58726 $ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
58727 }
58728
58729 $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
58730
58731 if ($normalizer = $question->getNormalizer()) {
58732 return $normalizer($ret);
58733 }
58734
58735 return $ret;
58736 }
58737
58738
58739
58740
58741 protected function writePrompt(OutputInterface $output, Question $question)
58742 {
58743 $message = $question->getQuestion();
58744
58745 if ($question instanceof ChoiceQuestion) {
58746 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
58747
58748 $messages = (array) $question->getQuestion();
58749 foreach ($question->getChoices() as $key => $value) {
58750 $width = $maxWidth - $this->strlen($key);
58751 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
58752 }
58753
58754 $output->writeln($messages);
58755
58756 $message = $question->getPrompt();
58757 }
58758
58759 $output->write($message);
58760 }
58761
58762
58763
58764
58765 protected function writeError(OutputInterface $output, \Exception $error)
58766 {
58767 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
58768 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
58769 } else {
58770 $message = '<error>'.$error->getMessage().'</error>';
58771 }
58772
58773 $output->writeln($message);
58774 }
58775
58776
58777
58778
58779
58780
58781
58782
58783
58784
58785
58786 private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
58787 {
58788 $ret = '';
58789
58790 $i = 0;
58791 $ofs = -1;
58792 $matches = $autocomplete;
58793 $numMatches = \count($matches);
58794
58795 $sttyMode = shell_exec('stty -g');
58796
58797
58798  shell_exec('stty -icanon -echo');
58799
58800
58801  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
58802
58803
58804  while (!feof($inputStream)) {
58805 $c = fread($inputStream, 1);
58806
58807
58808  if ("\177" === $c) {
58809 if (0 === $numMatches && 0 !== $i) {
58810 --$i;
58811
58812  $output->write("\033[1D");
58813 }
58814
58815 if (0 === $i) {
58816 $ofs = -1;
58817 $matches = $autocomplete;
58818 $numMatches = \count($matches);
58819 } else {
58820 $numMatches = 0;
58821 }
58822
58823
58824  $ret = substr($ret, 0, $i);
58825 } elseif ("\033" === $c) {
58826
58827  $c .= fread($inputStream, 2);
58828
58829
58830  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
58831 if ('A' === $c[2] && -1 === $ofs) {
58832 $ofs = 0;
58833 }
58834
58835 if (0 === $numMatches) {
58836 continue;
58837 }
58838
58839 $ofs += ('A' === $c[2]) ? -1 : 1;
58840 $ofs = ($numMatches + $ofs) % $numMatches;
58841 }
58842 } elseif (\ord($c) < 32) {
58843 if ("\t" === $c || "\n" === $c) {
58844 if ($numMatches > 0 && -1 !== $ofs) {
58845 $ret = $matches[$ofs];
58846
58847  $output->write(substr($ret, $i));
58848 $i = \strlen($ret);
58849 }
58850
58851 if ("\n" === $c) {
58852 $output->write($c);
58853 break;
58854 }
58855
58856 $numMatches = 0;
58857 }
58858
58859 continue;
58860 } else {
58861 $output->write($c);
58862 $ret .= $c;
58863 ++$i;
58864
58865 $numMatches = 0;
58866 $ofs = 0;
58867
58868 foreach ($autocomplete as $value) {
58869
58870  if (0 === strpos($value, $ret)) {
58871 $matches[$numMatches++] = $value;
58872 }
58873 }
58874 }
58875
58876
58877  $output->write("\033[K");
58878
58879 if ($numMatches > 0 && -1 !== $ofs) {
58880
58881  $output->write("\0337");
58882
58883  $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>');
58884
58885  $output->write("\0338");
58886 }
58887 }
58888
58889
58890  shell_exec(sprintf('stty %s', $sttyMode));
58891
58892 return $ret;
58893 }
58894
58895
58896
58897
58898
58899
58900
58901
58902
58903
58904
58905 private function getHiddenResponse(OutputInterface $output, $inputStream)
58906 {
58907 if ('\\' === \DIRECTORY_SEPARATOR) {
58908 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
58909
58910
58911  if ('phar:' === substr(__FILE__, 0, 5)) {
58912 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
58913 copy($exe, $tmpExe);
58914 $exe = $tmpExe;
58915 }
58916
58917 $value = rtrim(shell_exec($exe));
58918 $output->writeln('');
58919
58920 if (isset($tmpExe)) {
58921 unlink($tmpExe);
58922 }
58923
58924 return $value;
58925 }
58926
58927 if ($this->hasSttyAvailable()) {
58928 $sttyMode = shell_exec('stty -g');
58929
58930 shell_exec('stty -echo');
58931 $value = fgets($inputStream, 4096);
58932 shell_exec(sprintf('stty %s', $sttyMode));
58933
58934 if (false === $value) {
58935 throw new RuntimeException('Aborted');
58936 }
58937
58938 $value = trim($value);
58939 $output->writeln('');
58940
58941 return $value;
58942 }
58943
58944 if (false !== $shell = $this->getShell()) {
58945 $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword';
58946 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
58947 $value = rtrim(shell_exec($command));
58948 $output->writeln('');
58949
58950 return $value;
58951 }
58952
58953 throw new RuntimeException('Unable to hide the response.');
58954 }
58955
58956
58957
58958
58959
58960
58961
58962
58963
58964
58965
58966
58967 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
58968 {
58969 $error = null;
58970 $attempts = $question->getMaxAttempts();
58971 while (null === $attempts || $attempts--) {
58972 if (null !== $error) {
58973 $this->writeError($output, $error);
58974 }
58975
58976 try {
58977 return \call_user_func($question->getValidator(), $interviewer());
58978 } catch (RuntimeException $e) {
58979 throw $e;
58980 } catch (\Exception $error) {
58981 }
58982 }
58983
58984 throw $error;
58985 }
58986
58987
58988
58989
58990
58991
58992 private function getShell()
58993 {
58994 if (null !== self::$shell) {
58995 return self::$shell;
58996 }
58997
58998 self::$shell = false;
58999
59000 if (file_exists('/usr/bin/env')) {
59001
59002  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
59003 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
59004 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
59005 self::$shell = $sh;
59006 break;
59007 }
59008 }
59009 }
59010
59011 return self::$shell;
59012 }
59013
59014
59015
59016
59017
59018
59019 private function hasSttyAvailable()
59020 {
59021 if (null !== self::$stty) {
59022 return self::$stty;
59023 }
59024
59025 exec('stty 2>&1', $output, $exitcode);
59026
59027 return self::$stty = 0 === $exitcode;
59028 }
59029 }
59030 <?php
59031
59032
59033
59034
59035
59036
59037
59038
59039
59040
59041 namespace Symfony\Component\Console\Helper;
59042
59043 use Symfony\Component\Console\Exception\LogicException;
59044 use Symfony\Component\Console\Formatter\OutputFormatter;
59045 use Symfony\Component\Console\Input\InputInterface;
59046 use Symfony\Component\Console\Output\OutputInterface;
59047 use Symfony\Component\Console\Question\ChoiceQuestion;
59048 use Symfony\Component\Console\Question\ConfirmationQuestion;
59049 use Symfony\Component\Console\Question\Question;
59050 use Symfony\Component\Console\Style\SymfonyStyle;
59051
59052
59053
59054
59055
59056
59057 class SymfonyQuestionHelper extends QuestionHelper
59058 {
59059
59060
59061
59062 public function ask(InputInterface $input, OutputInterface $output, Question $question)
59063 {
59064 $validator = $question->getValidator();
59065 $question->setValidator(function ($value) use ($validator) {
59066 if (null !== $validator) {
59067 $value = $validator($value);
59068 } else {
59069
59070  if (!\is_array($value) && !\is_bool($value) && 0 === \strlen($value)) {
59071 throw new LogicException('A value is required.');
59072 }
59073 }
59074
59075 return $value;
59076 });
59077
59078 return parent::ask($input, $output, $question);
59079 }
59080
59081
59082
59083
59084 protected function writePrompt(OutputInterface $output, Question $question)
59085 {
59086 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
59087 $default = $question->getDefault();
59088
59089 switch (true) {
59090 case null === $default:
59091 $text = sprintf(' <info>%s</info>:', $text);
59092
59093 break;
59094
59095 case $question instanceof ConfirmationQuestion:
59096 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
59097
59098 break;
59099
59100 case $question instanceof ChoiceQuestion && $question->isMultiselect():
59101 $choices = $question->getChoices();
59102 $default = explode(',', $default);
59103
59104 foreach ($default as $key => $value) {
59105 $default[$key] = $choices[trim($value)];
59106 }
59107
59108 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
59109
59110 break;
59111
59112 case $question instanceof ChoiceQuestion:
59113 $choices = $question->getChoices();
59114 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default));
59115
59116 break;
59117
59118 default:
59119 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
59120 }
59121
59122 $output->writeln($text);
59123
59124 if ($question instanceof ChoiceQuestion) {
59125 $width = max(array_map('strlen', array_keys($question->getChoices())));
59126
59127 foreach ($question->getChoices() as $key => $value) {
59128 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
59129 }
59130 }
59131
59132 $output->write(' > ');
59133 }
59134
59135
59136
59137
59138 protected function writeError(OutputInterface $output, \Exception $error)
59139 {
59140 if ($output instanceof SymfonyStyle) {
59141 $output->newLine();
59142 $output->error($error->getMessage());
59143
59144 return;
59145 }
59146
59147 parent::writeError($output, $error);
59148 }
59149 }
59150 <?php
59151
59152
59153
59154
59155
59156
59157
59158
59159
59160
59161 namespace Symfony\Component\Console\Helper;
59162
59163 use Symfony\Component\Console\Exception\InvalidArgumentException;
59164 use Symfony\Component\Console\Output\OutputInterface;
59165
59166
59167
59168
59169
59170
59171
59172
59173
59174 class Table
59175 {
59176
59177
59178
59179 private $headers = array();
59180
59181
59182
59183
59184 private $rows = array();
59185
59186
59187
59188
59189 private $columnWidths = array();
59190
59191
59192
59193
59194
59195
59196 private $numberOfColumns;
59197
59198
59199
59200
59201 private $output;
59202
59203
59204
59205
59206 private $style;
59207
59208
59209
59210
59211 private $columnStyles = array();
59212
59213 private static $styles;
59214
59215 public function __construct(OutputInterface $output)
59216 {
59217 $this->output = $output;
59218
59219 if (!self::$styles) {
59220 self::$styles = self::initStyles();
59221 }
59222
59223 $this->setStyle('default');
59224 }
59225
59226
59227
59228
59229
59230
59231
59232 public static function setStyleDefinition($name, TableStyle $style)
59233 {
59234 if (!self::$styles) {
59235 self::$styles = self::initStyles();
59236 }
59237
59238 self::$styles[$name] = $style;
59239 }
59240
59241
59242
59243
59244
59245
59246
59247
59248 public static function getStyleDefinition($name)
59249 {
59250 if (!self::$styles) {
59251 self::$styles = self::initStyles();
59252 }
59253
59254 if (isset(self::$styles[$name])) {
59255 return self::$styles[$name];
59256 }
59257
59258 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
59259 }
59260
59261
59262
59263
59264
59265
59266
59267
59268 public function setStyle($name)
59269 {
59270 $this->style = $this->resolveStyle($name);
59271
59272 return $this;
59273 }
59274
59275
59276
59277
59278
59279
59280 public function getStyle()
59281 {
59282 return $this->style;
59283 }
59284
59285
59286
59287
59288
59289
59290
59291
59292
59293 public function setColumnStyle($columnIndex, $name)
59294 {
59295 $columnIndex = (int) $columnIndex;
59296
59297 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
59298
59299 return $this;
59300 }
59301
59302
59303
59304
59305
59306
59307
59308
59309
59310
59311 public function getColumnStyle($columnIndex)
59312 {
59313 if (isset($this->columnStyles[$columnIndex])) {
59314 return $this->columnStyles[$columnIndex];
59315 }
59316
59317 return $this->getStyle();
59318 }
59319
59320 public function setHeaders(array $headers)
59321 {
59322 $headers = array_values($headers);
59323 if (!empty($headers) && !\is_array($headers[0])) {
59324 $headers = array($headers);
59325 }
59326
59327 $this->headers = $headers;
59328
59329 return $this;
59330 }
59331
59332 public function setRows(array $rows)
59333 {
59334 $this->rows = array();
59335
59336 return $this->addRows($rows);
59337 }
59338
59339 public function addRows(array $rows)
59340 {
59341 foreach ($rows as $row) {
59342 $this->addRow($row);
59343 }
59344
59345 return $this;
59346 }
59347
59348 public function addRow($row)
59349 {
59350 if ($row instanceof TableSeparator) {
59351 $this->rows[] = $row;
59352
59353 return $this;
59354 }
59355
59356 if (!\is_array($row)) {
59357 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
59358 }
59359
59360 $this->rows[] = array_values($row);
59361
59362 return $this;
59363 }
59364
59365 public function setRow($column, array $row)
59366 {
59367 $this->rows[$column] = $row;
59368
59369 return $this;
59370 }
59371
59372
59373
59374
59375
59376
59377
59378
59379
59380
59381
59382
59383
59384
59385 public function render()
59386 {
59387 $this->calculateNumberOfColumns();
59388 $rows = $this->buildTableRows($this->rows);
59389 $headers = $this->buildTableRows($this->headers);
59390
59391 $this->calculateColumnsWidth(array_merge($headers, $rows));
59392
59393 $this->renderRowSeparator();
59394 if (!empty($headers)) {
59395 foreach ($headers as $header) {
59396 $this->renderRow($header, $this->style->getCellHeaderFormat());
59397 $this->renderRowSeparator();
59398 }
59399 }
59400 foreach ($rows as $row) {
59401 if ($row instanceof TableSeparator) {
59402 $this->renderRowSeparator();
59403 } else {
59404 $this->renderRow($row, $this->style->getCellRowFormat());
59405 }
59406 }
59407 if (!empty($rows)) {
59408 $this->renderRowSeparator();
59409 }
59410
59411 $this->cleanup();
59412 }
59413
59414
59415
59416
59417
59418
59419
59420
59421 private function renderRowSeparator()
59422 {
59423 if (0 === $count = $this->numberOfColumns) {
59424 return;
59425 }
59426
59427 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
59428 return;
59429 }
59430
59431 $markup = $this->style->getCrossingChar();
59432 for ($column = 0; $column < $count; ++$column) {
59433 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
59434 }
59435
59436 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
59437 }
59438
59439
59440
59441
59442 private function renderColumnSeparator()
59443 {
59444 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
59445 }
59446
59447
59448
59449
59450
59451
59452
59453
59454
59455
59456
59457 private function renderRow(array $row, $cellFormat)
59458 {
59459 if (empty($row)) {
59460 return;
59461 }
59462
59463 $rowContent = $this->renderColumnSeparator();
59464 foreach ($this->getRowColumns($row) as $column) {
59465 $rowContent .= $this->renderCell($row, $column, $cellFormat);
59466 $rowContent .= $this->renderColumnSeparator();
59467 }
59468 $this->output->writeln($rowContent);
59469 }
59470
59471
59472
59473
59474
59475
59476
59477
59478 private function renderCell(array $row, $column, $cellFormat)
59479 {
59480 $cell = isset($row[$column]) ? $row[$column] : '';
59481 $width = $this->columnWidths[$column];
59482 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
59483
59484  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
59485 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
59486 }
59487 }
59488
59489
59490  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
59491 $width += \strlen($cell) - mb_strwidth($cell, $encoding);
59492 }
59493
59494 $style = $this->getColumnStyle($column);
59495
59496 if ($cell instanceof TableSeparator) {
59497 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
59498 }
59499
59500 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
59501 $content = sprintf($style->getCellRowContentFormat(), $cell);
59502
59503 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
59504 }
59505
59506
59507
59508
59509 private function calculateNumberOfColumns()
59510 {
59511 if (null !== $this->numberOfColumns) {
59512 return;
59513 }
59514
59515 $columns = array(0);
59516 foreach (array_merge($this->headers, $this->rows) as $row) {
59517 if ($row instanceof TableSeparator) {
59518 continue;
59519 }
59520
59521 $columns[] = $this->getNumberOfColumns($row);
59522 }
59523
59524 $this->numberOfColumns = max($columns);
59525 }
59526
59527 private function buildTableRows($rows)
59528 {
59529 $unmergedRows = array();
59530 for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
59531 $rows = $this->fillNextRows($rows, $rowKey);
59532
59533
59534  foreach ($rows[$rowKey] as $column => $cell) {
59535 if (!strstr($cell, "\n")) {
59536 continue;
59537 }
59538 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
59539 foreach ($lines as $lineKey => $line) {
59540 if ($cell instanceof TableCell) {
59541 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
59542 }
59543 if (0 === $lineKey) {
59544 $rows[$rowKey][$column] = $line;
59545 } else {
59546 $unmergedRows[$rowKey][$lineKey][$column] = $line;
59547 }
59548 }
59549 }
59550 }
59551
59552 $tableRows = array();
59553 foreach ($rows as $rowKey => $row) {
59554 $tableRows[] = $this->fillCells($row);
59555 if (isset($unmergedRows[$rowKey])) {
59556 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
59557 }
59558 }
59559
59560 return $tableRows;
59561 }
59562
59563
59564
59565
59566
59567
59568
59569
59570
59571 private function fillNextRows(array $rows, $line)
59572 {
59573 $unmergedRows = array();
59574 foreach ($rows[$line] as $column => $cell) {
59575 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
59576 $nbLines = $cell->getRowspan() - 1;
59577 $lines = array($cell);
59578 if (strstr($cell, "\n")) {
59579 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
59580 $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
59581
59582 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
59583 unset($lines[0]);
59584 }
59585
59586
59587  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
59588 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
59589 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
59590 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
59591 if ($nbLines === $unmergedRowKey - $line) {
59592 break;
59593 }
59594 }
59595 }
59596 }
59597
59598 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
59599
59600  if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
59601 foreach ($unmergedRow as $cellKey => $cell) {
59602
59603  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
59604 }
59605 } else {
59606 $row = $this->copyRow($rows, $unmergedRowKey - 1);
59607 foreach ($unmergedRow as $column => $cell) {
59608 if (!empty($cell)) {
59609 $row[$column] = $unmergedRow[$column];
59610 }
59611 }
59612 array_splice($rows, $unmergedRowKey, 0, array($row));
59613 }
59614 }
59615
59616 return $rows;
59617 }
59618
59619
59620
59621
59622
59623
59624 private function fillCells($row)
59625 {
59626 $newRow = array();
59627 foreach ($row as $column => $cell) {
59628 $newRow[] = $cell;
59629 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
59630 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
59631
59632  $newRow[] = '';
59633 }
59634 }
59635 }
59636
59637 return $newRow ?: $row;
59638 }
59639
59640
59641
59642
59643
59644
59645
59646 private function copyRow(array $rows, $line)
59647 {
59648 $row = $rows[$line];
59649 foreach ($row as $cellKey => $cellValue) {
59650 $row[$cellKey] = '';
59651 if ($cellValue instanceof TableCell) {
59652 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
59653 }
59654 }
59655
59656 return $row;
59657 }
59658
59659
59660
59661
59662
59663
59664 private function getNumberOfColumns(array $row)
59665 {
59666 $columns = \count($row);
59667 foreach ($row as $column) {
59668 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
59669 }
59670
59671 return $columns;
59672 }
59673
59674
59675
59676
59677
59678
59679 private function getRowColumns(array $row)
59680 {
59681 $columns = range(0, $this->numberOfColumns - 1);
59682 foreach ($row as $cellKey => $cell) {
59683 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
59684
59685  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
59686 }
59687 }
59688
59689 return $columns;
59690 }
59691
59692
59693
59694
59695
59696
59697 private function calculateColumnsWidth($rows)
59698 {
59699 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
59700 $lengths = array();
59701 foreach ($rows as $row) {
59702 if ($row instanceof TableSeparator) {
59703 continue;
59704 }
59705
59706 foreach ($row as $i => $cell) {
59707 if ($cell instanceof TableCell) {
59708 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
59709 $textLength = Helper::strlen($textContent);
59710 if ($textLength > 0) {
59711 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
59712 foreach ($contentColumns as $position => $content) {
59713 $row[$i + $position] = $content;
59714 }
59715 }
59716 }
59717 }
59718
59719 $lengths[] = $this->getCellWidth($row, $column);
59720 }
59721
59722 $this->columnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2;
59723 }
59724 }
59725
59726
59727
59728
59729
59730
59731 private function getColumnSeparatorWidth()
59732 {
59733 return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
59734 }
59735
59736
59737
59738
59739
59740
59741
59742
59743
59744 private function getCellWidth(array $row, $column)
59745 {
59746 if (isset($row[$column])) {
59747 $cell = $row[$column];
59748 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
59749
59750 return $cellWidth;
59751 }
59752
59753 return 0;
59754 }
59755
59756
59757
59758
59759 private function cleanup()
59760 {
59761 $this->columnWidths = array();
59762 $this->numberOfColumns = null;
59763 }
59764
59765 private static function initStyles()
59766 {
59767 $borderless = new TableStyle();
59768 $borderless
59769 ->setHorizontalBorderChar('=')
59770 ->setVerticalBorderChar(' ')
59771 ->setCrossingChar(' ')
59772 ;
59773
59774 $compact = new TableStyle();
59775 $compact
59776 ->setHorizontalBorderChar('')
59777 ->setVerticalBorderChar(' ')
59778 ->setCrossingChar('')
59779 ->setCellRowContentFormat('%s')
59780 ;
59781
59782 $styleGuide = new TableStyle();
59783 $styleGuide
59784 ->setHorizontalBorderChar('-')
59785 ->setVerticalBorderChar(' ')
59786 ->setCrossingChar(' ')
59787 ->setCellHeaderFormat('%s')
59788 ;
59789
59790 return array(
59791 'default' => new TableStyle(),
59792 'borderless' => $borderless,
59793 'compact' => $compact,
59794 'symfony-style-guide' => $styleGuide,
59795 );
59796 }
59797
59798 private function resolveStyle($name)
59799 {
59800 if ($name instanceof TableStyle) {
59801 return $name;
59802 }
59803
59804 if (isset(self::$styles[$name])) {
59805 return self::$styles[$name];
59806 }
59807
59808 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
59809 }
59810 }
59811 <?php
59812
59813
59814
59815
59816
59817
59818
59819
59820
59821
59822 namespace Symfony\Component\Console\Helper;
59823
59824 use Symfony\Component\Console\Exception\InvalidArgumentException;
59825
59826
59827
59828
59829 class TableCell
59830 {
59831 private $value;
59832 private $options = array(
59833 'rowspan' => 1,
59834 'colspan' => 1,
59835 );
59836
59837
59838
59839
59840
59841 public function __construct($value = '', array $options = array())
59842 {
59843 if (is_numeric($value) && !\is_string($value)) {
59844 $value = (string) $value;
59845 }
59846
59847 $this->value = $value;
59848
59849
59850  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
59851 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
59852 }
59853
59854 $this->options = array_merge($this->options, $options);
59855 }
59856
59857
59858
59859
59860
59861
59862 public function __toString()
59863 {
59864 return $this->value;
59865 }
59866
59867
59868
59869
59870
59871
59872 public function getColspan()
59873 {
59874 return (int) $this->options['colspan'];
59875 }
59876
59877
59878
59879
59880
59881
59882 public function getRowspan()
59883 {
59884 return (int) $this->options['rowspan'];
59885 }
59886 }
59887 <?php
59888
59889
59890
59891
59892
59893
59894
59895
59896
59897
59898 namespace Symfony\Component\Console\Helper;
59899
59900 use Symfony\Component\Console\Exception\InvalidArgumentException;
59901 use Symfony\Component\Console\Output\NullOutput;
59902 use Symfony\Component\Console\Output\OutputInterface;
59903
59904
59905
59906
59907
59908
59909
59910
59911
59912
59913 class TableHelper extends Helper
59914 {
59915 const LAYOUT_DEFAULT = 0;
59916 const LAYOUT_BORDERLESS = 1;
59917 const LAYOUT_COMPACT = 2;
59918
59919 private $table;
59920
59921 public function __construct($triggerDeprecationError = true)
59922 {
59923 if ($triggerDeprecationError) {
59924 @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);
59925 }
59926
59927 $this->table = new Table(new NullOutput());
59928 }
59929
59930
59931
59932
59933
59934
59935
59936
59937
59938
59939 public function setLayout($layout)
59940 {
59941 switch ($layout) {
59942 case self::LAYOUT_BORDERLESS:
59943 $this->table->setStyle('borderless');
59944 break;
59945
59946 case self::LAYOUT_COMPACT:
59947 $this->table->setStyle('compact');
59948 break;
59949
59950 case self::LAYOUT_DEFAULT:
59951 $this->table->setStyle('default');
59952 break;
59953
59954 default:
59955 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
59956 }
59957
59958 return $this;
59959 }
59960
59961 public function setHeaders(array $headers)
59962 {
59963 $this->table->setHeaders($headers);
59964
59965 return $this;
59966 }
59967
59968 public function setRows(array $rows)
59969 {
59970 $this->table->setRows($rows);
59971
59972 return $this;
59973 }
59974
59975 public function addRows(array $rows)
59976 {
59977 $this->table->addRows($rows);
59978
59979 return $this;
59980 }
59981
59982 public function addRow(array $row)
59983 {
59984 $this->table->addRow($row);
59985
59986 return $this;
59987 }
59988
59989 public function setRow($column, array $row)
59990 {
59991 $this->table->setRow($column, $row);
59992
59993 return $this;
59994 }
59995
59996
59997
59998
59999
60000
60001
60002
60003 public function setPaddingChar($paddingChar)
60004 {
60005 $this->table->getStyle()->setPaddingChar($paddingChar);
60006
60007 return $this;
60008 }
60009
60010
60011
60012
60013
60014
60015
60016
60017 public function setHorizontalBorderChar($horizontalBorderChar)
60018 {
60019 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
60020
60021 return $this;
60022 }
60023
60024
60025
60026
60027
60028
60029
60030
60031 public function setVerticalBorderChar($verticalBorderChar)
60032 {
60033 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
60034
60035 return $this;
60036 }
60037
60038
60039
60040
60041
60042
60043
60044
60045 public function setCrossingChar($crossingChar)
60046 {
60047 $this->table->getStyle()->setCrossingChar($crossingChar);
60048
60049 return $this;
60050 }
60051
60052
60053
60054
60055
60056
60057
60058
60059 public function setCellHeaderFormat($cellHeaderFormat)
60060 {
60061 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
60062
60063 return $this;
60064 }
60065
60066
60067
60068
60069
60070
60071
60072
60073 public function setCellRowFormat($cellRowFormat)
60074 {
60075 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
60076
60077 return $this;
60078 }
60079
60080
60081
60082
60083
60084
60085
60086
60087 public function setCellRowContentFormat($cellRowContentFormat)
60088 {
60089 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
60090
60091 return $this;
60092 }
60093
60094
60095
60096
60097
60098
60099
60100
60101 public function setBorderFormat($borderFormat)
60102 {
60103 $this->table->getStyle()->setBorderFormat($borderFormat);
60104
60105 return $this;
60106 }
60107
60108
60109
60110
60111
60112
60113
60114
60115 public function setPadType($padType)
60116 {
60117 $this->table->getStyle()->setPadType($padType);
60118
60119 return $this;
60120 }
60121
60122
60123
60124
60125
60126
60127
60128
60129
60130
60131
60132
60133
60134 public function render(OutputInterface $output)
60135 {
60136 $p = new \ReflectionProperty($this->table, 'output');
60137 $p->setAccessible(true);
60138 $p->setValue($this->table, $output);
60139
60140 $this->table->render();
60141 }
60142
60143
60144
60145
60146 public function getName()
60147 {
60148 return 'table';
60149 }
60150 }
60151 <?php
60152
60153
60154
60155
60156
60157
60158
60159
60160
60161
60162 namespace Symfony\Component\Console\Helper;
60163
60164
60165
60166
60167
60168
60169 class TableSeparator extends TableCell
60170 {
60171 public function __construct(array $options = array())
60172 {
60173 parent::__construct('', $options);
60174 }
60175 }
60176 <?php
60177
60178
60179
60180
60181
60182
60183
60184
60185
60186
60187 namespace Symfony\Component\Console\Helper;
60188
60189 use Symfony\Component\Console\Exception\InvalidArgumentException;
60190 use Symfony\Component\Console\Exception\LogicException;
60191
60192
60193
60194
60195
60196
60197
60198 class TableStyle
60199 {
60200 private $paddingChar = ' ';
60201 private $horizontalBorderChar = '-';
60202 private $verticalBorderChar = '|';
60203 private $crossingChar = '+';
60204 private $cellHeaderFormat = '<info>%s</info>';
60205 private $cellRowFormat = '%s';
60206 private $cellRowContentFormat = ' %s ';
60207 private $borderFormat = '%s';
60208 private $padType = STR_PAD_RIGHT;
60209
60210
60211
60212
60213
60214
60215
60216
60217 public function setPaddingChar($paddingChar)
60218 {
60219 if (!$paddingChar) {
60220 throw new LogicException('The padding char must not be empty');
60221 }
60222
60223 $this->paddingChar = $paddingChar;
60224
60225 return $this;
60226 }
60227
60228
60229
60230
60231
60232
60233 public function getPaddingChar()
60234 {
60235 return $this->paddingChar;
60236 }
60237
60238
60239
60240
60241
60242
60243
60244
60245 public function setHorizontalBorderChar($horizontalBorderChar)
60246 {
60247 $this->horizontalBorderChar = $horizontalBorderChar;
60248
60249 return $this;
60250 }
60251
60252
60253
60254
60255
60256
60257 public function getHorizontalBorderChar()
60258 {
60259 return $this->horizontalBorderChar;
60260 }
60261
60262
60263
60264
60265
60266
60267
60268
60269 public function setVerticalBorderChar($verticalBorderChar)
60270 {
60271 $this->verticalBorderChar = $verticalBorderChar;
60272
60273 return $this;
60274 }
60275
60276
60277
60278
60279
60280
60281 public function getVerticalBorderChar()
60282 {
60283 return $this->verticalBorderChar;
60284 }
60285
60286
60287
60288
60289
60290
60291
60292
60293 public function setCrossingChar($crossingChar)
60294 {
60295 $this->crossingChar = $crossingChar;
60296
60297 return $this;
60298 }
60299
60300
60301
60302
60303
60304
60305 public function getCrossingChar()
60306 {
60307 return $this->crossingChar;
60308 }
60309
60310
60311
60312
60313
60314
60315
60316
60317 public function setCellHeaderFormat($cellHeaderFormat)
60318 {
60319 $this->cellHeaderFormat = $cellHeaderFormat;
60320
60321 return $this;
60322 }
60323
60324
60325
60326
60327
60328
60329 public function getCellHeaderFormat()
60330 {
60331 return $this->cellHeaderFormat;
60332 }
60333
60334
60335
60336
60337
60338
60339
60340
60341 public function setCellRowFormat($cellRowFormat)
60342 {
60343 $this->cellRowFormat = $cellRowFormat;
60344
60345 return $this;
60346 }
60347
60348
60349
60350
60351
60352
60353 public function getCellRowFormat()
60354 {
60355 return $this->cellRowFormat;
60356 }
60357
60358
60359
60360
60361
60362
60363
60364
60365 public function setCellRowContentFormat($cellRowContentFormat)
60366 {
60367 $this->cellRowContentFormat = $cellRowContentFormat;
60368
60369 return $this;
60370 }
60371
60372
60373
60374
60375
60376
60377 public function getCellRowContentFormat()
60378 {
60379 return $this->cellRowContentFormat;
60380 }
60381
60382
60383
60384
60385
60386
60387
60388
60389 public function setBorderFormat($borderFormat)
60390 {
60391 $this->borderFormat = $borderFormat;
60392
60393 return $this;
60394 }
60395
60396
60397
60398
60399
60400
60401 public function getBorderFormat()
60402 {
60403 return $this->borderFormat;
60404 }
60405
60406
60407
60408
60409
60410
60411
60412
60413 public function setPadType($padType)
60414 {
60415 if (!\in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
60416 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
60417 }
60418
60419 $this->padType = $padType;
60420
60421 return $this;
60422 }
60423
60424
60425
60426
60427
60428
60429 public function getPadType()
60430 {
60431 return $this->padType;
60432 }
60433 }
60434 <?php
60435
60436
60437
60438
60439
60440
60441
60442
60443
60444
60445 namespace Symfony\Component\Console\Input;
60446
60447 use Symfony\Component\Console\Exception\RuntimeException;
60448
60449
60450
60451
60452
60453
60454
60455
60456
60457
60458
60459
60460
60461
60462
60463
60464
60465
60466
60467
60468
60469
60470
60471
60472
60473
60474 class ArgvInput extends Input
60475 {
60476 private $tokens;
60477 private $parsed;
60478
60479
60480
60481
60482
60483 public function __construct(array $argv = null, InputDefinition $definition = null)
60484 {
60485 if (null === $argv) {
60486 $argv = $_SERVER['argv'];
60487 }
60488
60489
60490  array_shift($argv);
60491
60492 $this->tokens = $argv;
60493
60494 parent::__construct($definition);
60495 }
60496
60497 protected function setTokens(array $tokens)
60498 {
60499 $this->tokens = $tokens;
60500 }
60501
60502
60503
60504
60505 protected function parse()
60506 {
60507 $parseOptions = true;
60508 $this->parsed = $this->tokens;
60509 while (null !== $token = array_shift($this->parsed)) {
60510 if ($parseOptions && '' == $token) {
60511 $this->parseArgument($token);
60512 } elseif ($parseOptions && '--' == $token) {
60513 $parseOptions = false;
60514 } elseif ($parseOptions && 0 === strpos($token, '--')) {
60515 $this->parseLongOption($token);
60516 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
60517 $this->parseShortOption($token);
60518 } else {
60519 $this->parseArgument($token);
60520 }
60521 }
60522 }
60523
60524
60525
60526
60527
60528
60529 private function parseShortOption($token)
60530 {
60531 $name = substr($token, 1);
60532
60533 if (\strlen($name) > 1) {
60534 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
60535
60536  $this->addShortOption($name[0], substr($name, 1));
60537 } else {
60538 $this->parseShortOptionSet($name);
60539 }
60540 } else {
60541 $this->addShortOption($name, null);
60542 }
60543 }
60544
60545
60546
60547
60548
60549
60550
60551
60552 private function parseShortOptionSet($name)
60553 {
60554 $len = \strlen($name);
60555 for ($i = 0; $i < $len; ++$i) {
60556 if (!$this->definition->hasShortcut($name[$i])) {
60557 $encoding = mb_detect_encoding($name, null, true);
60558 throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
60559 }
60560
60561 $option = $this->definition->getOptionForShortcut($name[$i]);
60562 if ($option->acceptValue()) {
60563 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
60564
60565 break;
60566 } else {
60567 $this->addLongOption($option->getName(), null);
60568 }
60569 }
60570 }
60571
60572
60573
60574
60575
60576
60577 private function parseLongOption($token)
60578 {
60579 $name = substr($token, 2);
60580
60581 if (false !== $pos = strpos($name, '=')) {
60582 if (0 === \strlen($value = substr($name, $pos + 1))) {
60583 array_unshift($this->parsed, null);
60584 }
60585 $this->addLongOption(substr($name, 0, $pos), $value);
60586 } else {
60587 $this->addLongOption($name, null);
60588 }
60589 }
60590
60591
60592
60593
60594
60595
60596
60597
60598 private function parseArgument($token)
60599 {
60600 $c = \count($this->arguments);
60601
60602
60603  if ($this->definition->hasArgument($c)) {
60604 $arg = $this->definition->getArgument($c);
60605 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
60606
60607
60608  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
60609 $arg = $this->definition->getArgument($c - 1);
60610 $this->arguments[$arg->getName()][] = $token;
60611
60612
60613  } else {
60614 $all = $this->definition->getArguments();
60615 if (\count($all)) {
60616 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
60617 }
60618
60619 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
60620 }
60621 }
60622
60623
60624
60625
60626
60627
60628
60629
60630
60631 private function addShortOption($shortcut, $value)
60632 {
60633 if (!$this->definition->hasShortcut($shortcut)) {
60634 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
60635 }
60636
60637 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
60638 }
60639
60640
60641
60642
60643
60644
60645
60646
60647
60648 private function addLongOption($name, $value)
60649 {
60650 if (!$this->definition->hasOption($name)) {
60651 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
60652 }
60653
60654 $option = $this->definition->getOption($name);
60655
60656
60657  if (!isset($value[0])) {
60658 $value = null;
60659 }
60660
60661 if (null !== $value && !$option->acceptValue()) {
60662 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
60663 }
60664
60665 if (null === $value && $option->acceptValue() && \count($this->parsed)) {
60666
60667  
60668  $next = array_shift($this->parsed);
60669 if (isset($next[0]) && '-' !== $next[0]) {
60670 $value = $next;
60671 } elseif (empty($next)) {
60672 $value = null;
60673 } else {
60674 array_unshift($this->parsed, $next);
60675 }
60676 }
60677
60678 if (null === $value) {
60679 if ($option->isValueRequired()) {
60680 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
60681 }
60682
60683 if (!$option->isArray()) {
60684 $value = $option->isValueOptional() ? $option->getDefault() : true;
60685 }
60686 }
60687
60688 if ($option->isArray()) {
60689 $this->options[$name][] = $value;
60690 } else {
60691 $this->options[$name] = $value;
60692 }
60693 }
60694
60695
60696
60697
60698 public function getFirstArgument()
60699 {
60700 foreach ($this->tokens as $token) {
60701 if ($token && '-' === $token[0]) {
60702 continue;
60703 }
60704
60705 return $token;
60706 }
60707 }
60708
60709
60710
60711
60712 public function hasParameterOption($values)
60713 {
60714 $values = (array) $values;
60715
60716 foreach ($this->tokens as $token) {
60717 foreach ($values as $value) {
60718
60719  
60720  
60721  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
60722 if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) {
60723 return true;
60724 }
60725 }
60726 }
60727
60728 return false;
60729 }
60730
60731
60732
60733
60734 public function getParameterOption($values, $default = false)
60735 {
60736 $values = (array) $values;
60737 $tokens = $this->tokens;
60738
60739 while (0 < \count($tokens)) {
60740 $token = array_shift($tokens);
60741
60742 foreach ($values as $value) {
60743 if ($token === $value) {
60744 return array_shift($tokens);
60745 }
60746
60747  
60748  
60749  $leading = 0 === strpos($value, '--') ? $value.'=' : $value;
60750 if ('' !== $leading && 0 === strpos($token, $leading)) {
60751 return substr($token, \strlen($leading));
60752 }
60753 }
60754 }
60755
60756 return $default;
60757 }
60758
60759
60760
60761
60762
60763
60764 public function __toString()
60765 {
60766 $self = $this;
60767 $tokens = array_map(function ($token) use ($self) {
60768 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
60769 return $match[1].$self->escapeToken($match[2]);
60770 }
60771
60772 if ($token && '-' !== $token[0]) {
60773 return $self->escapeToken($token);
60774 }
60775
60776 return $token;
60777 }, $this->tokens);
60778
60779 return implode(' ', $tokens);
60780 }
60781 }
60782 <?php
60783
60784
60785
60786
60787
60788
60789
60790
60791
60792
60793 namespace Symfony\Component\Console\Input;
60794
60795 use Symfony\Component\Console\Exception\InvalidArgumentException;
60796 use Symfony\Component\Console\Exception\InvalidOptionException;
60797
60798
60799
60800
60801
60802
60803
60804
60805
60806
60807 class ArrayInput extends Input
60808 {
60809 private $parameters;
60810
60811 public function __construct(array $parameters, InputDefinition $definition = null)
60812 {
60813 $this->parameters = $parameters;
60814
60815 parent::__construct($definition);
60816 }
60817
60818
60819
60820
60821 public function getFirstArgument()
60822 {
60823 foreach ($this->parameters as $key => $value) {
60824 if ($key && '-' === $key[0]) {
60825 continue;
60826 }
60827
60828 return $value;
60829 }
60830 }
60831
60832
60833
60834
60835 public function hasParameterOption($values)
60836 {
60837 $values = (array) $values;
60838
60839 foreach ($this->parameters as $k => $v) {
60840 if (!\is_int($k)) {
60841 $v = $k;
60842 }
60843
60844 if (\in_array($v, $values)) {
60845 return true;
60846 }
60847 }
60848
60849 return false;
60850 }
60851
60852
60853
60854
60855 public function getParameterOption($values, $default = false)
60856 {
60857 $values = (array) $values;
60858
60859 foreach ($this->parameters as $k => $v) {
60860 if (\is_int($k)) {
60861 if (\in_array($v, $values)) {
60862 return true;
60863 }
60864 } elseif (\in_array($k, $values)) {
60865 return $v;
60866 }
60867 }
60868
60869 return $default;
60870 }
60871
60872
60873
60874
60875
60876
60877 public function __toString()
60878 {
60879 $params = array();
60880 foreach ($this->parameters as $param => $val) {
60881 if ($param && '-' === $param[0]) {
60882 if (\is_array($val)) {
60883 foreach ($val as $v) {
60884 $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : '');
60885 }
60886 } else {
60887 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
60888 }
60889 } else {
60890 $params[] = \is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val);
60891 }
60892 }
60893
60894 return implode(' ', $params);
60895 }
60896
60897
60898
60899
60900 protected function parse()
60901 {
60902 foreach ($this->parameters as $key => $value) {
60903 if (0 === strpos($key, '--')) {
60904 $this->addLongOption(substr($key, 2), $value);
60905 } elseif ('-' === $key[0]) {
60906 $this->addShortOption(substr($key, 1), $value);
60907 } else {
60908 $this->addArgument($key, $value);
60909 }
60910 }
60911 }
60912
60913
60914
60915
60916
60917
60918
60919
60920
60921 private function addShortOption($shortcut, $value)
60922 {
60923 if (!$this->definition->hasShortcut($shortcut)) {
60924 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
60925 }
60926
60927 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
60928 }
60929
60930
60931
60932
60933
60934
60935
60936
60937
60938
60939 private function addLongOption($name, $value)
60940 {
60941 if (!$this->definition->hasOption($name)) {
60942 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
60943 }
60944
60945 $option = $this->definition->getOption($name);
60946
60947 if (null === $value) {
60948 if ($option->isValueRequired()) {
60949 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
60950 }
60951
60952 $value = $option->isValueOptional() ? $option->getDefault() : true;
60953 }
60954
60955 $this->options[$name] = $value;
60956 }
60957
60958
60959
60960
60961
60962
60963
60964
60965
60966 private function addArgument($name, $value)
60967 {
60968 if (!$this->definition->hasArgument($name)) {
60969 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
60970 }
60971
60972 $this->arguments[$name] = $value;
60973 }
60974 }
60975 <?php
60976
60977
60978
60979
60980
60981
60982
60983
60984
60985
60986 namespace Symfony\Component\Console\Input;
60987
60988 use Symfony\Component\Console\Exception\InvalidArgumentException;
60989 use Symfony\Component\Console\Exception\RuntimeException;
60990
60991
60992
60993
60994
60995
60996
60997
60998
60999
61000
61001
61002 abstract class Input implements InputInterface
61003 {
61004 protected $definition;
61005 protected $options = array();
61006 protected $arguments = array();
61007 protected $interactive = true;
61008
61009 public function __construct(InputDefinition $definition = null)
61010 {
61011 if (null === $definition) {
61012 $this->definition = new InputDefinition();
61013 } else {
61014 $this->bind($definition);
61015 $this->validate();
61016 }
61017 }
61018
61019
61020
61021
61022 public function bind(InputDefinition $definition)
61023 {
61024 $this->arguments = array();
61025 $this->options = array();
61026 $this->definition = $definition;
61027
61028 $this->parse();
61029 }
61030
61031
61032
61033
61034 abstract protected function parse();
61035
61036
61037
61038
61039 public function validate()
61040 {
61041 $definition = $this->definition;
61042 $givenArguments = $this->arguments;
61043
61044 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
61045 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
61046 });
61047
61048 if (\count($missingArguments) > 0) {
61049 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
61050 }
61051 }
61052
61053
61054
61055
61056 public function isInteractive()
61057 {
61058 return $this->interactive;
61059 }
61060
61061
61062
61063
61064 public function setInteractive($interactive)
61065 {
61066 $this->interactive = (bool) $interactive;
61067 }
61068
61069
61070
61071
61072 public function getArguments()
61073 {
61074 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
61075 }
61076
61077
61078
61079
61080 public function getArgument($name)
61081 {
61082 if (!$this->definition->hasArgument($name)) {
61083 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
61084 }
61085
61086 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
61087 }
61088
61089
61090
61091
61092 public function setArgument($name, $value)
61093 {
61094 if (!$this->definition->hasArgument($name)) {
61095 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
61096 }
61097
61098 $this->arguments[$name] = $value;
61099 }
61100
61101
61102
61103
61104 public function hasArgument($name)
61105 {
61106 return $this->definition->hasArgument($name);
61107 }
61108
61109
61110
61111
61112 public function getOptions()
61113 {
61114 return array_merge($this->definition->getOptionDefaults(), $this->options);
61115 }
61116
61117
61118
61119
61120 public function getOption($name)
61121 {
61122 if (!$this->definition->hasOption($name)) {
61123 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
61124 }
61125
61126 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
61127 }
61128
61129
61130
61131
61132 public function setOption($name, $value)
61133 {
61134 if (!$this->definition->hasOption($name)) {
61135 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
61136 }
61137
61138 $this->options[$name] = $value;
61139 }
61140
61141
61142
61143
61144 public function hasOption($name)
61145 {
61146 return $this->definition->hasOption($name);
61147 }
61148
61149
61150
61151
61152
61153
61154
61155
61156 public function escapeToken($token)
61157 {
61158 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
61159 }
61160 }
61161 <?php
61162
61163
61164
61165
61166
61167
61168
61169
61170
61171
61172 namespace Symfony\Component\Console\Input;
61173
61174 use Symfony\Component\Console\Exception\InvalidArgumentException;
61175 use Symfony\Component\Console\Exception\LogicException;
61176
61177
61178
61179
61180
61181
61182 class InputArgument
61183 {
61184 const REQUIRED = 1;
61185 const OPTIONAL = 2;
61186 const IS_ARRAY = 4;
61187
61188 private $name;
61189 private $mode;
61190 private $default;
61191 private $description;
61192
61193
61194
61195
61196
61197
61198
61199
61200
61201 public function __construct($name, $mode = null, $description = '', $default = null)
61202 {
61203 if (null === $mode) {
61204 $mode = self::OPTIONAL;
61205 } elseif (!\is_int($mode) || $mode > 7 || $mode < 1) {
61206 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
61207 }
61208
61209 $this->name = $name;
61210 $this->mode = $mode;
61211 $this->description = $description;
61212
61213 $this->setDefault($default);
61214 }
61215
61216
61217
61218
61219
61220
61221 public function getName()
61222 {
61223 return $this->name;
61224 }
61225
61226
61227
61228
61229
61230
61231 public function isRequired()
61232 {
61233 return self::REQUIRED === (self::REQUIRED & $this->mode);
61234 }
61235
61236
61237
61238
61239
61240
61241 public function isArray()
61242 {
61243 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
61244 }
61245
61246
61247
61248
61249
61250
61251
61252
61253 public function setDefault($default = null)
61254 {
61255 if (self::REQUIRED === $this->mode && null !== $default) {
61256 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
61257 }
61258
61259 if ($this->isArray()) {
61260 if (null === $default) {
61261 $default = array();
61262 } elseif (!\is_array($default)) {
61263 throw new LogicException('A default value for an array argument must be an array.');
61264 }
61265 }
61266
61267 $this->default = $default;
61268 }
61269
61270
61271
61272
61273
61274
61275 public function getDefault()
61276 {
61277 return $this->default;
61278 }
61279
61280
61281
61282
61283
61284
61285 public function getDescription()
61286 {
61287 return $this->description;
61288 }
61289 }
61290 <?php
61291
61292
61293
61294
61295
61296
61297
61298
61299
61300
61301 namespace Symfony\Component\Console\Input;
61302
61303
61304
61305
61306
61307
61308
61309 interface InputAwareInterface
61310 {
61311
61312
61313
61314 public function setInput(InputInterface $input);
61315 }
61316 <?php
61317
61318
61319
61320
61321
61322
61323
61324
61325
61326
61327 namespace Symfony\Component\Console\Input;
61328
61329 use Symfony\Component\Console\Descriptor\TextDescriptor;
61330 use Symfony\Component\Console\Descriptor\XmlDescriptor;
61331 use Symfony\Component\Console\Exception\InvalidArgumentException;
61332 use Symfony\Component\Console\Exception\LogicException;
61333 use Symfony\Component\Console\Output\BufferedOutput;
61334
61335
61336
61337
61338
61339
61340
61341
61342
61343
61344
61345
61346
61347 class InputDefinition
61348 {
61349 private $arguments;
61350 private $requiredCount;
61351 private $hasAnArrayArgument = false;
61352 private $hasOptional;
61353 private $options;
61354 private $shortcuts;
61355
61356
61357
61358
61359 public function __construct(array $definition = array())
61360 {
61361 $this->setDefinition($definition);
61362 }
61363
61364
61365
61366
61367 public function setDefinition(array $definition)
61368 {
61369 $arguments = array();
61370 $options = array();
61371 foreach ($definition as $item) {
61372 if ($item instanceof InputOption) {
61373 $options[] = $item;
61374 } else {
61375 $arguments[] = $item;
61376 }
61377 }
61378
61379 $this->setArguments($arguments);
61380 $this->setOptions($options);
61381 }
61382
61383
61384
61385
61386
61387
61388 public function setArguments($arguments = array())
61389 {
61390 $this->arguments = array();
61391 $this->requiredCount = 0;
61392 $this->hasOptional = false;
61393 $this->hasAnArrayArgument = false;
61394 $this->addArguments($arguments);
61395 }
61396
61397
61398
61399
61400
61401
61402 public function addArguments($arguments = array())
61403 {
61404 if (null !== $arguments) {
61405 foreach ($arguments as $argument) {
61406 $this->addArgument($argument);
61407 }
61408 }
61409 }
61410
61411
61412
61413
61414 public function addArgument(InputArgument $argument)
61415 {
61416 if (isset($this->arguments[$argument->getName()])) {
61417 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
61418 }
61419
61420 if ($this->hasAnArrayArgument) {
61421 throw new LogicException('Cannot add an argument after an array argument.');
61422 }
61423
61424 if ($argument->isRequired() && $this->hasOptional) {
61425 throw new LogicException('Cannot add a required argument after an optional one.');
61426 }
61427
61428 if ($argument->isArray()) {
61429 $this->hasAnArrayArgument = true;
61430 }
61431
61432 if ($argument->isRequired()) {
61433 ++$this->requiredCount;
61434 } else {
61435 $this->hasOptional = true;
61436 }
61437
61438 $this->arguments[$argument->getName()] = $argument;
61439 }
61440
61441
61442
61443
61444
61445
61446
61447
61448
61449
61450 public function getArgument($name)
61451 {
61452 if (!$this->hasArgument($name)) {
61453 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
61454 }
61455
61456 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
61457
61458 return $arguments[$name];
61459 }
61460
61461
61462
61463
61464
61465
61466
61467
61468 public function hasArgument($name)
61469 {
61470 $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;
61471
61472 return isset($arguments[$name]);
61473 }
61474
61475
61476
61477
61478
61479
61480 public function getArguments()
61481 {
61482 return $this->arguments;
61483 }
61484
61485
61486
61487
61488
61489
61490 public function getArgumentCount()
61491 {
61492 return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments);
61493 }
61494
61495
61496
61497
61498
61499
61500 public function getArgumentRequiredCount()
61501 {
61502 return $this->requiredCount;
61503 }
61504
61505
61506
61507
61508
61509
61510 public function getArgumentDefaults()
61511 {
61512 $values = array();
61513 foreach ($this->arguments as $argument) {
61514 $values[$argument->getName()] = $argument->getDefault();
61515 }
61516
61517 return $values;
61518 }
61519
61520
61521
61522
61523
61524
61525 public function setOptions($options = array())
61526 {
61527 $this->options = array();
61528 $this->shortcuts = array();
61529 $this->addOptions($options);
61530 }
61531
61532
61533
61534
61535
61536
61537 public function addOptions($options = array())
61538 {
61539 foreach ($options as $option) {
61540 $this->addOption($option);
61541 }
61542 }
61543
61544
61545
61546
61547 public function addOption(InputOption $option)
61548 {
61549 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
61550 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
61551 }
61552
61553 if ($option->getShortcut()) {
61554 foreach (explode('|', $option->getShortcut()) as $shortcut) {
61555 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
61556 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
61557 }
61558 }
61559 }
61560
61561 $this->options[$option->getName()] = $option;
61562 if ($option->getShortcut()) {
61563 foreach (explode('|', $option->getShortcut()) as $shortcut) {
61564 $this->shortcuts[$shortcut] = $option->getName();
61565 }
61566 }
61567 }
61568
61569
61570
61571
61572
61573
61574
61575
61576
61577
61578 public function getOption($name)
61579 {
61580 if (!$this->hasOption($name)) {
61581 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
61582 }
61583
61584 return $this->options[$name];
61585 }
61586
61587
61588
61589
61590
61591
61592
61593
61594
61595
61596
61597 public function hasOption($name)
61598 {
61599 return isset($this->options[$name]);
61600 }
61601
61602
61603
61604
61605
61606
61607 public function getOptions()
61608 {
61609 return $this->options;
61610 }
61611
61612
61613
61614
61615
61616
61617
61618
61619 public function hasShortcut($name)
61620 {
61621 return isset($this->shortcuts[$name]);
61622 }
61623
61624
61625
61626
61627
61628
61629
61630
61631 public function getOptionForShortcut($shortcut)
61632 {
61633 return $this->getOption($this->shortcutToName($shortcut));
61634 }
61635
61636
61637
61638
61639
61640
61641 public function getOptionDefaults()
61642 {
61643 $values = array();
61644 foreach ($this->options as $option) {
61645 $values[$option->getName()] = $option->getDefault();
61646 }
61647
61648 return $values;
61649 }
61650
61651
61652
61653
61654
61655
61656
61657
61658
61659
61660 private function shortcutToName($shortcut)
61661 {
61662 if (!isset($this->shortcuts[$shortcut])) {
61663 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
61664 }
61665
61666 return $this->shortcuts[$shortcut];
61667 }
61668
61669
61670
61671
61672
61673
61674
61675
61676 public function getSynopsis($short = false)
61677 {
61678 $elements = array();
61679
61680 if ($short && $this->getOptions()) {
61681 $elements[] = '[options]';
61682 } elseif (!$short) {
61683 foreach ($this->getOptions() as $option) {
61684 $value = '';
61685 if ($option->acceptValue()) {
61686 $value = sprintf(
61687 ' %s%s%s',
61688 $option->isValueOptional() ? '[' : '',
61689 strtoupper($option->getName()),
61690 $option->isValueOptional() ? ']' : ''
61691 );
61692 }
61693
61694 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
61695 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
61696 }
61697 }
61698
61699 if (\count($elements) && $this->getArguments()) {
61700 $elements[] = '[--]';
61701 }
61702
61703 foreach ($this->getArguments() as $argument) {
61704 $element = '<'.$argument->getName().'>';
61705 if (!$argument->isRequired()) {
61706 $element = '['.$element.']';
61707 } elseif ($argument->isArray()) {
61708 $element .= ' ('.$element.')';
61709 }
61710
61711 if ($argument->isArray()) {
61712 $element .= '...';
61713 }
61714
61715 $elements[] = $element;
61716 }
61717
61718 return implode(' ', $elements);
61719 }
61720
61721
61722
61723
61724
61725
61726
61727
61728 public function asText()
61729 {
61730 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
61731
61732 $descriptor = new TextDescriptor();
61733 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
61734 $descriptor->describe($output, $this, array('raw_output' => true));
61735
61736 return $output->fetch();
61737 }
61738
61739
61740
61741
61742
61743
61744
61745
61746
61747
61748 public function asXml($asDom = false)
61749 {
61750 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
61751
61752 $descriptor = new XmlDescriptor();
61753
61754 if ($asDom) {
61755 return $descriptor->getInputDefinitionDocument($this);
61756 }
61757
61758 $output = new BufferedOutput();
61759 $descriptor->describe($output, $this);
61760
61761 return $output->fetch();
61762 }
61763 }
61764 <?php
61765
61766
61767
61768
61769
61770
61771
61772
61773
61774
61775 namespace Symfony\Component\Console\Input;
61776
61777 use Symfony\Component\Console\Exception\InvalidArgumentException;
61778 use Symfony\Component\Console\Exception\RuntimeException;
61779
61780
61781
61782
61783
61784
61785 interface InputInterface
61786 {
61787
61788
61789
61790
61791
61792 public function getFirstArgument();
61793
61794
61795
61796
61797
61798
61799
61800
61801
61802
61803
61804
61805
61806 public function hasParameterOption($values);
61807
61808
61809
61810
61811
61812
61813
61814
61815
61816
61817
61818
61819
61820
61821 public function getParameterOption($values, $default = false);
61822
61823
61824
61825
61826
61827
61828 public function bind(InputDefinition $definition);
61829
61830
61831
61832
61833
61834
61835 public function validate();
61836
61837
61838
61839
61840
61841
61842 public function getArguments();
61843
61844
61845
61846
61847
61848
61849
61850
61851
61852
61853 public function getArgument($name);
61854
61855
61856
61857
61858
61859
61860
61861
61862
61863 public function setArgument($name, $value);
61864
61865
61866
61867
61868
61869
61870
61871
61872 public function hasArgument($name);
61873
61874
61875
61876
61877
61878
61879 public function getOptions();
61880
61881
61882
61883
61884
61885
61886
61887
61888
61889
61890 public function getOption($name);
61891
61892
61893
61894
61895
61896
61897
61898
61899
61900 public function setOption($name, $value);
61901
61902
61903
61904
61905
61906
61907
61908
61909 public function hasOption($name);
61910
61911
61912
61913
61914
61915
61916 public function isInteractive();
61917
61918
61919
61920
61921
61922
61923 public function setInteractive($interactive);
61924 }
61925 <?php
61926
61927
61928
61929
61930
61931
61932
61933
61934
61935
61936 namespace Symfony\Component\Console\Input;
61937
61938 use Symfony\Component\Console\Exception\InvalidArgumentException;
61939 use Symfony\Component\Console\Exception\LogicException;
61940
61941
61942
61943
61944
61945
61946 class InputOption
61947 {
61948 const VALUE_NONE = 1;
61949 const VALUE_REQUIRED = 2;
61950 const VALUE_OPTIONAL = 4;
61951 const VALUE_IS_ARRAY = 8;
61952
61953 private $name;
61954 private $shortcut;
61955 private $mode;
61956 private $default;
61957 private $description;
61958
61959
61960
61961
61962
61963
61964
61965
61966
61967
61968 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
61969 {
61970 if (0 === strpos($name, '--')) {
61971 $name = substr($name, 2);
61972 }
61973
61974 if (empty($name)) {
61975 throw new InvalidArgumentException('An option name cannot be empty.');
61976 }
61977
61978 if (empty($shortcut)) {
61979 $shortcut = null;
61980 }
61981
61982 if (null !== $shortcut) {
61983 if (\is_array($shortcut)) {
61984 $shortcut = implode('|', $shortcut);
61985 }
61986 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
61987 $shortcuts = array_filter($shortcuts);
61988 $shortcut = implode('|', $shortcuts);
61989
61990 if (empty($shortcut)) {
61991 throw new InvalidArgumentException('An option shortcut cannot be empty.');
61992 }
61993 }
61994
61995 if (null === $mode) {
61996 $mode = self::VALUE_NONE;
61997 } elseif (!\is_int($mode) || $mode > 15 || $mode < 1) {
61998 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
61999 }
62000
62001 $this->name = $name;
62002 $this->shortcut = $shortcut;
62003 $this->mode = $mode;
62004 $this->description = $description;
62005
62006 if ($this->isArray() && !$this->acceptValue()) {
62007 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
62008 }
62009
62010 $this->setDefault($default);
62011 }
62012
62013
62014
62015
62016
62017
62018 public function getShortcut()
62019 {
62020 return $this->shortcut;
62021 }
62022
62023
62024
62025
62026
62027
62028 public function getName()
62029 {
62030 return $this->name;
62031 }
62032
62033
62034
62035
62036
62037
62038 public function acceptValue()
62039 {
62040 return $this->isValueRequired() || $this->isValueOptional();
62041 }
62042
62043
62044
62045
62046
62047
62048 public function isValueRequired()
62049 {
62050 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
62051 }
62052
62053
62054
62055
62056
62057
62058 public function isValueOptional()
62059 {
62060 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
62061 }
62062
62063
62064
62065
62066
62067
62068 public function isArray()
62069 {
62070 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
62071 }
62072
62073
62074
62075
62076
62077
62078
62079
62080 public function setDefault($default = null)
62081 {
62082 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
62083 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
62084 }
62085
62086 if ($this->isArray()) {
62087 if (null === $default) {
62088 $default = array();
62089 } elseif (!\is_array($default)) {
62090 throw new LogicException('A default value for an array option must be an array.');
62091 }
62092 }
62093
62094 $this->default = $this->acceptValue() ? $default : false;
62095 }
62096
62097
62098
62099
62100
62101
62102 public function getDefault()
62103 {
62104 return $this->default;
62105 }
62106
62107
62108
62109
62110
62111
62112 public function getDescription()
62113 {
62114 return $this->description;
62115 }
62116
62117
62118
62119
62120
62121
62122 public function equals(self $option)
62123 {
62124 return $option->getName() === $this->getName()
62125 && $option->getShortcut() === $this->getShortcut()
62126 && $option->getDefault() === $this->getDefault()
62127 && $option->isArray() === $this->isArray()
62128 && $option->isValueRequired() === $this->isValueRequired()
62129 && $option->isValueOptional() === $this->isValueOptional()
62130 ;
62131 }
62132 }
62133 <?php
62134
62135
62136
62137
62138
62139
62140
62141
62142
62143
62144 namespace Symfony\Component\Console\Input;
62145
62146 use Symfony\Component\Console\Exception\InvalidArgumentException;
62147
62148
62149
62150
62151
62152
62153
62154
62155
62156
62157 class StringInput extends ArgvInput
62158 {
62159 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
62160 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
62161
62162
62163
62164
62165
62166
62167
62168 public function __construct($input, InputDefinition $definition = null)
62169 {
62170 if ($definition) {
62171 @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);
62172 }
62173
62174 parent::__construct(array(), null);
62175
62176 $this->setTokens($this->tokenize($input));
62177
62178 if (null !== $definition) {
62179 $this->bind($definition);
62180 }
62181 }
62182
62183
62184
62185
62186
62187
62188
62189
62190
62191
62192 private function tokenize($input)
62193 {
62194 $tokens = array();
62195 $length = \strlen($input);
62196 $cursor = 0;
62197 while ($cursor < $length) {
62198 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
62199 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
62200 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, \strlen($match[3]) - 2)));
62201 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
62202 $tokens[] = stripcslashes(substr($match[0], 1, \strlen($match[0]) - 2));
62203 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
62204 $tokens[] = stripcslashes($match[1]);
62205 } else {
62206
62207  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
62208 }
62209
62210 $cursor += \strlen($match[0]);
62211 }
62212
62213 return $tokens;
62214 }
62215 }
62216 Copyright (c) 2004-2018 Fabien Potencier
62217
62218 Permission is hereby granted, free of charge, to any person obtaining a copy
62219 of this software and associated documentation files (the "Software"), to deal
62220 in the Software without restriction, including without limitation the rights
62221 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62222 copies of the Software, and to permit persons to whom the Software is furnished
62223 to do so, subject to the following conditions:
62224
62225 The above copyright notice and this permission notice shall be included in all
62226 copies or substantial portions of the Software.
62227
62228 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62229 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62230 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62231 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62232 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62233 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
62234 THE SOFTWARE.
62235 <?php
62236
62237
62238
62239
62240
62241
62242
62243
62244
62245
62246 namespace Symfony\Component\Console\Logger;
62247
62248 use Psr\Log\AbstractLogger;
62249 use Psr\Log\InvalidArgumentException;
62250 use Psr\Log\LogLevel;
62251 use Symfony\Component\Console\Output\ConsoleOutputInterface;
62252 use Symfony\Component\Console\Output\OutputInterface;
62253
62254
62255
62256
62257
62258
62259
62260
62261 class ConsoleLogger extends AbstractLogger
62262 {
62263 const INFO = 'info';
62264 const ERROR = 'error';
62265
62266 private $output;
62267 private $verbosityLevelMap = array(
62268 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
62269 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
62270 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
62271 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
62272 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
62273 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
62274 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
62275 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
62276 );
62277 private $formatLevelMap = array(
62278 LogLevel::EMERGENCY => self::ERROR,
62279 LogLevel::ALERT => self::ERROR,
62280 LogLevel::CRITICAL => self::ERROR,
62281 LogLevel::ERROR => self::ERROR,
62282 LogLevel::WARNING => self::INFO,
62283 LogLevel::NOTICE => self::INFO,
62284 LogLevel::INFO => self::INFO,
62285 LogLevel::DEBUG => self::INFO,
62286 );
62287
62288 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
62289 {
62290 $this->output = $output;
62291 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
62292 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
62293 }
62294
62295
62296
62297
62298 public function log($level, $message, array $context = array())
62299 {
62300 if (!isset($this->verbosityLevelMap[$level])) {
62301 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
62302 }
62303
62304
62305  if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) {
62306 $output = $this->output->getErrorOutput();
62307 } else {
62308 $output = $this->output;
62309 }
62310
62311 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
62312 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
62313 }
62314 }
62315
62316
62317
62318
62319
62320
62321
62322
62323
62324
62325
62326 private function interpolate($message, array $context)
62327 {
62328
62329  $replace = array();
62330 foreach ($context as $key => $val) {
62331 if (!\is_array($val) && (!\is_object($val) || method_exists($val, '__toString'))) {
62332 $replace[sprintf('{%s}', $key)] = $val;
62333 }
62334 }
62335
62336
62337  return strtr($message, $replace);
62338 }
62339 }
62340 <?php
62341
62342
62343
62344
62345
62346
62347
62348
62349
62350
62351 namespace Symfony\Component\Console\Output;
62352
62353
62354
62355
62356 class BufferedOutput extends Output
62357 {
62358 private $buffer = '';
62359
62360
62361
62362
62363
62364
62365 public function fetch()
62366 {
62367 $content = $this->buffer;
62368 $this->buffer = '';
62369
62370 return $content;
62371 }
62372
62373
62374
62375
62376 protected function doWrite($message, $newline)
62377 {
62378 $this->buffer .= $message;
62379
62380 if ($newline) {
62381 $this->buffer .= PHP_EOL;
62382 }
62383 }
62384 }
62385 <?php
62386
62387
62388
62389
62390
62391
62392
62393
62394
62395
62396 namespace Symfony\Component\Console\Output;
62397
62398 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
62399
62400
62401
62402
62403
62404
62405
62406
62407
62408
62409
62410
62411
62412
62413 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
62414 {
62415 private $stderr;
62416
62417
62418
62419
62420
62421
62422 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
62423 {
62424 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
62425
62426 $actualDecorated = $this->isDecorated();
62427 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
62428
62429 if (null === $decorated) {
62430 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
62431 }
62432 }
62433
62434
62435
62436
62437 public function setDecorated($decorated)
62438 {
62439 parent::setDecorated($decorated);
62440 $this->stderr->setDecorated($decorated);
62441 }
62442
62443
62444
62445
62446 public function setFormatter(OutputFormatterInterface $formatter)
62447 {
62448 parent::setFormatter($formatter);
62449 $this->stderr->setFormatter($formatter);
62450 }
62451
62452
62453
62454
62455 public function setVerbosity($level)
62456 {
62457 parent::setVerbosity($level);
62458 $this->stderr->setVerbosity($level);
62459 }
62460
62461
62462
62463
62464 public function getErrorOutput()
62465 {
62466 return $this->stderr;
62467 }
62468
62469
62470
62471
62472 public function setErrorOutput(OutputInterface $error)
62473 {
62474 $this->stderr = $error;
62475 }
62476
62477
62478
62479
62480
62481
62482
62483 protected function hasStdoutSupport()
62484 {
62485 return false === $this->isRunningOS400();
62486 }
62487
62488
62489
62490
62491
62492
62493
62494 protected function hasStderrSupport()
62495 {
62496 return false === $this->isRunningOS400();
62497 }
62498
62499
62500
62501
62502
62503
62504
62505 private function isRunningOS400()
62506 {
62507 $checks = array(
62508 \function_exists('php_uname') ? php_uname('s') : '',
62509 getenv('OSTYPE'),
62510 PHP_OS,
62511 );
62512
62513 return false !== stripos(implode(';', $checks), 'OS400');
62514 }
62515
62516
62517
62518
62519 private function openOutputStream()
62520 {
62521 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
62522
62523 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
62524 }
62525
62526
62527
62528
62529 private function openErrorStream()
62530 {
62531 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
62532
62533 return fopen($errorStream, 'w');
62534 }
62535 }
62536 <?php
62537
62538
62539
62540
62541
62542
62543
62544
62545
62546
62547 namespace Symfony\Component\Console\Output;
62548
62549
62550
62551
62552
62553
62554
62555 interface ConsoleOutputInterface extends OutputInterface
62556 {
62557
62558
62559
62560
62561
62562 public function getErrorOutput();
62563
62564 public function setErrorOutput(OutputInterface $error);
62565 }
62566 <?php
62567
62568
62569
62570
62571
62572
62573
62574
62575
62576
62577 namespace Symfony\Component\Console\Output;
62578
62579 use Symfony\Component\Console\Formatter\OutputFormatter;
62580 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
62581
62582
62583
62584
62585
62586
62587
62588
62589
62590 class NullOutput implements OutputInterface
62591 {
62592
62593
62594
62595 public function setFormatter(OutputFormatterInterface $formatter)
62596 {
62597
62598  }
62599
62600
62601
62602
62603 public function getFormatter()
62604 {
62605
62606  return new OutputFormatter();
62607 }
62608
62609
62610
62611
62612 public function setDecorated($decorated)
62613 {
62614
62615  }
62616
62617
62618
62619
62620 public function isDecorated()
62621 {
62622 return false;
62623 }
62624
62625
62626
62627
62628 public function setVerbosity($level)
62629 {
62630
62631  }
62632
62633
62634
62635
62636 public function getVerbosity()
62637 {
62638 return self::VERBOSITY_QUIET;
62639 }
62640
62641
62642
62643
62644 public function isQuiet()
62645 {
62646 return true;
62647 }
62648
62649
62650
62651
62652 public function isVerbose()
62653 {
62654 return false;
62655 }
62656
62657
62658
62659
62660 public function isVeryVerbose()
62661 {
62662 return false;
62663 }
62664
62665
62666
62667
62668 public function isDebug()
62669 {
62670 return false;
62671 }
62672
62673
62674
62675
62676 public function writeln($messages, $options = self::OUTPUT_NORMAL)
62677 {
62678
62679  }
62680
62681
62682
62683
62684 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
62685 {
62686
62687  }
62688 }
62689 <?php
62690
62691
62692
62693
62694
62695
62696
62697
62698
62699
62700 namespace Symfony\Component\Console\Output;
62701
62702 use Symfony\Component\Console\Formatter\OutputFormatter;
62703 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
62704
62705
62706
62707
62708
62709
62710
62711
62712
62713
62714
62715
62716
62717
62718 abstract class Output implements OutputInterface
62719 {
62720 private $verbosity;
62721 private $formatter;
62722
62723
62724
62725
62726
62727
62728 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
62729 {
62730 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
62731 $this->formatter = $formatter ?: new OutputFormatter();
62732 $this->formatter->setDecorated($decorated);
62733 }
62734
62735
62736
62737
62738 public function setFormatter(OutputFormatterInterface $formatter)
62739 {
62740 $this->formatter = $formatter;
62741 }
62742
62743
62744
62745
62746 public function getFormatter()
62747 {
62748 return $this->formatter;
62749 }
62750
62751
62752
62753
62754 public function setDecorated($decorated)
62755 {
62756 $this->formatter->setDecorated($decorated);
62757 }
62758
62759
62760
62761
62762 public function isDecorated()
62763 {
62764 return $this->formatter->isDecorated();
62765 }
62766
62767
62768
62769
62770 public function setVerbosity($level)
62771 {
62772 $this->verbosity = (int) $level;
62773 }
62774
62775
62776
62777
62778 public function getVerbosity()
62779 {
62780 return $this->verbosity;
62781 }
62782
62783
62784
62785
62786 public function isQuiet()
62787 {
62788 return self::VERBOSITY_QUIET === $this->verbosity;
62789 }
62790
62791
62792
62793
62794 public function isVerbose()
62795 {
62796 return self::VERBOSITY_VERBOSE <= $this->verbosity;
62797 }
62798
62799
62800
62801
62802 public function isVeryVerbose()
62803 {
62804 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
62805 }
62806
62807
62808
62809
62810 public function isDebug()
62811 {
62812 return self::VERBOSITY_DEBUG <= $this->verbosity;
62813 }
62814
62815
62816
62817
62818 public function writeln($messages, $options = self::OUTPUT_NORMAL)
62819 {
62820 $this->write($messages, true, $options);
62821 }
62822
62823
62824
62825
62826 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
62827 {
62828 $messages = (array) $messages;
62829
62830 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
62831 $type = $types & $options ?: self::OUTPUT_NORMAL;
62832
62833 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
62834 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
62835
62836 if ($verbosity > $this->getVerbosity()) {
62837 return;
62838 }
62839
62840 foreach ($messages as $message) {
62841 switch ($type) {
62842 case OutputInterface::OUTPUT_NORMAL:
62843 $message = $this->formatter->format($message);
62844 break;
62845 case OutputInterface::OUTPUT_RAW:
62846 break;
62847 case OutputInterface::OUTPUT_PLAIN:
62848 $message = strip_tags($this->formatter->format($message));
62849 break;
62850 }
62851
62852 $this->doWrite($message, $newline);
62853 }
62854 }
62855
62856
62857
62858
62859
62860
62861
62862 abstract protected function doWrite($message, $newline);
62863 }
62864 <?php
62865
62866
62867
62868
62869
62870
62871
62872
62873
62874
62875 namespace Symfony\Component\Console\Output;
62876
62877 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
62878
62879
62880
62881
62882
62883
62884 interface OutputInterface
62885 {
62886 const VERBOSITY_QUIET = 16;
62887 const VERBOSITY_NORMAL = 32;
62888 const VERBOSITY_VERBOSE = 64;
62889 const VERBOSITY_VERY_VERBOSE = 128;
62890 const VERBOSITY_DEBUG = 256;
62891
62892 const OUTPUT_NORMAL = 1;
62893 const OUTPUT_RAW = 2;
62894 const OUTPUT_PLAIN = 4;
62895
62896
62897
62898
62899
62900
62901
62902
62903 public function write($messages, $newline = false, $options = 0);
62904
62905
62906
62907
62908
62909
62910
62911 public function writeln($messages, $options = 0);
62912
62913
62914
62915
62916
62917
62918 public function setVerbosity($level);
62919
62920
62921
62922
62923
62924
62925 public function getVerbosity();
62926
62927
62928
62929
62930
62931
62932 public function setDecorated($decorated);
62933
62934
62935
62936
62937
62938
62939 public function isDecorated();
62940
62941 public function setFormatter(OutputFormatterInterface $formatter);
62942
62943
62944
62945
62946
62947
62948 public function getFormatter();
62949 }
62950 <?php
62951
62952
62953
62954
62955
62956
62957
62958
62959
62960
62961 namespace Symfony\Component\Console\Output;
62962
62963 use Symfony\Component\Console\Exception\InvalidArgumentException;
62964 use Symfony\Component\Console\Exception\RuntimeException;
62965 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
62966
62967
62968
62969
62970
62971
62972
62973
62974
62975
62976
62977
62978
62979
62980 class StreamOutput extends Output
62981 {
62982 private $stream;
62983
62984
62985
62986
62987
62988
62989
62990
62991
62992 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
62993 {
62994 if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
62995 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
62996 }
62997
62998 $this->stream = $stream;
62999
63000 if (null === $decorated) {
63001 $decorated = $this->hasColorSupport();
63002 }
63003
63004 parent::__construct($verbosity, $decorated, $formatter);
63005 }
63006
63007
63008
63009
63010
63011
63012 public function getStream()
63013 {
63014 return $this->stream;
63015 }
63016
63017
63018
63019
63020 protected function doWrite($message, $newline)
63021 {
63022 if ($newline) {
63023 $message .= PHP_EOL;
63024 }
63025
63026 if (false === @fwrite($this->stream, $message)) {
63027
63028  throw new RuntimeException('Unable to write output.');
63029 }
63030
63031 fflush($this->stream);
63032 }
63033
63034
63035
63036
63037
63038
63039
63040
63041
63042
63043
63044
63045
63046
63047 protected function hasColorSupport()
63048 {
63049 if ('Hyper' === getenv('TERM_PROGRAM')) {
63050 return true;
63051 }
63052
63053 if (\DIRECTORY_SEPARATOR === '\\') {
63054 return (\function_exists('sapi_windows_vt100_support')
63055 && @sapi_windows_vt100_support($this->stream))
63056 || false !== getenv('ANSICON')
63057 || 'ON' === getenv('ConEmuANSI')
63058 || 'xterm' === getenv('TERM');
63059 }
63060
63061 if (\function_exists('stream_isatty')) {
63062 return @stream_isatty($this->stream);
63063 }
63064
63065 if (\function_exists('posix_isatty')) {
63066 return @posix_isatty($this->stream);
63067 }
63068
63069 $stat = @fstat($this->stream);
63070
63071  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
63072 }
63073 }
63074 <?php
63075
63076
63077
63078
63079
63080
63081
63082
63083
63084
63085 namespace Symfony\Component\Console\Question;
63086
63087 use Symfony\Component\Console\Exception\InvalidArgumentException;
63088
63089
63090
63091
63092
63093
63094 class ChoiceQuestion extends Question
63095 {
63096 private $choices;
63097 private $multiselect = false;
63098 private $prompt = ' > ';
63099 private $errorMessage = 'Value "%s" is invalid';
63100
63101
63102
63103
63104
63105
63106 public function __construct($question, array $choices, $default = null)
63107 {
63108 if (!$choices) {
63109 throw new \LogicException('Choice question must have at least 1 choice available.');
63110 }
63111
63112 parent::__construct($question, $default);
63113
63114 $this->choices = $choices;
63115 $this->setValidator($this->getDefaultValidator());
63116 $this->setAutocompleterValues($choices);
63117 }
63118
63119
63120
63121
63122
63123
63124 public function getChoices()
63125 {
63126 return $this->choices;
63127 }
63128
63129
63130
63131
63132
63133
63134
63135
63136
63137
63138 public function setMultiselect($multiselect)
63139 {
63140 $this->multiselect = $multiselect;
63141 $this->setValidator($this->getDefaultValidator());
63142
63143 return $this;
63144 }
63145
63146
63147
63148
63149
63150
63151 public function isMultiselect()
63152 {
63153 return $this->multiselect;
63154 }
63155
63156
63157
63158
63159
63160
63161 public function getPrompt()
63162 {
63163 return $this->prompt;
63164 }
63165
63166
63167
63168
63169
63170
63171
63172
63173 public function setPrompt($prompt)
63174 {
63175 $this->prompt = $prompt;
63176
63177 return $this;
63178 }
63179
63180
63181
63182
63183
63184
63185
63186
63187
63188
63189 public function setErrorMessage($errorMessage)
63190 {
63191 $this->errorMessage = $errorMessage;
63192 $this->setValidator($this->getDefaultValidator());
63193
63194 return $this;
63195 }
63196
63197
63198
63199
63200
63201
63202 private function getDefaultValidator()
63203 {
63204 $choices = $this->choices;
63205 $errorMessage = $this->errorMessage;
63206 $multiselect = $this->multiselect;
63207 $isAssoc = $this->isAssoc($choices);
63208
63209 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
63210
63211  $selectedChoices = str_replace(' ', '', $selected);
63212
63213 if ($multiselect) {
63214
63215  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
63216 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
63217 }
63218 $selectedChoices = explode(',', $selectedChoices);
63219 } else {
63220 $selectedChoices = array($selected);
63221 }
63222
63223 $multiselectChoices = array();
63224 foreach ($selectedChoices as $value) {
63225 $results = array();
63226 foreach ($choices as $key => $choice) {
63227 if ($choice === $value) {
63228 $results[] = $key;
63229 }
63230 }
63231
63232 if (\count($results) > 1) {
63233 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
63234 }
63235
63236 $result = array_search($value, $choices);
63237
63238 if (!$isAssoc) {
63239 if (false !== $result) {
63240 $result = $choices[$result];
63241 } elseif (isset($choices[$value])) {
63242 $result = $choices[$value];
63243 }
63244 } elseif (false === $result && isset($choices[$value])) {
63245 $result = $value;
63246 }
63247
63248 if (false === $result) {
63249 throw new InvalidArgumentException(sprintf($errorMessage, $value));
63250 }
63251
63252 $multiselectChoices[] = (string) $result;
63253 }
63254
63255 if ($multiselect) {
63256 return $multiselectChoices;
63257 }
63258
63259 return current($multiselectChoices);
63260 };
63261 }
63262 }
63263 <?php
63264
63265
63266
63267
63268
63269
63270
63271
63272
63273
63274 namespace Symfony\Component\Console\Question;
63275
63276
63277
63278
63279
63280
63281 class ConfirmationQuestion extends Question
63282 {
63283 private $trueAnswerRegex;
63284
63285
63286
63287
63288
63289
63290 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
63291 {
63292 parent::__construct($question, (bool) $default);
63293
63294 $this->trueAnswerRegex = $trueAnswerRegex;
63295 $this->setNormalizer($this->getDefaultNormalizer());
63296 }
63297
63298
63299
63300
63301
63302
63303 private function getDefaultNormalizer()
63304 {
63305 $default = $this->getDefault();
63306 $regex = $this->trueAnswerRegex;
63307
63308 return function ($answer) use ($default, $regex) {
63309 if (\is_bool($answer)) {
63310 return $answer;
63311 }
63312
63313 $answerIsTrue = (bool) preg_match($regex, $answer);
63314 if (false === $default) {
63315 return $answer && $answerIsTrue;
63316 }
63317
63318 return !$answer || $answerIsTrue;
63319 };
63320 }
63321 }
63322 <?php
63323
63324
63325
63326
63327
63328
63329
63330
63331
63332
63333 namespace Symfony\Component\Console\Question;
63334
63335 use Symfony\Component\Console\Exception\InvalidArgumentException;
63336 use Symfony\Component\Console\Exception\LogicException;
63337
63338
63339
63340
63341
63342
63343 class Question
63344 {
63345 private $question;
63346 private $attempts;
63347 private $hidden = false;
63348 private $hiddenFallback = true;
63349 private $autocompleterValues;
63350 private $validator;
63351 private $default;
63352 private $normalizer;
63353
63354
63355
63356
63357
63358 public function __construct($question, $default = null)
63359 {
63360 $this->question = $question;
63361 $this->default = $default;
63362 }
63363
63364
63365
63366
63367
63368
63369 public function getQuestion()
63370 {
63371 return $this->question;
63372 }
63373
63374
63375
63376
63377
63378
63379 public function getDefault()
63380 {
63381 return $this->default;
63382 }
63383
63384
63385
63386
63387
63388
63389 public function isHidden()
63390 {
63391 return $this->hidden;
63392 }
63393
63394
63395
63396
63397
63398
63399
63400
63401
63402
63403 public function setHidden($hidden)
63404 {
63405 if ($this->autocompleterValues) {
63406 throw new LogicException('A hidden question cannot use the autocompleter.');
63407 }
63408
63409 $this->hidden = (bool) $hidden;
63410
63411 return $this;
63412 }
63413
63414
63415
63416
63417
63418
63419 public function isHiddenFallback()
63420 {
63421 return $this->hiddenFallback;
63422 }
63423
63424
63425
63426
63427
63428
63429
63430
63431 public function setHiddenFallback($fallback)
63432 {
63433 $this->hiddenFallback = (bool) $fallback;
63434
63435 return $this;
63436 }
63437
63438
63439
63440
63441
63442
63443 public function getAutocompleterValues()
63444 {
63445 return $this->autocompleterValues;
63446 }
63447
63448
63449
63450
63451
63452
63453
63454
63455
63456
63457
63458 public function setAutocompleterValues($values)
63459 {
63460 if (\is_array($values)) {
63461 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
63462 }
63463
63464 if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) {
63465 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
63466 }
63467
63468 if ($this->hidden) {
63469 throw new LogicException('A hidden question cannot use the autocompleter.');
63470 }
63471
63472 $this->autocompleterValues = $values;
63473
63474 return $this;
63475 }
63476
63477
63478
63479
63480
63481
63482
63483
63484 public function setValidator($validator)
63485 {
63486 $this->validator = $validator;
63487
63488 return $this;
63489 }
63490
63491
63492
63493
63494
63495
63496 public function getValidator()
63497 {
63498 return $this->validator;
63499 }
63500
63501
63502
63503
63504
63505
63506
63507
63508
63509
63510
63511
63512 public function setMaxAttempts($attempts)
63513 {
63514 if (null !== $attempts && $attempts < 1) {
63515 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
63516 }
63517
63518 $this->attempts = $attempts;
63519
63520 return $this;
63521 }
63522
63523
63524
63525
63526
63527
63528
63529
63530 public function getMaxAttempts()
63531 {
63532 return $this->attempts;
63533 }
63534
63535
63536
63537
63538
63539
63540
63541
63542
63543
63544 public function setNormalizer($normalizer)
63545 {
63546 $this->normalizer = $normalizer;
63547
63548 return $this;
63549 }
63550
63551
63552
63553
63554
63555
63556
63557
63558 public function getNormalizer()
63559 {
63560 return $this->normalizer;
63561 }
63562
63563 protected function isAssoc($array)
63564 {
63565 return (bool) \count(array_filter(array_keys($array), 'is_string'));
63566 }
63567 }
63568 <?php
63569
63570
63571
63572
63573
63574
63575
63576
63577
63578
63579 namespace Symfony\Component\Console;
63580
63581 use Symfony\Component\Console\Exception\RuntimeException;
63582 use Symfony\Component\Console\Input\StringInput;
63583 use Symfony\Component\Console\Output\ConsoleOutput;
63584 use Symfony\Component\Process\PhpExecutableFinder;
63585 use Symfony\Component\Process\ProcessBuilder;
63586
63587
63588
63589
63590
63591
63592
63593
63594
63595
63596
63597
63598 class Shell
63599 {
63600 private $application;
63601 private $history;
63602 private $output;
63603 private $hasReadline;
63604 private $processIsolation = false;
63605
63606
63607
63608
63609
63610 public function __construct(Application $application)
63611 {
63612 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
63613
63614 $this->hasReadline = \function_exists('readline');
63615 $this->application = $application;
63616 $this->history = getenv('HOME').'/.history_'.$application->getName();
63617 $this->output = new ConsoleOutput();
63618 }
63619
63620
63621
63622
63623 public function run()
63624 {
63625 $this->application->setAutoExit(false);
63626 $this->application->setCatchExceptions(true);
63627
63628 if ($this->hasReadline) {
63629 readline_read_history($this->history);
63630 readline_completion_function(array($this, 'autocompleter'));
63631 }
63632
63633 $this->output->writeln($this->getHeader());
63634 $php = null;
63635 if ($this->processIsolation) {
63636 $finder = new PhpExecutableFinder();
63637 $php = $finder->find();
63638 $this->output->writeln(<<<'EOF'
63639 <info>Running with process isolation, you should consider this:</info>
63640   * each command is executed as separate process,
63641   * commands don't support interactivity, all params must be passed explicitly,
63642   * commands output is not colorized.
63643
63644 EOF
63645 );
63646 }
63647
63648 while (true) {
63649 $command = $this->readline();
63650
63651 if (false === $command) {
63652 $this->output->writeln("\n");
63653
63654 break;
63655 }
63656
63657 if ($this->hasReadline) {
63658 readline_add_history($command);
63659 readline_write_history($this->history);
63660 }
63661
63662 if ($this->processIsolation) {
63663 $pb = new ProcessBuilder();
63664
63665 $process = $pb
63666 ->add($php)
63667 ->add($_SERVER['argv'][0])
63668 ->add($command)
63669 ->inheritEnvironmentVariables(true)
63670 ->getProcess()
63671 ;
63672
63673 $output = $this->output;
63674 $process->run(function ($type, $data) use ($output) {
63675 $output->writeln($data);
63676 });
63677
63678 $ret = $process->getExitCode();
63679 } else {
63680 $ret = $this->application->run(new StringInput($command), $this->output);
63681 }
63682
63683 if (0 !== $ret) {
63684 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
63685 }
63686 }
63687 }
63688
63689
63690
63691
63692
63693
63694 protected function getHeader()
63695 {
63696 return <<<EOF
63697
63698 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
63699
63700 At the prompt, type <comment>help</comment> for some help,
63701 or <comment>list</comment> to get a list of available commands.
63702
63703 To exit the shell, type <comment>^D</comment>.
63704
63705 EOF;
63706 }
63707
63708
63709
63710
63711
63712
63713 protected function getPrompt()
63714 {
63715
63716  return $this->output->getFormatter()->format($this->application->getName().' > ');
63717 }
63718
63719 protected function getOutput()
63720 {
63721 return $this->output;
63722 }
63723
63724 protected function getApplication()
63725 {
63726 return $this->application;
63727 }
63728
63729
63730
63731
63732
63733
63734
63735
63736 private function autocompleter($text)
63737 {
63738 $info = readline_info();
63739 $text = substr($info['line_buffer'], 0, $info['end']);
63740
63741 if ($info['point'] !== $info['end']) {
63742 return true;
63743 }
63744
63745
63746  if (false === strpos($text, ' ') || !$text) {
63747 return array_keys($this->application->all());
63748 }
63749
63750
63751  try {
63752 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
63753 } catch (\Exception $e) {
63754 return true;
63755 }
63756
63757 $list = array('--help');
63758 foreach ($command->getDefinition()->getOptions() as $option) {
63759 $list[] = '--'.$option->getName();
63760 }
63761
63762 return $list;
63763 }
63764
63765
63766
63767
63768
63769
63770 private function readline()
63771 {
63772 if ($this->hasReadline) {
63773 $line = readline($this->getPrompt());
63774 } else {
63775 $this->output->write($this->getPrompt());
63776 $line = fgets(STDIN, 1024);
63777 $line = (false === $line || '' === $line) ? false : rtrim($line);
63778 }
63779
63780 return $line;
63781 }
63782
63783 public function getProcessIsolation()
63784 {
63785 return $this->processIsolation;
63786 }
63787
63788 public function setProcessIsolation($processIsolation)
63789 {
63790 $this->processIsolation = (bool) $processIsolation;
63791
63792 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
63793 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
63794 }
63795 }
63796 }
63797 <?php
63798
63799
63800
63801
63802
63803
63804
63805
63806
63807
63808 namespace Symfony\Component\Console\Style;
63809
63810 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
63811 use Symfony\Component\Console\Helper\ProgressBar;
63812 use Symfony\Component\Console\Output\OutputInterface;
63813
63814
63815
63816
63817
63818
63819 abstract class OutputStyle implements OutputInterface, StyleInterface
63820 {
63821 private $output;
63822
63823 public function __construct(OutputInterface $output)
63824 {
63825 $this->output = $output;
63826 }
63827
63828
63829
63830
63831 public function newLine($count = 1)
63832 {
63833 $this->output->write(str_repeat(PHP_EOL, $count));
63834 }
63835
63836
63837
63838
63839
63840
63841 public function createProgressBar($max = 0)
63842 {
63843 return new ProgressBar($this->output, $max);
63844 }
63845
63846
63847
63848
63849 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
63850 {
63851 $this->output->write($messages, $newline, $type);
63852 }
63853
63854
63855
63856
63857 public function writeln($messages, $type = self::OUTPUT_NORMAL)
63858 {
63859 $this->output->writeln($messages, $type);
63860 }
63861
63862
63863
63864
63865 public function setVerbosity($level)
63866 {
63867 $this->output->setVerbosity($level);
63868 }
63869
63870
63871
63872
63873 public function getVerbosity()
63874 {
63875 return $this->output->getVerbosity();
63876 }
63877
63878
63879
63880
63881 public function setDecorated($decorated)
63882 {
63883 $this->output->setDecorated($decorated);
63884 }
63885
63886
63887
63888
63889 public function isDecorated()
63890 {
63891 return $this->output->isDecorated();
63892 }
63893
63894
63895
63896
63897 public function setFormatter(OutputFormatterInterface $formatter)
63898 {
63899 $this->output->setFormatter($formatter);
63900 }
63901
63902
63903
63904
63905 public function getFormatter()
63906 {
63907 return $this->output->getFormatter();
63908 }
63909 }
63910 <?php
63911
63912
63913
63914
63915
63916
63917
63918
63919
63920
63921 namespace Symfony\Component\Console\Style;
63922
63923
63924
63925
63926
63927
63928 interface StyleInterface
63929 {
63930
63931
63932
63933
63934
63935 public function title($message);
63936
63937
63938
63939
63940
63941
63942 public function section($message);
63943
63944
63945
63946
63947 public function listing(array $elements);
63948
63949
63950
63951
63952
63953
63954 public function text($message);
63955
63956
63957
63958
63959
63960
63961 public function success($message);
63962
63963
63964
63965
63966
63967
63968 public function error($message);
63969
63970
63971
63972
63973
63974
63975 public function warning($message);
63976
63977
63978
63979
63980
63981
63982 public function note($message);
63983
63984
63985
63986
63987
63988
63989 public function caution($message);
63990
63991
63992
63993
63994 public function table(array $headers, array $rows);
63995
63996
63997
63998
63999
64000
64001
64002
64003
64004
64005 public function ask($question, $default = null, $validator = null);
64006
64007
64008
64009
64010
64011
64012
64013
64014
64015 public function askHidden($question, $validator = null);
64016
64017
64018
64019
64020
64021
64022
64023
64024
64025 public function confirm($question, $default = true);
64026
64027
64028
64029
64030
64031
64032
64033
64034
64035
64036 public function choice($question, array $choices, $default = null);
64037
64038
64039
64040
64041
64042
64043 public function newLine($count = 1);
64044
64045
64046
64047
64048
64049
64050 public function progressStart($max = 0);
64051
64052
64053
64054
64055
64056
64057 public function progressAdvance($step = 1);
64058
64059
64060
64061
64062 public function progressFinish();
64063 }
64064 <?php
64065
64066
64067
64068
64069
64070
64071
64072
64073
64074
64075 namespace Symfony\Component\Console\Style;
64076
64077 use Symfony\Component\Console\Application;
64078 use Symfony\Component\Console\Exception\RuntimeException;
64079 use Symfony\Component\Console\Formatter\OutputFormatter;
64080 use Symfony\Component\Console\Helper\Helper;
64081 use Symfony\Component\Console\Helper\ProgressBar;
64082 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
64083 use Symfony\Component\Console\Helper\Table;
64084 use Symfony\Component\Console\Input\InputInterface;
64085 use Symfony\Component\Console\Output\BufferedOutput;
64086 use Symfony\Component\Console\Output\OutputInterface;
64087 use Symfony\Component\Console\Question\ChoiceQuestion;
64088 use Symfony\Component\Console\Question\ConfirmationQuestion;
64089 use Symfony\Component\Console\Question\Question;
64090
64091
64092
64093
64094
64095
64096 class SymfonyStyle extends OutputStyle
64097 {
64098 const MAX_LINE_LENGTH = 120;
64099
64100 private $input;
64101 private $questionHelper;
64102 private $progressBar;
64103 private $lineLength;
64104 private $bufferedOutput;
64105
64106 public function __construct(InputInterface $input, OutputInterface $output)
64107 {
64108 $this->input = $input;
64109 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
64110
64111  $this->lineLength = min($this->getTerminalWidth() - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
64112
64113 parent::__construct($output);
64114 }
64115
64116
64117
64118
64119
64120
64121
64122
64123
64124
64125 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
64126 {
64127 $messages = \is_array($messages) ? array_values($messages) : array($messages);
64128
64129 $this->autoPrependBlock();
64130 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
64131 $this->newLine();
64132 }
64133
64134
64135
64136
64137 public function title($message)
64138 {
64139 $this->autoPrependBlock();
64140 $this->writeln(array(
64141 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
64142 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
64143 ));
64144 $this->newLine();
64145 }
64146
64147
64148
64149
64150 public function section($message)
64151 {
64152 $this->autoPrependBlock();
64153 $this->writeln(array(
64154 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
64155 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
64156 ));
64157 $this->newLine();
64158 }
64159
64160
64161
64162
64163 public function listing(array $elements)
64164 {
64165 $this->autoPrependText();
64166 $elements = array_map(function ($element) {
64167 return sprintf(' * %s', $element);
64168 }, $elements);
64169
64170 $this->writeln($elements);
64171 $this->newLine();
64172 }
64173
64174
64175
64176
64177 public function text($message)
64178 {
64179 $this->autoPrependText();
64180
64181 $messages = \is_array($message) ? array_values($message) : array($message);
64182 foreach ($messages as $message) {
64183 $this->writeln(sprintf(' %s', $message));
64184 }
64185 }
64186
64187
64188
64189
64190
64191
64192 public function comment($message)
64193 {
64194 $messages = \is_array($message) ? array_values($message) : array($message);
64195
64196 $this->autoPrependBlock();
64197 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
64198 $this->newLine();
64199 }
64200
64201
64202
64203
64204 public function success($message)
64205 {
64206 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
64207 }
64208
64209
64210
64211
64212 public function error($message)
64213 {
64214 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
64215 }
64216
64217
64218
64219
64220 public function warning($message)
64221 {
64222 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
64223 }
64224
64225
64226
64227
64228 public function note($message)
64229 {
64230 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
64231 }
64232
64233
64234
64235
64236 public function caution($message)
64237 {
64238 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
64239 }
64240
64241
64242
64243
64244 public function table(array $headers, array $rows)
64245 {
64246 $style = clone Table::getStyleDefinition('symfony-style-guide');
64247 $style->setCellHeaderFormat('<info>%s</info>');
64248
64249 $table = new Table($this);
64250 $table->setHeaders($headers);
64251 $table->setRows($rows);
64252 $table->setStyle($style);
64253
64254 $table->render();
64255 $this->newLine();
64256 }
64257
64258
64259
64260
64261 public function ask($question, $default = null, $validator = null)
64262 {
64263 $question = new Question($question, $default);
64264 $question->setValidator($validator);
64265
64266 return $this->askQuestion($question);
64267 }
64268
64269
64270
64271
64272 public function askHidden($question, $validator = null)
64273 {
64274 $question = new Question($question);
64275
64276 $question->setHidden(true);
64277 $question->setValidator($validator);
64278
64279 return $this->askQuestion($question);
64280 }
64281
64282
64283
64284
64285 public function confirm($question, $default = true)
64286 {
64287 return $this->askQuestion(new ConfirmationQuestion($question, $default));
64288 }
64289
64290
64291
64292
64293 public function choice($question, array $choices, $default = null)
64294 {
64295 if (null !== $default) {
64296 $values = array_flip($choices);
64297 $default = $values[$default];
64298 }
64299
64300 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
64301 }
64302
64303
64304
64305
64306 public function progressStart($max = 0)
64307 {
64308 $this->progressBar = $this->createProgressBar($max);
64309 $this->progressBar->start();
64310 }
64311
64312
64313
64314
64315 public function progressAdvance($step = 1)
64316 {
64317 $this->getProgressBar()->advance($step);
64318 }
64319
64320
64321
64322
64323 public function progressFinish()
64324 {
64325 $this->getProgressBar()->finish();
64326 $this->newLine(2);
64327 $this->progressBar = null;
64328 }
64329
64330
64331
64332
64333 public function createProgressBar($max = 0)
64334 {
64335 $progressBar = parent::createProgressBar($max);
64336
64337 if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
64338 $progressBar->setEmptyBarCharacter('░'); 
64339  $progressBar->setProgressCharacter('');
64340 $progressBar->setBarCharacter('▓'); 
64341  }
64342
64343 return $progressBar;
64344 }
64345
64346
64347
64348
64349 public function askQuestion(Question $question)
64350 {
64351 if ($this->input->isInteractive()) {
64352 $this->autoPrependBlock();
64353 }
64354
64355 if (!$this->questionHelper) {
64356 $this->questionHelper = new SymfonyQuestionHelper();
64357 }
64358
64359 $answer = $this->questionHelper->ask($this->input, $this, $question);
64360
64361 if ($this->input->isInteractive()) {
64362 $this->newLine();
64363 $this->bufferedOutput->write("\n");
64364 }
64365
64366 return $answer;
64367 }
64368
64369
64370
64371
64372 public function writeln($messages, $type = self::OUTPUT_NORMAL)
64373 {
64374 parent::writeln($messages, $type);
64375 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
64376 }
64377
64378
64379
64380
64381 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
64382 {
64383 parent::write($messages, $newline, $type);
64384 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
64385 }
64386
64387
64388
64389
64390 public function newLine($count = 1)
64391 {
64392 parent::newLine($count);
64393 $this->bufferedOutput->write(str_repeat("\n", $count));
64394 }
64395
64396
64397
64398
64399 private function getProgressBar()
64400 {
64401 if (!$this->progressBar) {
64402 throw new RuntimeException('The ProgressBar is not started.');
64403 }
64404
64405 return $this->progressBar;
64406 }
64407
64408 private function getTerminalWidth()
64409 {
64410 $application = new Application();
64411 $dimensions = $application->getTerminalDimensions();
64412
64413 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
64414 }
64415
64416 private function autoPrependBlock()
64417 {
64418 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
64419
64420 if (!isset($chars[0])) {
64421 return $this->newLine(); 
64422  }
64423
64424  $this->newLine(2 - substr_count($chars, "\n"));
64425 }
64426
64427 private function autoPrependText()
64428 {
64429 $fetched = $this->bufferedOutput->fetch();
64430
64431  if ("\n" !== substr($fetched, -1)) {
64432 $this->newLine();
64433 }
64434 }
64435
64436 private function reduceBuffer($messages)
64437 {
64438
64439  
64440  return array_map(function ($value) {
64441 return substr($value, -4);
64442 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
64443 }
64444
64445 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
64446 {
64447 $indentLength = 0;
64448 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
64449 $lines = array();
64450
64451 if (null !== $type) {
64452 $type = sprintf('[%s] ', $type);
64453 $indentLength = \strlen($type);
64454 $lineIndentation = str_repeat(' ', $indentLength);
64455 }
64456
64457
64458  foreach ($messages as $key => $message) {
64459 if ($escape) {
64460 $message = OutputFormatter::escape($message);
64461 }
64462
64463 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
64464
64465 if (\count($messages) > 1 && $key < \count($messages) - 1) {
64466 $lines[] = '';
64467 }
64468 }
64469
64470 $firstLineIndex = 0;
64471 if ($padding && $this->isDecorated()) {
64472 $firstLineIndex = 1;
64473 array_unshift($lines, '');
64474 $lines[] = '';
64475 }
64476
64477 foreach ($lines as $i => &$line) {
64478 if (null !== $type) {
64479 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
64480 }
64481
64482 $line = $prefix.$line;
64483 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
64484
64485 if ($style) {
64486 $line = sprintf('<%s>%s</>', $style, $line);
64487 }
64488 }
64489
64490 return $lines;
64491 }
64492 }
64493 <?php
64494
64495
64496
64497
64498
64499
64500
64501
64502
64503
64504 namespace Symfony\Component\Console\Tester;
64505
64506 use Symfony\Component\Console\Application;
64507 use Symfony\Component\Console\Input\ArrayInput;
64508 use Symfony\Component\Console\Input\InputInterface;
64509 use Symfony\Component\Console\Output\OutputInterface;
64510 use Symfony\Component\Console\Output\StreamOutput;
64511
64512
64513
64514
64515
64516
64517
64518
64519
64520
64521
64522 class ApplicationTester
64523 {
64524 private $application;
64525 private $input;
64526 private $output;
64527 private $statusCode;
64528
64529 public function __construct(Application $application)
64530 {
64531 $this->application = $application;
64532 }
64533
64534
64535
64536
64537
64538
64539
64540
64541
64542
64543
64544
64545
64546
64547
64548 public function run(array $input, $options = array())
64549 {
64550 $this->input = new ArrayInput($input);
64551 if (isset($options['interactive'])) {
64552 $this->input->setInteractive($options['interactive']);
64553 }
64554
64555 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
64556 if (isset($options['decorated'])) {
64557 $this->output->setDecorated($options['decorated']);
64558 }
64559 if (isset($options['verbosity'])) {
64560 $this->output->setVerbosity($options['verbosity']);
64561 }
64562
64563 return $this->statusCode = $this->application->run($this->input, $this->output);
64564 }
64565
64566
64567
64568
64569
64570
64571
64572
64573 public function getDisplay($normalize = false)
64574 {
64575 rewind($this->output->getStream());
64576
64577 $display = stream_get_contents($this->output->getStream());
64578
64579 if ($normalize) {
64580 $display = str_replace(PHP_EOL, "\n", $display);
64581 }
64582
64583 return $display;
64584 }
64585
64586
64587
64588
64589
64590
64591 public function getInput()
64592 {
64593 return $this->input;
64594 }
64595
64596
64597
64598
64599
64600
64601 public function getOutput()
64602 {
64603 return $this->output;
64604 }
64605
64606
64607
64608
64609
64610
64611 public function getStatusCode()
64612 {
64613 return $this->statusCode;
64614 }
64615 }
64616 <?php
64617
64618
64619
64620
64621
64622
64623
64624
64625
64626
64627 namespace Symfony\Component\Console\Tester;
64628
64629 use Symfony\Component\Console\Command\Command;
64630 use Symfony\Component\Console\Input\ArrayInput;
64631 use Symfony\Component\Console\Input\InputInterface;
64632 use Symfony\Component\Console\Output\OutputInterface;
64633 use Symfony\Component\Console\Output\StreamOutput;
64634
64635
64636
64637
64638
64639
64640 class CommandTester
64641 {
64642 private $command;
64643 private $input;
64644 private $output;
64645 private $statusCode;
64646
64647 public function __construct(Command $command)
64648 {
64649 $this->command = $command;
64650 }
64651
64652
64653
64654
64655
64656
64657
64658
64659
64660
64661
64662
64663
64664
64665
64666 public function execute(array $input, array $options = array())
64667 {
64668
64669  
64670  if (!isset($input['command'])
64671 && (null !== $application = $this->command->getApplication())
64672 && $application->getDefinition()->hasArgument('command')
64673 ) {
64674 $input = array_merge(array('command' => $this->command->getName()), $input);
64675 }
64676
64677 $this->input = new ArrayInput($input);
64678 if (isset($options['interactive'])) {
64679 $this->input->setInteractive($options['interactive']);
64680 }
64681
64682 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
64683 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
64684 if (isset($options['verbosity'])) {
64685 $this->output->setVerbosity($options['verbosity']);
64686 }
64687
64688 return $this->statusCode = $this->command->run($this->input, $this->output);
64689 }
64690
64691
64692
64693
64694
64695
64696
64697
64698 public function getDisplay($normalize = false)
64699 {
64700 rewind($this->output->getStream());
64701
64702 $display = stream_get_contents($this->output->getStream());
64703
64704 if ($normalize) {
64705 $display = str_replace(PHP_EOL, "\n", $display);
64706 }
64707
64708 return $display;
64709 }
64710
64711
64712
64713
64714
64715
64716 public function getInput()
64717 {
64718 return $this->input;
64719 }
64720
64721
64722
64723
64724
64725
64726 public function getOutput()
64727 {
64728 return $this->output;
64729 }
64730
64731
64732
64733
64734
64735
64736 public function getStatusCode()
64737 {
64738 return $this->statusCode;
64739 }
64740 }
64741 <?php
64742
64743
64744
64745
64746
64747
64748
64749
64750
64751
64752 namespace Symfony\Component\Debug;
64753
64754 use Psr\Log\AbstractLogger;
64755
64756
64757
64758
64759
64760
64761 class BufferingLogger extends AbstractLogger
64762 {
64763 private $logs = array();
64764
64765 public function log($level, $message, array $context = array())
64766 {
64767 $this->logs[] = array($level, $message, $context);
64768 }
64769
64770 public function cleanLogs()
64771 {
64772 $logs = $this->logs;
64773 $this->logs = array();
64774
64775 return $logs;
64776 }
64777 }
64778 <?php
64779
64780
64781
64782
64783
64784
64785
64786
64787
64788
64789 namespace Symfony\Component\Debug;
64790
64791
64792
64793
64794
64795
64796 class Debug
64797 {
64798 private static $enabled = false;
64799
64800
64801
64802
64803
64804
64805
64806
64807
64808 public static function enable($errorReportingLevel = null, $displayErrors = true)
64809 {
64810 if (static::$enabled) {
64811 return;
64812 }
64813
64814 static::$enabled = true;
64815
64816 if (null !== $errorReportingLevel) {
64817 error_reporting($errorReportingLevel);
64818 } else {
64819 error_reporting(-1);
64820 }
64821
64822 if (!\in_array(\PHP_SAPI, array('cli', 'phpdbg'), true)) {
64823 ini_set('display_errors', 0);
64824 ExceptionHandler::register();
64825 } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) {
64826
64827  ini_set('display_errors', 1);
64828 }
64829 if ($displayErrors) {
64830 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
64831 } else {
64832 ErrorHandler::register()->throwAt(0, true);
64833 }
64834
64835 DebugClassLoader::enable();
64836 }
64837 }
64838 <?php
64839
64840
64841
64842
64843
64844
64845
64846
64847
64848
64849 namespace Symfony\Component\Debug;
64850
64851
64852
64853
64854
64855
64856
64857
64858
64859
64860
64861
64862 class DebugClassLoader
64863 {
64864 private $classLoader;
64865 private $isFinder;
64866 private $loaded = array();
64867 private $wasFinder;
64868 private static $caseCheck;
64869 private static $deprecated = array();
64870 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
64871 private static $darwinCache = array('/' => array('/', array()));
64872
64873
64874
64875
64876 public function __construct($classLoader)
64877 {
64878 $this->wasFinder = \is_object($classLoader) && method_exists($classLoader, 'findFile');
64879
64880 if ($this->wasFinder) {
64881 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
64882 $this->classLoader = array($classLoader, 'loadClass');
64883 $this->isFinder = true;
64884 } else {
64885 $this->classLoader = $classLoader;
64886 $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
64887 }
64888
64889 if (!isset(self::$caseCheck)) {
64890 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
64891 $i = strrpos($file, \DIRECTORY_SEPARATOR);
64892 $dir = substr($file, 0, 1 + $i);
64893 $file = substr($file, 1 + $i);
64894 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
64895 $test = realpath($dir.$test);
64896
64897 if (false === $test || false === $i) {
64898
64899  self::$caseCheck = 0;
64900 } elseif (substr($test, -\strlen($file)) === $file) {
64901
64902  self::$caseCheck = 1;
64903 } elseif (false !== stripos(PHP_OS, 'darwin')) {
64904
64905  self::$caseCheck = 2;
64906 } else {
64907
64908  self::$caseCheck = 0;
64909 }
64910 }
64911 }
64912
64913
64914
64915
64916
64917
64918 public function getClassLoader()
64919 {
64920 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
64921 }
64922
64923
64924
64925
64926 public static function enable()
64927 {
64928
64929  class_exists('Symfony\Component\Debug\ErrorHandler');
64930 class_exists('Psr\Log\LogLevel');
64931
64932 if (!\is_array($functions = spl_autoload_functions())) {
64933 return;
64934 }
64935
64936 foreach ($functions as $function) {
64937 spl_autoload_unregister($function);
64938 }
64939
64940 foreach ($functions as $function) {
64941 if (!\is_array($function) || !$function[0] instanceof self) {
64942 $function = array(new static($function), 'loadClass');
64943 }
64944
64945 spl_autoload_register($function);
64946 }
64947 }
64948
64949
64950
64951
64952 public static function disable()
64953 {
64954 if (!\is_array($functions = spl_autoload_functions())) {
64955 return;
64956 }
64957
64958 foreach ($functions as $function) {
64959 spl_autoload_unregister($function);
64960 }
64961
64962 foreach ($functions as $function) {
64963 if (\is_array($function) && $function[0] instanceof self) {
64964 $function = $function[0]->getClassLoader();
64965 }
64966
64967 spl_autoload_register($function);
64968 }
64969 }
64970
64971
64972
64973
64974
64975
64976
64977
64978
64979
64980 public function findFile($class)
64981 {
64982 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
64983
64984 if ($this->wasFinder) {
64985 return $this->classLoader[0]->findFile($class);
64986 }
64987 }
64988
64989
64990
64991
64992
64993
64994
64995
64996
64997
64998 public function loadClass($class)
64999 {
65000 ErrorHandler::stackErrors();
65001
65002 try {
65003 if ($this->isFinder && !isset($this->loaded[$class])) {
65004 $this->loaded[$class] = true;
65005 if ($file = $this->classLoader[0]->findFile($class)) {
65006 require $file;
65007 }
65008 } else {
65009 \call_user_func($this->classLoader, $class);
65010 $file = false;
65011 }
65012 } catch (\Exception $e) {
65013 ErrorHandler::unstackErrors();
65014
65015 throw $e;
65016 } catch (\Throwable $e) {
65017 ErrorHandler::unstackErrors();
65018
65019 throw $e;
65020 }
65021
65022 ErrorHandler::unstackErrors();
65023
65024 $exists = class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
65025
65026 if ($class && '\\' === $class[0]) {
65027 $class = substr($class, 1);
65028 }
65029
65030 if ($exists) {
65031 $refl = new \ReflectionClass($class);
65032 $name = $refl->getName();
65033
65034 if ($name !== $class && 0 === strcasecmp($name, $class)) {
65035 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
65036 }
65037
65038 if (\in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
65039 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
65040 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
65041 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
65042 } else {
65043 if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
65044 $len = 0;
65045 $ns = '';
65046 } else {
65047 $ns = substr($name, 0, $len);
65048 }
65049 $parent = get_parent_class($class);
65050
65051 if (!$parent || strncmp($ns, $parent, $len)) {
65052 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
65053 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
65054 }
65055
65056 $parentInterfaces = array();
65057 $deprecatedInterfaces = array();
65058 if ($parent) {
65059 foreach (class_implements($parent) as $interface) {
65060 $parentInterfaces[$interface] = 1;
65061 }
65062 }
65063
65064 foreach ($refl->getInterfaceNames() as $interface) {
65065 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
65066 $deprecatedInterfaces[] = $interface;
65067 }
65068 foreach (class_implements($interface) as $interface) {
65069 $parentInterfaces[$interface] = 1;
65070 }
65071 }
65072
65073 foreach ($deprecatedInterfaces as $interface) {
65074 if (!isset($parentInterfaces[$interface])) {
65075 @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);
65076 }
65077 }
65078 }
65079 }
65080 }
65081
65082 if ($file) {
65083 if (!$exists) {
65084 if (false !== strpos($class, '/')) {
65085 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));
65086 }
65087
65088 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));
65089 }
65090 if (self::$caseCheck) {
65091 $real = explode('\\', $class.strrchr($file, '.'));
65092 $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
65093
65094 $i = \count($tail) - 1;
65095 $j = \count($real) - 1;
65096
65097 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
65098 --$i;
65099 --$j;
65100 }
65101
65102 array_splice($tail, 0, $i + 1);
65103 }
65104 if (self::$caseCheck && $tail) {
65105 $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
65106 $tailLen = \strlen($tail);
65107 $real = $refl->getFileName();
65108
65109 if (2 === self::$caseCheck) {
65110
65111
65112 $i = 1 + strrpos($real, '/');
65113 $file = substr($real, $i);
65114 $real = substr($real, 0, $i);
65115
65116 if (isset(self::$darwinCache[$real])) {
65117 $kDir = $real;
65118 } else {
65119 $kDir = strtolower($real);
65120
65121 if (isset(self::$darwinCache[$kDir])) {
65122 $real = self::$darwinCache[$kDir][0];
65123 } else {
65124 $dir = getcwd();
65125 chdir($real);
65126 $real = getcwd().'/';
65127 chdir($dir);
65128
65129 $dir = $real;
65130 $k = $kDir;
65131 $i = \strlen($dir) - 1;
65132 while (!isset(self::$darwinCache[$k])) {
65133 self::$darwinCache[$k] = array($dir, array());
65134 self::$darwinCache[$dir] = &self::$darwinCache[$k];
65135
65136 while ('/' !== $dir[--$i]) {
65137 }
65138 $k = substr($k, 0, ++$i);
65139 $dir = substr($dir, 0, $i--);
65140 }
65141 }
65142 }
65143
65144 $dirFiles = self::$darwinCache[$kDir][1];
65145
65146 if (isset($dirFiles[$file])) {
65147 $kFile = $file;
65148 } else {
65149 $kFile = strtolower($file);
65150
65151 if (!isset($dirFiles[$kFile])) {
65152 foreach (scandir($real, 2) as $f) {
65153 if ('.' !== $f[0]) {
65154 $dirFiles[$f] = $f;
65155 if ($f === $file) {
65156 $kFile = $k = $file;
65157 } elseif ($f !== $k = strtolower($f)) {
65158 $dirFiles[$k] = $f;
65159 }
65160 }
65161 }
65162 self::$darwinCache[$kDir][1] = $dirFiles;
65163 }
65164 }
65165
65166 $real .= $dirFiles[$kFile];
65167 }
65168
65169 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
65170 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
65171 ) {
65172 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)));
65173 }
65174 }
65175
65176 return true;
65177 }
65178 }
65179 }
65180 <?php
65181
65182
65183
65184
65185
65186
65187
65188
65189
65190
65191 namespace Symfony\Component\Debug;
65192
65193 use Psr\Log\LoggerInterface;
65194 use Psr\Log\LogLevel;
65195 use Symfony\Component\Debug\Exception\ContextErrorException;
65196 use Symfony\Component\Debug\Exception\FatalErrorException;
65197 use Symfony\Component\Debug\Exception\FatalThrowableError;
65198 use Symfony\Component\Debug\Exception\OutOfMemoryException;
65199 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
65200 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
65201 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
65202 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
65203
65204
65205
65206
65207
65208
65209
65210
65211
65212
65213
65214
65215
65216
65217
65218
65219
65220
65221
65222
65223
65224
65225
65226 class ErrorHandler
65227 {
65228
65229
65230
65231 const TYPE_DEPRECATION = -100;
65232
65233 private $levels = array(
65234 E_DEPRECATED => 'Deprecated',
65235 E_USER_DEPRECATED => 'User Deprecated',
65236 E_NOTICE => 'Notice',
65237 E_USER_NOTICE => 'User Notice',
65238 E_STRICT => 'Runtime Notice',
65239 E_WARNING => 'Warning',
65240 E_USER_WARNING => 'User Warning',
65241 E_COMPILE_WARNING => 'Compile Warning',
65242 E_CORE_WARNING => 'Core Warning',
65243 E_USER_ERROR => 'User Error',
65244 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
65245 E_COMPILE_ERROR => 'Compile Error',
65246 E_PARSE => 'Parse Error',
65247 E_ERROR => 'Error',
65248 E_CORE_ERROR => 'Core Error',
65249 );
65250
65251 private $loggers = array(
65252 E_DEPRECATED => array(null, LogLevel::INFO),
65253 E_USER_DEPRECATED => array(null, LogLevel::INFO),
65254 E_NOTICE => array(null, LogLevel::WARNING),
65255 E_USER_NOTICE => array(null, LogLevel::WARNING),
65256 E_STRICT => array(null, LogLevel::WARNING),
65257 E_WARNING => array(null, LogLevel::WARNING),
65258 E_USER_WARNING => array(null, LogLevel::WARNING),
65259 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
65260 E_CORE_WARNING => array(null, LogLevel::WARNING),
65261 E_USER_ERROR => array(null, LogLevel::CRITICAL),
65262 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
65263 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
65264 E_PARSE => array(null, LogLevel::CRITICAL),
65265 E_ERROR => array(null, LogLevel::CRITICAL),
65266 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
65267 );
65268
65269 private $thrownErrors = 0x1FFF; 
65270  private $scopedErrors = 0x1FFF; 
65271  private $tracedErrors = 0x77FB; 
65272  private $screamedErrors = 0x55; 
65273  private $loggedErrors = 0;
65274
65275 private $loggedTraces = array();
65276 private $isRecursive = 0;
65277 private $isRoot = false;
65278 private $exceptionHandler;
65279 private $bootstrappingLogger;
65280
65281 private static $reservedMemory;
65282 private static $stackedErrors = array();
65283 private static $stackedErrorLevels = array();
65284 private static $toStringException = null;
65285 private static $exitCode = 0;
65286
65287
65288
65289
65290
65291
65292 private $displayErrors = 0x1FFF;
65293
65294
65295
65296
65297
65298
65299
65300
65301
65302 public static function register($handler = null, $replace = true)
65303 {
65304 if (null === self::$reservedMemory) {
65305 self::$reservedMemory = str_repeat('x', 10240);
65306 register_shutdown_function(__CLASS__.'::handleFatalError');
65307 }
65308
65309 $levels = -1;
65310
65311 if ($handlerIsNew = !$handler instanceof self) {
65312
65313  if (null !== $handler) {
65314 $levels = $replace ? $handler : 0;
65315 $replace = true;
65316 }
65317 $handler = new static();
65318 }
65319
65320 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
65321 restore_error_handler();
65322
65323  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
65324 $handler->isRoot = true;
65325 }
65326
65327 if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) {
65328 $handler = $prev[0];
65329 $replace = false;
65330 }
65331 if (!$replace && $prev) {
65332 restore_error_handler();
65333 $handlerIsRegistered = \is_array($prev) && $handler === $prev[0];
65334 } else {
65335 $handlerIsRegistered = true;
65336 }
65337 if (\is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) {
65338 restore_exception_handler();
65339 if (!$handlerIsRegistered) {
65340 $handler = $prev[0];
65341 } elseif ($handler !== $prev[0] && $replace) {
65342 set_exception_handler(array($handler, 'handleException'));
65343 $p = $prev[0]->setExceptionHandler(null);
65344 $handler->setExceptionHandler($p);
65345 $prev[0]->setExceptionHandler($p);
65346 }
65347 } else {
65348 $handler->setExceptionHandler($prev);
65349 }
65350
65351 $handler->throwAt($levels & $handler->thrownErrors, true);
65352
65353 return $handler;
65354 }
65355
65356 public function __construct(BufferingLogger $bootstrappingLogger = null)
65357 {
65358 if ($bootstrappingLogger) {
65359 $this->bootstrappingLogger = $bootstrappingLogger;
65360 $this->setDefaultLogger($bootstrappingLogger);
65361 }
65362 }
65363
65364
65365
65366
65367
65368
65369
65370
65371 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
65372 {
65373 $loggers = array();
65374
65375 if (\is_array($levels)) {
65376 foreach ($levels as $type => $logLevel) {
65377 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
65378 $loggers[$type] = array($logger, $logLevel);
65379 }
65380 }
65381 } else {
65382 if (null === $levels) {
65383 $levels = E_ALL | E_STRICT;
65384 }
65385 foreach ($this->loggers as $type => $log) {
65386 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
65387 $log[0] = $logger;
65388 $loggers[$type] = $log;
65389 }
65390 }
65391 }
65392
65393 $this->setLoggers($loggers);
65394 }
65395
65396
65397
65398
65399
65400
65401
65402
65403
65404
65405 public function setLoggers(array $loggers)
65406 {
65407 $prevLogged = $this->loggedErrors;
65408 $prev = $this->loggers;
65409 $flush = array();
65410
65411 foreach ($loggers as $type => $log) {
65412 if (!isset($prev[$type])) {
65413 throw new \InvalidArgumentException('Unknown error type: '.$type);
65414 }
65415 if (!\is_array($log)) {
65416 $log = array($log);
65417 } elseif (!array_key_exists(0, $log)) {
65418 throw new \InvalidArgumentException('No logger provided');
65419 }
65420 if (null === $log[0]) {
65421 $this->loggedErrors &= ~$type;
65422 } elseif ($log[0] instanceof LoggerInterface) {
65423 $this->loggedErrors |= $type;
65424 } else {
65425 throw new \InvalidArgumentException('Invalid logger provided');
65426 }
65427 $this->loggers[$type] = $log + $prev[$type];
65428
65429 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
65430 $flush[$type] = $type;
65431 }
65432 }
65433 $this->reRegister($prevLogged | $this->thrownErrors);
65434
65435 if ($flush) {
65436 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
65437 $type = $log[2]['type'];
65438 if (!isset($flush[$type])) {
65439 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
65440 } elseif ($this->loggers[$type][0]) {
65441 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
65442 }
65443 }
65444 }
65445
65446 return $prev;
65447 }
65448
65449
65450
65451
65452
65453
65454
65455
65456
65457
65458 public function setExceptionHandler($handler)
65459 {
65460 if (null !== $handler && !\is_callable($handler)) {
65461 throw new \LogicException('The exception handler must be a valid PHP callable.');
65462 }
65463 $prev = $this->exceptionHandler;
65464 $this->exceptionHandler = $handler;
65465
65466 return $prev;
65467 }
65468
65469
65470
65471
65472
65473
65474
65475
65476
65477 public function throwAt($levels, $replace = false)
65478 {
65479 $prev = $this->thrownErrors;
65480 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
65481 if (!$replace) {
65482 $this->thrownErrors |= $prev;
65483 }
65484 $this->reRegister($prev | $this->loggedErrors);
65485
65486
65487  $this->displayErrors = $this->thrownErrors;
65488
65489 return $prev;
65490 }
65491
65492
65493
65494
65495
65496
65497
65498
65499
65500 public function scopeAt($levels, $replace = false)
65501 {
65502 $prev = $this->scopedErrors;
65503 $this->scopedErrors = (int) $levels;
65504 if (!$replace) {
65505 $this->scopedErrors |= $prev;
65506 }
65507
65508 return $prev;
65509 }
65510
65511
65512
65513
65514
65515
65516
65517
65518
65519 public function traceAt($levels, $replace = false)
65520 {
65521 $prev = $this->tracedErrors;
65522 $this->tracedErrors = (int) $levels;
65523 if (!$replace) {
65524 $this->tracedErrors |= $prev;
65525 }
65526
65527 return $prev;
65528 }
65529
65530
65531
65532
65533
65534
65535
65536
65537
65538 public function screamAt($levels, $replace = false)
65539 {
65540 $prev = $this->screamedErrors;
65541 $this->screamedErrors = (int) $levels;
65542 if (!$replace) {
65543 $this->screamedErrors |= $prev;
65544 }
65545
65546 return $prev;
65547 }
65548
65549
65550
65551
65552 private function reRegister($prev)
65553 {
65554 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
65555 $handler = set_error_handler('var_dump');
65556 $handler = \is_array($handler) ? $handler[0] : null;
65557 restore_error_handler();
65558 if ($handler === $this) {
65559 restore_error_handler();
65560 if ($this->isRoot) {
65561 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
65562 } else {
65563 set_error_handler(array($this, 'handleError'));
65564 }
65565 }
65566 }
65567 }
65568
65569
65570
65571
65572
65573
65574
65575
65576
65577
65578
65579
65580
65581
65582
65583 public function handleError($type, $message, $file, $line)
65584 {
65585 $level = error_reporting();
65586 $silenced = 0 === ($level & $type);
65587 $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
65588 $log = $this->loggedErrors & $type;
65589 $throw = $this->thrownErrors & $type & $level;
65590 $type &= $level | $this->screamedErrors;
65591
65592 if (!$type || (!$log && !$throw)) {
65593 return !$silenced && $type && $log;
65594 }
65595 $scope = $this->scopedErrors & $type;
65596
65597 if (4 < $numArgs = \func_num_args()) {
65598 $context = $scope ? (func_get_arg(4) ?: array()) : array();
65599 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
65600  } else {
65601 $context = array();
65602 $backtrace = null;
65603 }
65604
65605 if (isset($context['GLOBALS']) && $scope) {
65606 $e = $context; 
65607  unset($e['GLOBALS'], $context); 
65608  $context = $e;
65609 }
65610
65611 if (null !== $backtrace && $type & E_ERROR) {
65612
65613  
65614  
65615  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
65616
65617 return true;
65618 }
65619
65620 if ($throw) {
65621 if (null !== self::$toStringException) {
65622 $throw = self::$toStringException;
65623 self::$toStringException = null;
65624 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
65625
65626  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
65627 } else {
65628 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
65629 }
65630
65631 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
65632
65633  
65634  
65635
65636 $throw->errorHandlerCanary = new ErrorHandlerCanary();
65637 }
65638
65639 if (E_USER_ERROR & $type) {
65640 $backtrace = $backtrace ?: $throw->getTrace();
65641
65642 for ($i = 1; isset($backtrace[$i]); ++$i) {
65643 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
65644 && '__toString' === $backtrace[$i]['function']
65645 && '->' === $backtrace[$i]['type']
65646 && !isset($backtrace[$i - 1]['class'])
65647 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
65648 ) {
65649
65650  
65651  
65652  
65653  
65654  
65655
65656 foreach ($context as $e) {
65657 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
65658 if (1 === $i) {
65659
65660  $throw = $e;
65661 break;
65662 }
65663 self::$toStringException = $e;
65664
65665 return true;
65666 }
65667 }
65668
65669 if (1 < $i) {
65670
65671  $this->handleException($throw);
65672
65673
65674  return false;
65675 }
65676 }
65677 }
65678 }
65679
65680 throw $throw;
65681 }
65682
65683
65684  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
65685 $trace = true;
65686
65687 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
65688 $trace = false;
65689 } else {
65690 $this->loggedTraces[$e] = 1;
65691 }
65692
65693 $e = compact('type', 'file', 'line', 'level');
65694
65695 if ($type & $level) {
65696 if ($scope) {
65697 $e['scope_vars'] = $context;
65698 if ($trace) {
65699 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
65700 }
65701 } elseif ($trace) {
65702 if (null === $backtrace) {
65703 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
65704 } else {
65705 foreach ($backtrace as &$frame) {
65706 unset($frame['args'], $frame);
65707 }
65708 $e['stack'] = $backtrace;
65709 }
65710 }
65711 }
65712
65713 if ($this->isRecursive) {
65714 $log = 0;
65715 } elseif (self::$stackedErrorLevels) {
65716 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
65717 } else {
65718 try {
65719 $this->isRecursive = true;
65720 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
65721 $this->isRecursive = false;
65722 } catch (\Exception $e) {
65723 $this->isRecursive = false;
65724
65725 throw $e;
65726 } catch (\Throwable $e) {
65727 $this->isRecursive = false;
65728
65729 throw $e;
65730 }
65731 }
65732
65733 return !$silenced && $type && $log;
65734 }
65735
65736
65737
65738
65739
65740
65741
65742
65743
65744 public function handleException($exception, array $error = null)
65745 {
65746 if (null === $error) {
65747 self::$exitCode = 255;
65748 }
65749 if (!$exception instanceof \Exception) {
65750 $exception = new FatalThrowableError($exception);
65751 }
65752 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
65753 $handlerException = null;
65754
65755 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
65756 $e = array(
65757 'type' => $type,
65758 'file' => $exception->getFile(),
65759 'line' => $exception->getLine(),
65760 'level' => error_reporting(),
65761 'stack' => $exception->getTrace(),
65762 );
65763 if ($exception instanceof FatalErrorException) {
65764 if ($exception instanceof FatalThrowableError) {
65765 $error = array(
65766 'type' => $type,
65767 'message' => $message = $exception->getMessage(),
65768 'file' => $e['file'],
65769 'line' => $e['line'],
65770 );
65771 } else {
65772 $message = 'Fatal '.$exception->getMessage();
65773 }
65774 } elseif ($exception instanceof \ErrorException) {
65775 $message = 'Uncaught '.$exception->getMessage();
65776 if ($exception instanceof ContextErrorException) {
65777 $e['context'] = $exception->getContext();
65778 }
65779 } else {
65780 $message = 'Uncaught Exception: '.$exception->getMessage();
65781 }
65782 }
65783 if ($this->loggedErrors & $type) {
65784 try {
65785 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
65786 } catch (\Exception $handlerException) {
65787 } catch (\Throwable $handlerException) {
65788 }
65789 }
65790 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
65791 foreach ($this->getFatalErrorHandlers() as $handler) {
65792 if ($e = $handler->handleError($error, $exception)) {
65793 $exception = $e;
65794 break;
65795 }
65796 }
65797 }
65798 $exceptionHandler = $this->exceptionHandler;
65799 $this->exceptionHandler = null;
65800 try {
65801 if (null !== $exceptionHandler) {
65802 return \call_user_func($exceptionHandler, $exception);
65803 }
65804 $handlerException = $handlerException ?: $exception;
65805 } catch (\Exception $handlerException) {
65806 } catch (\Throwable $handlerException) {
65807 }
65808 if ($exception === $handlerException) {
65809 self::$reservedMemory = null; 
65810  throw $exception; 
65811  }
65812 $this->handleException($handlerException);
65813 }
65814
65815
65816
65817
65818
65819
65820
65821
65822 public static function handleFatalError(array $error = null)
65823 {
65824 if (null === self::$reservedMemory) {
65825 return;
65826 }
65827
65828 $handler = self::$reservedMemory = null;
65829 $handlers = array();
65830 $previousHandler = null;
65831 $sameHandlerLimit = 10;
65832
65833 while (!\is_array($handler) || !$handler[0] instanceof self) {
65834 $handler = set_exception_handler('var_dump');
65835 restore_exception_handler();
65836
65837 if (!$handler) {
65838 break;
65839 }
65840 restore_exception_handler();
65841
65842 if ($handler !== $previousHandler) {
65843 array_unshift($handlers, $handler);
65844 $previousHandler = $handler;
65845 } elseif (0 === --$sameHandlerLimit) {
65846 $handler = null;
65847 break;
65848 }
65849 }
65850 foreach ($handlers as $h) {
65851 set_exception_handler($h);
65852 }
65853 if (!$handler) {
65854 return;
65855 }
65856 if ($handler !== $h) {
65857 $handler[0]->setExceptionHandler($h);
65858 }
65859 $handler = $handler[0];
65860 $handlers = array();
65861
65862 if ($exit = null === $error) {
65863 $error = error_get_last();
65864 }
65865
65866 try {
65867 while (self::$stackedErrorLevels) {
65868 static::unstackErrors();
65869 }
65870 } catch (\Exception $exception) {
65871
65872  } catch (\Throwable $exception) {
65873
65874  }
65875
65876 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
65877
65878  $handler->throwAt(0, true);
65879 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
65880
65881 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
65882 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
65883 } else {
65884 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
65885 }
65886 }
65887
65888 try {
65889 if (isset($exception)) {
65890 self::$exitCode = 255;
65891 $handler->handleException($exception, $error);
65892 }
65893 } catch (FatalErrorException $e) {
65894
65895  }
65896
65897 if ($exit && self::$exitCode) {
65898 $exitCode = self::$exitCode;
65899 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
65900 }
65901 }
65902
65903
65904
65905
65906
65907
65908
65909
65910
65911
65912
65913
65914 public static function stackErrors()
65915 {
65916 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
65917 }
65918
65919
65920
65921
65922 public static function unstackErrors()
65923 {
65924 $level = array_pop(self::$stackedErrorLevels);
65925
65926 if (null !== $level) {
65927 $e = error_reporting($level);
65928 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
65929
65930  error_reporting($e);
65931 }
65932 }
65933
65934 if (empty(self::$stackedErrorLevels)) {
65935 $errors = self::$stackedErrors;
65936 self::$stackedErrors = array();
65937
65938 foreach ($errors as $e) {
65939 $e[0]->log($e[1], $e[2], $e[3]);
65940 }
65941 }
65942 }
65943
65944
65945
65946
65947
65948
65949
65950
65951 protected function getFatalErrorHandlers()
65952 {
65953 return array(
65954 new UndefinedFunctionFatalErrorHandler(),
65955 new UndefinedMethodFatalErrorHandler(),
65956 new ClassNotFoundFatalErrorHandler(),
65957 );
65958 }
65959
65960
65961
65962
65963
65964
65965
65966
65967 public function setLevel($level)
65968 {
65969 @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);
65970
65971 $level = null === $level ? error_reporting() : $level;
65972 $this->throwAt($level, true);
65973 }
65974
65975
65976
65977
65978
65979
65980
65981
65982 public function setDisplayErrors($displayErrors)
65983 {
65984 @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);
65985
65986 if ($displayErrors) {
65987 $this->throwAt($this->displayErrors, true);
65988 } else {
65989 $displayErrors = $this->displayErrors;
65990 $this->throwAt(0, true);
65991 $this->displayErrors = $displayErrors;
65992 }
65993 }
65994
65995
65996
65997
65998
65999
66000
66001
66002
66003 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
66004 {
66005 @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);
66006
66007 $handler = set_error_handler('var_dump');
66008 $handler = \is_array($handler) ? $handler[0] : null;
66009 restore_error_handler();
66010 if (!$handler instanceof self) {
66011 return;
66012 }
66013 if ('deprecation' === $channel) {
66014 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
66015 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
66016 } elseif ('scream' === $channel) {
66017 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
66018 $handler->screamAt(E_ALL | E_STRICT);
66019 } elseif ('emergency' === $channel) {
66020 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
66021 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
66022 }
66023 }
66024
66025
66026
66027
66028 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
66029 {
66030 $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());
66031
66032 return $this->handleError($level, $message, $file, $line, (array) $context);
66033 }
66034
66035
66036
66037
66038
66039
66040 public function handleFatal()
66041 {
66042 @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);
66043
66044 static::handleFatalError();
66045 }
66046 }
66047
66048
66049
66050
66051
66052
66053
66054
66055 class ErrorHandlerCanary
66056 {
66057 private static $displayErrors = null;
66058
66059 public function __construct()
66060 {
66061 if (null === self::$displayErrors) {
66062 self::$displayErrors = ini_set('display_errors', 1);
66063 }
66064 }
66065
66066 public function __destruct()
66067 {
66068 if (null !== self::$displayErrors) {
66069 ini_set('display_errors', self::$displayErrors);
66070 self::$displayErrors = null;
66071 }
66072 }
66073 }
66074 <?php
66075
66076
66077
66078
66079
66080
66081
66082
66083
66084
66085 namespace Symfony\Component\Debug\Exception;
66086
66087
66088
66089
66090
66091
66092 class ClassNotFoundException extends FatalErrorException
66093 {
66094 public function __construct($message, \ErrorException $previous)
66095 {
66096 parent::__construct(
66097 $message,
66098 $previous->getCode(),
66099 $previous->getSeverity(),
66100 $previous->getFile(),
66101 $previous->getLine(),
66102 null,
66103 true,
66104 null,
66105 $previous->getPrevious()
66106 );
66107 $this->setTrace($previous->getTrace());
66108 }
66109 }
66110 <?php
66111
66112
66113
66114
66115
66116
66117
66118
66119
66120
66121 namespace Symfony\Component\Debug\Exception;
66122
66123
66124
66125
66126
66127
66128 class ContextErrorException extends \ErrorException
66129 {
66130 private $context = array();
66131
66132 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
66133 {
66134 parent::__construct($message, $code, $severity, $filename, $lineno);
66135 $this->context = $context;
66136 }
66137
66138
66139
66140
66141 public function getContext()
66142 {
66143 return $this->context;
66144 }
66145 }
66146 <?php
66147
66148
66149
66150
66151
66152
66153
66154
66155
66156
66157 namespace Symfony\Component\Debug\Exception;
66158
66159 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
66160
66161
66162
66163
66164
66165
66166 class DummyException extends \ErrorException
66167 {
66168 }
66169 <?php
66170
66171
66172
66173
66174
66175
66176
66177
66178
66179
66180 namespace Symfony\Component\HttpKernel\Exception;
66181
66182
66183
66184
66185
66186
66187
66188
66189
66190
66191 class FatalErrorException extends \ErrorException
66192 {
66193 }
66194
66195 namespace Symfony\Component\Debug\Exception;
66196
66197 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
66198
66199
66200
66201
66202
66203
66204 class FatalErrorException extends LegacyFatalErrorException
66205 {
66206 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null, $previous = null)
66207 {
66208 parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
66209
66210 if (null !== $trace) {
66211 if (!$traceArgs) {
66212 foreach ($trace as &$frame) {
66213 unset($frame['args'], $frame['this'], $frame);
66214 }
66215 }
66216
66217 $this->setTrace($trace);
66218 } elseif (null !== $traceOffset) {
66219 if (\function_exists('xdebug_get_function_stack')) {
66220 $trace = xdebug_get_function_stack();
66221 if (0 < $traceOffset) {
66222 array_splice($trace, -$traceOffset);
66223 }
66224
66225 foreach ($trace as &$frame) {
66226 if (!isset($frame['type'])) {
66227
66228  if (isset($frame['class'])) {
66229 $frame['type'] = '::';
66230 }
66231 } elseif ('dynamic' === $frame['type']) {
66232 $frame['type'] = '->';
66233 } elseif ('static' === $frame['type']) {
66234 $frame['type'] = '::';
66235 }
66236
66237
66238  if (!$traceArgs) {
66239 unset($frame['params'], $frame['args']);
66240 } elseif (isset($frame['params']) && !isset($frame['args'])) {
66241 $frame['args'] = $frame['params'];
66242 unset($frame['params']);
66243 }
66244 }
66245
66246 unset($frame);
66247 $trace = array_reverse($trace);
66248 } elseif (\function_exists('symfony_debug_backtrace')) {
66249 $trace = symfony_debug_backtrace();
66250 if (0 < $traceOffset) {
66251 array_splice($trace, 0, $traceOffset);
66252 }
66253 } else {
66254 $trace = array();
66255 }
66256
66257 $this->setTrace($trace);
66258 }
66259 }
66260
66261 protected function setTrace($trace)
66262 {
66263 $traceReflector = new \ReflectionProperty('Exception', 'trace');
66264 $traceReflector->setAccessible(true);
66265 $traceReflector->setValue($this, $trace);
66266 }
66267 }
66268 <?php
66269
66270
66271
66272
66273
66274
66275
66276
66277
66278
66279 namespace Symfony\Component\Debug\Exception;
66280
66281
66282
66283
66284
66285
66286 class FatalThrowableError extends FatalErrorException
66287 {
66288 public function __construct(\Throwable $e)
66289 {
66290 if ($e instanceof \ParseError) {
66291 $message = 'Parse error: '.$e->getMessage();
66292 $severity = E_PARSE;
66293 } elseif ($e instanceof \TypeError) {
66294 $message = 'Type error: '.$e->getMessage();
66295 $severity = E_RECOVERABLE_ERROR;
66296 } else {
66297 $message = $e->getMessage();
66298 $severity = E_ERROR;
66299 }
66300
66301 \ErrorException::__construct(
66302 $message,
66303 $e->getCode(),
66304 $severity,
66305 $e->getFile(),
66306 $e->getLine(),
66307 $e->getPrevious()
66308 );
66309
66310 $this->setTrace($e->getTrace());
66311 }
66312 }
66313 <?php
66314
66315
66316
66317
66318
66319
66320
66321
66322
66323
66324 namespace Symfony\Component\HttpKernel\Exception;
66325
66326 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
66327
66328
66329
66330
66331
66332
66333
66334
66335
66336
66337 class FlattenException
66338 {
66339 private $handler;
66340
66341 public static function __callStatic($method, $args)
66342 {
66343 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
66344 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_called_class(), $method));
66345 }
66346
66347 return \call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
66348 }
66349
66350 public function __call($method, $args)
66351 {
66352 if (!isset($this->handler)) {
66353 $this->handler = new DebugFlattenException();
66354 }
66355
66356 if (!method_exists($this->handler, $method)) {
66357 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_class($this), $method));
66358 }
66359
66360 return \call_user_func_array(array($this->handler, $method), $args);
66361 }
66362 }
66363
66364 namespace Symfony\Component\Debug\Exception;
66365
66366 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
66367 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
66368
66369
66370
66371
66372
66373
66374
66375
66376 class FlattenException extends LegacyFlattenException
66377 {
66378 private $message;
66379 private $code;
66380 private $previous;
66381 private $trace;
66382 private $class;
66383 private $statusCode;
66384 private $headers;
66385 private $file;
66386 private $line;
66387
66388 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
66389 {
66390 $e = new static();
66391 $e->setMessage($exception->getMessage());
66392 $e->setCode($exception->getCode());
66393
66394 if ($exception instanceof HttpExceptionInterface) {
66395 $statusCode = $exception->getStatusCode();
66396 $headers = array_merge($headers, $exception->getHeaders());
66397 }
66398
66399 if (null === $statusCode) {
66400 $statusCode = 500;
66401 }
66402
66403 $e->setStatusCode($statusCode);
66404 $e->setHeaders($headers);
66405 $e->setTraceFromException($exception);
66406 $e->setClass(\get_class($exception));
66407 $e->setFile($exception->getFile());
66408 $e->setLine($exception->getLine());
66409
66410 $previous = $exception->getPrevious();
66411
66412 if ($previous instanceof \Exception) {
66413 $e->setPrevious(static::create($previous));
66414 } elseif ($previous instanceof \Throwable) {
66415 $e->setPrevious(static::create(new FatalThrowableError($previous)));
66416 }
66417
66418 return $e;
66419 }
66420
66421 public function toArray()
66422 {
66423 $exceptions = array();
66424 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
66425 $exceptions[] = array(
66426 'message' => $exception->getMessage(),
66427 'class' => $exception->getClass(),
66428 'trace' => $exception->getTrace(),
66429 );
66430 }
66431
66432 return $exceptions;
66433 }
66434
66435 public function getStatusCode()
66436 {
66437 return $this->statusCode;
66438 }
66439
66440 public function setStatusCode($code)
66441 {
66442 $this->statusCode = $code;
66443 }
66444
66445 public function getHeaders()
66446 {
66447 return $this->headers;
66448 }
66449
66450 public function setHeaders(array $headers)
66451 {
66452 $this->headers = $headers;
66453 }
66454
66455 public function getClass()
66456 {
66457 return $this->class;
66458 }
66459
66460 public function setClass($class)
66461 {
66462 $this->class = $class;
66463 }
66464
66465 public function getFile()
66466 {
66467 return $this->file;
66468 }
66469
66470 public function setFile($file)
66471 {
66472 $this->file = $file;
66473 }
66474
66475 public function getLine()
66476 {
66477 return $this->line;
66478 }
66479
66480 public function setLine($line)
66481 {
66482 $this->line = $line;
66483 }
66484
66485 public function getMessage()
66486 {
66487 return $this->message;
66488 }
66489
66490 public function setMessage($message)
66491 {
66492 $this->message = $message;
66493 }
66494
66495 public function getCode()
66496 {
66497 return $this->code;
66498 }
66499
66500 public function setCode($code)
66501 {
66502 $this->code = $code;
66503 }
66504
66505 public function getPrevious()
66506 {
66507 return $this->previous;
66508 }
66509
66510 public function setPrevious(FlattenException $previous)
66511 {
66512 $this->previous = $previous;
66513 }
66514
66515 public function getAllPrevious()
66516 {
66517 $exceptions = array();
66518 $e = $this;
66519 while ($e = $e->getPrevious()) {
66520 $exceptions[] = $e;
66521 }
66522
66523 return $exceptions;
66524 }
66525
66526 public function getTrace()
66527 {
66528 return $this->trace;
66529 }
66530
66531 public function setTraceFromException(\Exception $exception)
66532 {
66533 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
66534 }
66535
66536 public function setTrace($trace, $file, $line)
66537 {
66538 $this->trace = array();
66539 $this->trace[] = array(
66540 'namespace' => '',
66541 'short_class' => '',
66542 'class' => '',
66543 'type' => '',
66544 'function' => '',
66545 'file' => $file,
66546 'line' => $line,
66547 'args' => array(),
66548 );
66549 foreach ($trace as $entry) {
66550 $class = '';
66551 $namespace = '';
66552 if (isset($entry['class'])) {
66553 $parts = explode('\\', $entry['class']);
66554 $class = array_pop($parts);
66555 $namespace = implode('\\', $parts);
66556 }
66557
66558 $this->trace[] = array(
66559 'namespace' => $namespace,
66560 'short_class' => $class,
66561 'class' => isset($entry['class']) ? $entry['class'] : '',
66562 'type' => isset($entry['type']) ? $entry['type'] : '',
66563 'function' => isset($entry['function']) ? $entry['function'] : null,
66564 'file' => isset($entry['file']) ? $entry['file'] : null,
66565 'line' => isset($entry['line']) ? $entry['line'] : null,
66566 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
66567 );
66568 }
66569 }
66570
66571 private function flattenArgs($args, $level = 0, &$count = 0)
66572 {
66573 $result = array();
66574 foreach ($args as $key => $value) {
66575 if (++$count > 1e4) {
66576 return array('array', '*SKIPPED over 10000 entries*');
66577 }
66578 if ($value instanceof \__PHP_Incomplete_Class) {
66579
66580  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
66581 } elseif (\is_object($value)) {
66582 $result[$key] = array('object', \get_class($value));
66583 } elseif (\is_array($value)) {
66584 if ($level > 10) {
66585 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
66586 } else {
66587 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
66588 }
66589 } elseif (null === $value) {
66590 $result[$key] = array('null', null);
66591 } elseif (\is_bool($value)) {
66592 $result[$key] = array('boolean', $value);
66593 } elseif (\is_resource($value)) {
66594 $result[$key] = array('resource', get_resource_type($value));
66595 } else {
66596 $result[$key] = array('string', (string) $value);
66597 }
66598 }
66599
66600 return $result;
66601 }
66602
66603 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
66604 {
66605 $array = new \ArrayObject($value);
66606
66607 return $array['__PHP_Incomplete_Class_Name'];
66608 }
66609 }
66610 <?php
66611
66612
66613
66614
66615
66616
66617
66618
66619
66620
66621 namespace Symfony\Component\Debug\Exception;
66622
66623
66624
66625
66626
66627
66628 class OutOfMemoryException extends FatalErrorException
66629 {
66630 }
66631 <?php
66632
66633
66634
66635
66636
66637
66638
66639
66640
66641
66642 namespace Symfony\Component\Debug\Exception;
66643
66644
66645
66646
66647
66648
66649 class UndefinedFunctionException extends FatalErrorException
66650 {
66651 public function __construct($message, \ErrorException $previous)
66652 {
66653 parent::__construct(
66654 $message,
66655 $previous->getCode(),
66656 $previous->getSeverity(),
66657 $previous->getFile(),
66658 $previous->getLine(),
66659 null,
66660 true,
66661 null,
66662 $previous->getPrevious()
66663 );
66664 $this->setTrace($previous->getTrace());
66665 }
66666 }
66667 <?php
66668
66669
66670
66671
66672
66673
66674
66675
66676
66677
66678 namespace Symfony\Component\Debug\Exception;
66679
66680
66681
66682
66683
66684
66685 class UndefinedMethodException extends FatalErrorException
66686 {
66687 public function __construct($message, \ErrorException $previous)
66688 {
66689 parent::__construct(
66690 $message,
66691 $previous->getCode(),
66692 $previous->getSeverity(),
66693 $previous->getFile(),
66694 $previous->getLine(),
66695 null,
66696 true,
66697 null,
66698 $previous->getPrevious()
66699 );
66700 $this->setTrace($previous->getTrace());
66701 }
66702 }
66703 <?php
66704
66705
66706
66707
66708
66709
66710
66711
66712
66713
66714 namespace Symfony\Component\Debug;
66715
66716 use Symfony\Component\Debug\Exception\FlattenException;
66717 use Symfony\Component\Debug\Exception\OutOfMemoryException;
66718 use Symfony\Component\HttpFoundation\Response;
66719
66720
66721
66722
66723
66724
66725
66726
66727
66728
66729
66730
66731
66732 class ExceptionHandler
66733 {
66734 private $debug;
66735 private $charset;
66736 private $handler;
66737 private $caughtBuffer;
66738 private $caughtLength;
66739 private $fileLinkFormat;
66740
66741 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
66742 {
66743 if (false !== strpos($charset, '%')) {
66744 @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);
66745
66746
66747  $pivot = $fileLinkFormat;
66748 $fileLinkFormat = $charset;
66749 $charset = $pivot;
66750 }
66751 $this->debug = $debug;
66752 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
66753 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
66754 }
66755
66756
66757
66758
66759
66760
66761
66762
66763
66764
66765 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
66766 {
66767 $handler = new static($debug, $charset, $fileLinkFormat);
66768
66769 $prev = set_exception_handler(array($handler, 'handle'));
66770 if (\is_array($prev) && $prev[0] instanceof ErrorHandler) {
66771 restore_exception_handler();
66772 $prev[0]->setExceptionHandler(array($handler, 'handle'));
66773 }
66774
66775 return $handler;
66776 }
66777
66778
66779
66780
66781
66782
66783
66784
66785 public function setHandler($handler)
66786 {
66787 if (null !== $handler && !\is_callable($handler)) {
66788 throw new \LogicException('The exception handler must be a valid PHP callable.');
66789 }
66790 $old = $this->handler;
66791 $this->handler = $handler;
66792
66793 return $old;
66794 }
66795
66796
66797
66798
66799
66800
66801
66802
66803 public function setFileLinkFormat($format)
66804 {
66805 $old = $this->fileLinkFormat;
66806 $this->fileLinkFormat = $format;
66807
66808 return $old;
66809 }
66810
66811
66812
66813
66814
66815
66816
66817
66818
66819 public function handle(\Exception $exception)
66820 {
66821 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
66822 $this->failSafeHandle($exception);
66823
66824 return;
66825 }
66826
66827 $caughtLength = $this->caughtLength = 0;
66828
66829 ob_start(array($this, 'catchOutput'));
66830 $this->failSafeHandle($exception);
66831 while (null === $this->caughtBuffer && ob_end_flush()) {
66832
66833  }
66834 if (isset($this->caughtBuffer[0])) {
66835 ob_start(array($this, 'cleanOutput'));
66836 echo $this->caughtBuffer;
66837 $caughtLength = ob_get_length();
66838 }
66839 $this->caughtBuffer = null;
66840
66841 try {
66842 \call_user_func($this->handler, $exception);
66843 $this->caughtLength = $caughtLength;
66844 } catch (\Exception $e) {
66845 if (!$caughtLength) {
66846
66847  throw $exception;
66848 }
66849 }
66850 }
66851
66852
66853
66854
66855
66856
66857
66858
66859 private function failSafeHandle(\Exception $exception)
66860 {
66861 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
66862 && __CLASS__ !== \get_class($this)
66863 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
66864 && __CLASS__ !== $reflector->class
66865 ) {
66866 $response = $this->createResponse($exception);
66867 $response->sendHeaders();
66868 $response->sendContent();
66869 @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);
66870
66871 return;
66872 }
66873
66874 $this->sendPhpResponse($exception);
66875 }
66876
66877
66878
66879
66880
66881
66882
66883
66884
66885 public function sendPhpResponse($exception)
66886 {
66887 if (!$exception instanceof FlattenException) {
66888 $exception = FlattenException::create($exception);
66889 }
66890
66891 if (!headers_sent()) {
66892 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
66893 foreach ($exception->getHeaders() as $name => $value) {
66894 header($name.': '.$value, false);
66895 }
66896 header('Content-Type: text/html; charset='.$this->charset);
66897 }
66898
66899 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
66900 }
66901
66902
66903
66904
66905
66906
66907
66908
66909
66910
66911 public function createResponse($exception)
66912 {
66913 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66914
66915 if (!$exception instanceof FlattenException) {
66916 $exception = FlattenException::create($exception);
66917 }
66918
66919 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
66920 }
66921
66922
66923
66924
66925
66926
66927
66928
66929 public function getHtml($exception)
66930 {
66931 if (!$exception instanceof FlattenException) {
66932 $exception = FlattenException::create($exception);
66933 }
66934
66935 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
66936 }
66937
66938
66939
66940
66941
66942
66943 public function getContent(FlattenException $exception)
66944 {
66945 switch ($exception->getStatusCode()) {
66946 case 404:
66947 $title = 'Sorry, the page you are looking for could not be found.';
66948 break;
66949 default:
66950 $title = 'Whoops, looks like something went wrong.';
66951 }
66952
66953 $content = '';
66954 if ($this->debug) {
66955 try {
66956 $count = \count($exception->getAllPrevious());
66957 $total = $count + 1;
66958 foreach ($exception->toArray() as $position => $e) {
66959 $ind = $count - $position + 1;
66960 $class = $this->formatClass($e['class']);
66961 $message = nl2br($this->escapeHtml($e['message']));
66962 $content .= sprintf(<<<'EOF'
66963                         <h2 class="block_exception clear_fix">
66964                             <span class="exception_counter">%d/%d</span>
66965                             <span class="exception_title">%s%s:</span>
66966                             <span class="exception_message">%s</span>
66967                         </h2>
66968                         <div class="block">
66969                             <ol class="traces list_exception">
66970
66971 EOF
66972 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
66973 foreach ($e['trace'] as $trace) {
66974 $content .= '       <li>';
66975 if ($trace['function']) {
66976 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
66977 }
66978 if (isset($trace['file']) && isset($trace['line'])) {
66979 $content .= $this->formatPath($trace['file'], $trace['line']);
66980 }
66981 $content .= "</li>\n";
66982 }
66983
66984 $content .= "    </ol>\n</div>\n";
66985 }
66986 } catch (\Exception $e) {
66987
66988  if ($this->debug) {
66989 $title = sprintf('Exception thrown when handling an exception (%s: %s)', \get_class($e), $this->escapeHtml($e->getMessage()));
66990 } else {
66991 $title = 'Whoops, looks like something went wrong.';
66992 }
66993 }
66994 }
66995
66996 return <<<EOF
66997             <div id="sf-resetcontent" class="sf-reset">
66998                 <h1>$title</h1>
66999                 $content
67000             </div>
67001 EOF;
67002 }
67003
67004
67005
67006
67007
67008
67009 public function getStylesheet(FlattenException $exception)
67010 {
67011 return <<<'EOF'
67012             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
67013             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
67014             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
67015             .sf-reset .clear_fix { display:inline-block; }
67016             .sf-reset * html .clear_fix { height:1%; }
67017             .sf-reset .clear_fix { display:block; }
67018             .sf-reset, .sf-reset .block { margin: auto }
67019             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
67020             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
67021             .sf-reset strong { font-weight:bold; }
67022             .sf-reset a { color:#6c6159; cursor: default; }
67023             .sf-reset a img { border:none; }
67024             .sf-reset a:hover { text-decoration:underline; }
67025             .sf-reset em { font-style:italic; }
67026             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
67027             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
67028             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
67029             .sf-reset .exception_message { margin-left: 3em; display: block; }
67030             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
67031             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
67032                 -webkit-border-bottom-right-radius: 16px;
67033                 -webkit-border-bottom-left-radius: 16px;
67034                 -moz-border-radius-bottomright: 16px;
67035                 -moz-border-radius-bottomleft: 16px;
67036                 border-bottom-right-radius: 16px;
67037                 border-bottom-left-radius: 16px;
67038                 border-bottom:1px solid #ccc;
67039                 border-right:1px solid #ccc;
67040                 border-left:1px solid #ccc;
67041                 word-wrap: break-word;
67042             }
67043             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
67044                 -webkit-border-top-left-radius: 16px;
67045                 -webkit-border-top-right-radius: 16px;
67046                 -moz-border-radius-topleft: 16px;
67047                 -moz-border-radius-topright: 16px;
67048                 border-top-left-radius: 16px;
67049                 border-top-right-radius: 16px;
67050                 border-top:1px solid #ccc;
67051                 border-right:1px solid #ccc;
67052                 border-left:1px solid #ccc;
67053                 overflow: hidden;
67054                 word-wrap: break-word;
67055             }
67056             .sf-reset a { background:none; color:#868686; text-decoration:none; }
67057             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
67058             .sf-reset ol { padding: 10px 0; }
67059             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
67060                 -webkit-border-radius: 10px;
67061                 -moz-border-radius: 10px;
67062                 border-radius: 10px;
67063                 border: 1px solid #ccc;
67064             }
67065 EOF;
67066 }
67067
67068 private function decorate($content, $css)
67069 {
67070 return <<<EOF
67071 <!DOCTYPE html>
67072 <html>
67073     <head>
67074         <meta charset="{$this->charset}" />
67075         <meta name="robots" content="noindex,nofollow" />
67076         <style>
67077             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
67078             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;}
67079
67080             html { background: #eee; padding: 10px }
67081             img { border: 0; }
67082             #sf-resetcontent { width:970px; margin:0 auto; }
67083             $css
67084         </style>
67085     </head>
67086     <body>
67087         $content
67088     </body>
67089 </html>
67090 EOF;
67091 }
67092
67093 private function formatClass($class)
67094 {
67095 $parts = explode('\\', $class);
67096
67097 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
67098 }
67099
67100 private function formatPath($path, $line)
67101 {
67102 $path = $this->escapeHtml($path);
67103 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
67104
67105 if ($linkFormat = $this->fileLinkFormat) {
67106 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
67107
67108 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
67109 }
67110
67111 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);
67112 }
67113
67114
67115
67116
67117
67118
67119
67120
67121 private function formatArgs(array $args)
67122 {
67123 $result = array();
67124 foreach ($args as $key => $item) {
67125 if ('object' === $item[0]) {
67126 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
67127 } elseif ('array' === $item[0]) {
67128 $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
67129 } elseif ('string' === $item[0]) {
67130 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
67131 } elseif ('null' === $item[0]) {
67132 $formattedValue = '<em>null</em>';
67133 } elseif ('boolean' === $item[0]) {
67134 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
67135 } elseif ('resource' === $item[0]) {
67136 $formattedValue = '<em>resource</em>';
67137 } else {
67138 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
67139 }
67140
67141 $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
67142 }
67143
67144 return implode(', ', $result);
67145 }
67146
67147
67148
67149
67150
67151
67152 protected static function utf8Htmlize($str)
67153 {
67154 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
67155
67156 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
67157 }
67158
67159
67160
67161
67162 private function escapeHtml($str)
67163 {
67164 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
67165 }
67166
67167
67168
67169
67170 public function catchOutput($buffer)
67171 {
67172 $this->caughtBuffer = $buffer;
67173
67174 return '';
67175 }
67176
67177
67178
67179
67180 public function cleanOutput($buffer)
67181 {
67182 if ($this->caughtLength) {
67183
67184  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
67185 if (isset($cleanBuffer[0])) {
67186 $buffer = $cleanBuffer;
67187 }
67188 }
67189
67190 return $buffer;
67191 }
67192 }
67193 <?php
67194
67195
67196
67197
67198
67199
67200
67201
67202
67203
67204 namespace Symfony\Component\Debug\FatalErrorHandler;
67205
67206 use Composer\Autoload\ClassLoader as ComposerClassLoader;
67207 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
67208 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
67209 use Symfony\Component\Debug\DebugClassLoader;
67210 use Symfony\Component\Debug\Exception\ClassNotFoundException;
67211 use Symfony\Component\Debug\Exception\FatalErrorException;
67212
67213
67214
67215
67216
67217
67218 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
67219 {
67220
67221
67222
67223 public function handleError(array $error, FatalErrorException $exception)
67224 {
67225 $messageLen = \strlen($error['message']);
67226 $notFoundSuffix = '\' not found';
67227 $notFoundSuffixLen = \strlen($notFoundSuffix);
67228 if ($notFoundSuffixLen > $messageLen) {
67229 return;
67230 }
67231
67232 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
67233 return;
67234 }
67235
67236 foreach (array('class', 'interface', 'trait') as $typeName) {
67237 $prefix = ucfirst($typeName).' \'';
67238 $prefixLen = \strlen($prefix);
67239 if (0 !== strpos($error['message'], $prefix)) {
67240 continue;
67241 }
67242
67243 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
67244 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
67245 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
67246 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
67247 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
67248 $tail = ' for another namespace?';
67249 } else {
67250 $className = $fullyQualifiedClassName;
67251 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
67252 $tail = '?';
67253 }
67254
67255 if ($candidates = $this->getClassCandidates($className)) {
67256 $tail = array_pop($candidates).'"?';
67257 if ($candidates) {
67258 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
67259 } else {
67260 $tail = ' for "'.$tail;
67261 }
67262 }
67263 $message .= "\nDid you forget a \"use\" statement".$tail;
67264
67265 return new ClassNotFoundException($message, $exception);
67266 }
67267 }
67268
67269
67270
67271
67272
67273
67274
67275
67276
67277
67278
67279 private function getClassCandidates($class)
67280 {
67281 if (!\is_array($functions = spl_autoload_functions())) {
67282 return array();
67283 }
67284
67285
67286  $classes = array();
67287
67288 foreach ($functions as $function) {
67289 if (!\is_array($function)) {
67290 continue;
67291 }
67292
67293  if ($function[0] instanceof DebugClassLoader) {
67294 $function = $function[0]->getClassLoader();
67295
67296
67297  if (\is_object($function)) {
67298 $function = array($function);
67299 }
67300
67301 if (!\is_array($function)) {
67302 continue;
67303 }
67304 }
67305
67306 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
67307 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
67308 foreach ($paths as $path) {
67309 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
67310 }
67311 }
67312 }
67313 if ($function[0] instanceof ComposerClassLoader) {
67314 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
67315 foreach ($paths as $path) {
67316 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
67317 }
67318 }
67319 }
67320 }
67321
67322 return array_unique($classes);
67323 }
67324
67325
67326
67327
67328
67329
67330
67331
67332 private function findClassInPath($path, $class, $prefix)
67333 {
67334 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
67335 return array();
67336 }
67337
67338 $classes = array();
67339 $filename = $class.'.php';
67340 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
67341 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
67342 $classes[] = $class;
67343 }
67344 }
67345
67346 return $classes;
67347 }
67348
67349
67350
67351
67352
67353
67354
67355
67356 private function convertFileToClass($path, $file, $prefix)
67357 {
67358 $candidates = array(
67359
67360  $namespacedClass = str_replace(array($path.\DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
67361
67362  $prefix.$namespacedClass,
67363
67364  $prefix.'\\'.$namespacedClass,
67365
67366  str_replace('\\', '_', $namespacedClass),
67367
67368  str_replace('\\', '_', $prefix.$namespacedClass),
67369
67370  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
67371 );
67372
67373 if ($prefix) {
67374 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
67375 }
67376
67377
67378  
67379  
67380  foreach ($candidates as $candidate) {
67381 if ($this->classExists($candidate)) {
67382 return $candidate;
67383 }
67384 }
67385
67386 require_once $file;
67387
67388 foreach ($candidates as $candidate) {
67389 if ($this->classExists($candidate)) {
67390 return $candidate;
67391 }
67392 }
67393 }
67394
67395
67396
67397
67398
67399
67400 private function classExists($class)
67401 {
67402 return class_exists($class, false) || interface_exists($class, false) || (\function_exists('trait_exists') && trait_exists($class, false));
67403 }
67404 }
67405 <?php
67406
67407
67408
67409
67410
67411
67412
67413
67414
67415
67416 namespace Symfony\Component\Debug\FatalErrorHandler;
67417
67418 use Symfony\Component\Debug\Exception\FatalErrorException;
67419
67420
67421
67422
67423
67424
67425 interface FatalErrorHandlerInterface
67426 {
67427
67428
67429
67430
67431
67432
67433
67434
67435 public function handleError(array $error, FatalErrorException $exception);
67436 }
67437 <?php
67438
67439
67440
67441
67442
67443
67444
67445
67446
67447
67448 namespace Symfony\Component\Debug\FatalErrorHandler;
67449
67450 use Symfony\Component\Debug\Exception\FatalErrorException;
67451 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
67452
67453
67454
67455
67456
67457
67458 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
67459 {
67460
67461
67462
67463 public function handleError(array $error, FatalErrorException $exception)
67464 {
67465 $messageLen = \strlen($error['message']);
67466 $notFoundSuffix = '()';
67467 $notFoundSuffixLen = \strlen($notFoundSuffix);
67468 if ($notFoundSuffixLen > $messageLen) {
67469 return;
67470 }
67471
67472 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
67473 return;
67474 }
67475
67476 $prefix = 'Call to undefined function ';
67477 $prefixLen = \strlen($prefix);
67478 if (0 !== strpos($error['message'], $prefix)) {
67479 return;
67480 }
67481
67482 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
67483 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
67484 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
67485 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
67486 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
67487 } else {
67488 $functionName = $fullyQualifiedFunctionName;
67489 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
67490 }
67491
67492 $candidates = array();
67493 foreach (get_defined_functions() as $type => $definedFunctionNames) {
67494 foreach ($definedFunctionNames as $definedFunctionName) {
67495 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
67496 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
67497 } else {
67498 $definedFunctionNameBasename = $definedFunctionName;
67499 }
67500
67501 if ($definedFunctionNameBasename === $functionName) {
67502 $candidates[] = '\\'.$definedFunctionName;
67503 }
67504 }
67505 }
67506
67507 if ($candidates) {
67508 sort($candidates);
67509 $last = array_pop($candidates).'"?';
67510 if ($candidates) {
67511 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
67512 } else {
67513 $candidates = '"'.$last;
67514 }
67515 $message .= "\nDid you mean to call ".$candidates;
67516 }
67517
67518 return new UndefinedFunctionException($message, $exception);
67519 }
67520 }
67521 <?php
67522
67523
67524
67525
67526
67527
67528
67529
67530
67531
67532 namespace Symfony\Component\Debug\FatalErrorHandler;
67533
67534 use Symfony\Component\Debug\Exception\FatalErrorException;
67535 use Symfony\Component\Debug\Exception\UndefinedMethodException;
67536
67537
67538
67539
67540
67541
67542 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
67543 {
67544
67545
67546
67547 public function handleError(array $error, FatalErrorException $exception)
67548 {
67549 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
67550 if (!$matches) {
67551 return;
67552 }
67553
67554 $className = $matches[1];
67555 $methodName = $matches[2];
67556
67557 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
67558
67559 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
67560
67561  return new UndefinedMethodException($message, $exception);
67562 }
67563
67564 $candidates = array();
67565 foreach ($methods as $definedMethodName) {
67566 $lev = levenshtein($methodName, $definedMethodName);
67567 if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
67568 $candidates[] = $definedMethodName;
67569 }
67570 }
67571
67572 if ($candidates) {
67573 sort($candidates);
67574 $last = array_pop($candidates).'"?';
67575 if ($candidates) {
67576 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
67577 } else {
67578 $candidates = '"'.$last;
67579 }
67580
67581 $message .= "\nDid you mean to call ".$candidates;
67582 }
67583
67584 return new UndefinedMethodException($message, $exception);
67585 }
67586 }
67587 Copyright (c) 2004-2018 Fabien Potencier
67588
67589 Permission is hereby granted, free of charge, to any person obtaining a copy
67590 of this software and associated documentation files (the "Software"), to deal
67591 in the Software without restriction, including without limitation the rights
67592 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
67593 copies of the Software, and to permit persons to whom the Software is furnished
67594 to do so, subject to the following conditions:
67595
67596 The above copyright notice and this permission notice shall be included in all
67597 copies or substantial portions of the Software.
67598
67599 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
67600 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
67601 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
67602 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67603 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67604 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
67605 THE SOFTWARE.
67606 <?php
67607
67608
67609
67610
67611
67612
67613
67614
67615
67616
67617 namespace Symfony\Component\Filesystem\Exception;
67618
67619
67620
67621
67622
67623
67624 interface ExceptionInterface
67625 {
67626 }
67627 <?php
67628
67629
67630
67631
67632
67633
67634
67635
67636
67637
67638 namespace Symfony\Component\Filesystem\Exception;
67639
67640
67641
67642
67643
67644
67645
67646 class FileNotFoundException extends IOException
67647 {
67648 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
67649 {
67650 if (null === $message) {
67651 if (null === $path) {
67652 $message = 'File could not be found.';
67653 } else {
67654 $message = sprintf('File "%s" could not be found.', $path);
67655 }
67656 }
67657
67658 parent::__construct($message, $code, $previous, $path);
67659 }
67660 }
67661 <?php
67662
67663
67664
67665
67666
67667
67668
67669
67670
67671
67672 namespace Symfony\Component\Filesystem\Exception;
67673
67674
67675
67676
67677
67678
67679
67680
67681 class IOException extends \RuntimeException implements IOExceptionInterface
67682 {
67683 private $path;
67684
67685 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
67686 {
67687 $this->path = $path;
67688
67689 parent::__construct($message, $code, $previous);
67690 }
67691
67692
67693
67694
67695 public function getPath()
67696 {
67697 return $this->path;
67698 }
67699 }
67700 <?php
67701
67702
67703
67704
67705
67706
67707
67708
67709
67710
67711 namespace Symfony\Component\Filesystem\Exception;
67712
67713
67714
67715
67716
67717
67718 interface IOExceptionInterface extends ExceptionInterface
67719 {
67720
67721
67722
67723
67724
67725 public function getPath();
67726 }
67727 <?php
67728
67729
67730
67731
67732
67733
67734
67735
67736
67737
67738 namespace Symfony\Component\Filesystem;
67739
67740 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
67741 use Symfony\Component\Filesystem\Exception\IOException;
67742
67743
67744
67745
67746
67747
67748 class Filesystem
67749 {
67750 private static $lastError;
67751
67752
67753
67754
67755
67756
67757
67758
67759
67760
67761
67762
67763
67764
67765
67766 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
67767 {
67768 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
67769 if ($originIsLocal && !is_file($originFile)) {
67770 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
67771 }
67772
67773 $this->mkdir(\dirname($targetFile));
67774
67775 $doCopy = true;
67776 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
67777 $doCopy = filemtime($originFile) > filemtime($targetFile);
67778 }
67779
67780 if ($doCopy) {
67781
67782  if (false === $source = @fopen($originFile, 'r')) {
67783 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
67784 }
67785
67786
67787  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
67788 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
67789 }
67790
67791 $bytesCopied = stream_copy_to_stream($source, $target);
67792 fclose($source);
67793 fclose($target);
67794 unset($source, $target);
67795
67796 if (!is_file($targetFile)) {
67797 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
67798 }
67799
67800 if ($originIsLocal) {
67801
67802  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
67803
67804 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
67805 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);
67806 }
67807 }
67808 }
67809 }
67810
67811
67812
67813
67814
67815
67816
67817
67818
67819 public function mkdir($dirs, $mode = 0777)
67820 {
67821 foreach ($this->toIterator($dirs) as $dir) {
67822 if (is_dir($dir)) {
67823 continue;
67824 }
67825
67826 if (!self::box('mkdir', $dir, $mode, true)) {
67827 if (!is_dir($dir)) {
67828
67829  if (self::$lastError) {
67830 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
67831 }
67832 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
67833 }
67834 }
67835 }
67836 }
67837
67838
67839
67840
67841
67842
67843
67844
67845 public function exists($files)
67846 {
67847 $maxPathLength = PHP_MAXPATHLEN - 2;
67848
67849 foreach ($this->toIterator($files) as $file) {
67850 if (\strlen($file) > $maxPathLength) {
67851 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
67852 }
67853
67854 if (!file_exists($file)) {
67855 return false;
67856 }
67857 }
67858
67859 return true;
67860 }
67861
67862
67863
67864
67865
67866
67867
67868
67869
67870
67871 public function touch($files, $time = null, $atime = null)
67872 {
67873 foreach ($this->toIterator($files) as $file) {
67874 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
67875 if (true !== $touch) {
67876 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
67877 }
67878 }
67879 }
67880
67881
67882
67883
67884
67885
67886
67887
67888 public function remove($files)
67889 {
67890 if ($files instanceof \Traversable) {
67891 $files = iterator_to_array($files, false);
67892 } elseif (!\is_array($files)) {
67893 $files = array($files);
67894 }
67895 $files = array_reverse($files);
67896 foreach ($files as $file) {
67897 if (is_link($file)) {
67898
67899  if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
67900 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
67901 }
67902 } elseif (is_dir($file)) {
67903 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
67904
67905 if (!self::box('rmdir', $file) && file_exists($file)) {
67906 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
67907 }
67908 } elseif (!self::box('unlink', $file) && file_exists($file)) {
67909 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
67910 }
67911 }
67912 }
67913
67914
67915
67916
67917
67918
67919
67920
67921
67922
67923
67924 public function chmod($files, $mode, $umask = 0000, $recursive = false)
67925 {
67926 foreach ($this->toIterator($files) as $file) {
67927 if (true !== @chmod($file, $mode & ~$umask)) {
67928 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
67929 }
67930 if ($recursive && is_dir($file) && !is_link($file)) {
67931 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
67932 }
67933 }
67934 }
67935
67936
67937
67938
67939
67940
67941
67942
67943
67944
67945 public function chown($files, $user, $recursive = false)
67946 {
67947 foreach ($this->toIterator($files) as $file) {
67948 if ($recursive && is_dir($file) && !is_link($file)) {
67949 $this->chown(new \FilesystemIterator($file), $user, true);
67950 }
67951 if (is_link($file) && \function_exists('lchown')) {
67952 if (true !== @lchown($file, $user)) {
67953 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
67954 }
67955 } else {
67956 if (true !== @chown($file, $user)) {
67957 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
67958 }
67959 }
67960 }
67961 }
67962
67963
67964
67965
67966
67967
67968
67969
67970
67971
67972 public function chgrp($files, $group, $recursive = false)
67973 {
67974 foreach ($this->toIterator($files) as $file) {
67975 if ($recursive && is_dir($file) && !is_link($file)) {
67976 $this->chgrp(new \FilesystemIterator($file), $group, true);
67977 }
67978 if (is_link($file) && \function_exists('lchgrp')) {
67979 if (true !== @lchgrp($file, $group) || (\defined('HHVM_VERSION') && !posix_getgrnam($group))) {
67980 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
67981 }
67982 } else {
67983 if (true !== @chgrp($file, $group)) {
67984 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
67985 }
67986 }
67987 }
67988 }
67989
67990
67991
67992
67993
67994
67995
67996
67997
67998
67999
68000 public function rename($origin, $target, $overwrite = false)
68001 {
68002
68003  if (!$overwrite && $this->isReadable($target)) {
68004 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
68005 }
68006
68007 if (true !== @rename($origin, $target)) {
68008 if (is_dir($origin)) {
68009
68010  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
68011 $this->remove($origin);
68012
68013 return;
68014 }
68015 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
68016 }
68017 }
68018
68019
68020
68021
68022
68023
68024
68025
68026
68027
68028 private function isReadable($filename)
68029 {
68030 $maxPathLength = PHP_MAXPATHLEN - 2;
68031
68032 if (\strlen($filename) > $maxPathLength) {
68033 throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename);
68034 }
68035
68036 return is_readable($filename);
68037 }
68038
68039
68040
68041
68042
68043
68044
68045
68046
68047
68048 public function symlink($originDir, $targetDir, $copyOnWindows = false)
68049 {
68050 if ('\\' === \DIRECTORY_SEPARATOR) {
68051 $originDir = strtr($originDir, '/', '\\');
68052 $targetDir = strtr($targetDir, '/', '\\');
68053
68054 if ($copyOnWindows) {
68055 $this->mirror($originDir, $targetDir);
68056
68057 return;
68058 }
68059 }
68060
68061 $this->mkdir(\dirname($targetDir));
68062
68063 if (is_link($targetDir)) {
68064 if (readlink($targetDir) === $originDir) {
68065 return;
68066 }
68067 $this->remove($targetDir);
68068 }
68069
68070 if (!self::box('symlink', $originDir, $targetDir)) {
68071 if (null !== self::$lastError) {
68072 if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
68073 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);
68074 }
68075 }
68076 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
68077 }
68078 }
68079
68080
68081
68082
68083
68084
68085
68086
68087
68088 public function makePathRelative($endPath, $startPath)
68089 {
68090
68091  if ('\\' === \DIRECTORY_SEPARATOR) {
68092 $endPath = str_replace('\\', '/', $endPath);
68093 $startPath = str_replace('\\', '/', $startPath);
68094 }
68095
68096 $stripDriveLetter = function ($path) {
68097 if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) {
68098 return substr($path, 2);
68099 }
68100
68101 return $path;
68102 };
68103
68104 $endPath = $stripDriveLetter($endPath);
68105 $startPath = $stripDriveLetter($startPath);
68106
68107
68108  $startPathArr = explode('/', trim($startPath, '/'));
68109 $endPathArr = explode('/', trim($endPath, '/'));
68110
68111 $normalizePathArray = function ($pathSegments, $absolute) {
68112 $result = array();
68113
68114 foreach ($pathSegments as $segment) {
68115 if ('..' === $segment && ($absolute || \count($result))) {
68116 array_pop($result);
68117 } elseif ('.' !== $segment) {
68118 $result[] = $segment;
68119 }
68120 }
68121
68122 return $result;
68123 };
68124
68125 $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath));
68126 $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath));
68127
68128
68129  $index = 0;
68130 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
68131 ++$index;
68132 }
68133
68134
68135  if (1 === \count($startPathArr) && '' === $startPathArr[0]) {
68136 $depth = 0;
68137 } else {
68138 $depth = \count($startPathArr) - $index;
68139 }
68140
68141
68142  $traverser = str_repeat('../', $depth);
68143
68144 $endPathRemainder = implode('/', \array_slice($endPathArr, $index));
68145
68146
68147  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
68148
68149 return '' === $relativePath ? './' : $relativePath;
68150 }
68151
68152
68153
68154
68155
68156
68157
68158
68159
68160
68161
68162
68163
68164
68165
68166
68167
68168
68169
68170
68171 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
68172 {
68173 $targetDir = rtrim($targetDir, '/\\');
68174 $originDir = rtrim($originDir, '/\\');
68175 $originDirLen = \strlen($originDir);
68176
68177
68178  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
68179 $deleteIterator = $iterator;
68180 if (null === $deleteIterator) {
68181 $flags = \FilesystemIterator::SKIP_DOTS;
68182 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
68183 }
68184 $targetDirLen = \strlen($targetDir);
68185 foreach ($deleteIterator as $file) {
68186 $origin = $originDir.substr($file->getPathname(), $targetDirLen);
68187 if (!$this->exists($origin)) {
68188 $this->remove($file);
68189 }
68190 }
68191 }
68192
68193 $copyOnWindows = false;
68194 if (isset($options['copy_on_windows'])) {
68195 $copyOnWindows = $options['copy_on_windows'];
68196 }
68197
68198 if (null === $iterator) {
68199 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
68200 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
68201 }
68202
68203 if ($this->exists($originDir)) {
68204 $this->mkdir($targetDir);
68205 }
68206
68207 foreach ($iterator as $file) {
68208 $target = $targetDir.substr($file->getPathname(), $originDirLen);
68209
68210 if ($copyOnWindows) {
68211 if (is_file($file)) {
68212 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
68213 } elseif (is_dir($file)) {
68214 $this->mkdir($target);
68215 } else {
68216 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
68217 }
68218 } else {
68219 if (is_link($file)) {
68220 $this->symlink($file->getLinkTarget(), $target);
68221 } elseif (is_dir($file)) {
68222 $this->mkdir($target);
68223 } elseif (is_file($file)) {
68224 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
68225 } else {
68226 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
68227 }
68228 }
68229 }
68230 }
68231
68232
68233
68234
68235
68236
68237
68238
68239 public function isAbsolutePath($file)
68240 {
68241 return strspn($file, '/\\', 0, 1)
68242 || (\strlen($file) > 3 && ctype_alpha($file[0])
68243 && ':' === substr($file, 1, 1)
68244 && strspn($file, '/\\', 2, 1)
68245 )
68246 || null !== parse_url($file, PHP_URL_SCHEME)
68247 ;
68248 }
68249
68250
68251
68252
68253
68254
68255
68256
68257
68258
68259 public function tempnam($dir, $prefix)
68260 {
68261 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
68262
68263
68264  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
68265 $tmpFile = @tempnam($hierarchy, $prefix);
68266
68267
68268  if (false !== $tmpFile) {
68269 if (null !== $scheme && 'gs' !== $scheme) {
68270 return $scheme.'://'.$tmpFile;
68271 }
68272
68273 return $tmpFile;
68274 }
68275
68276 throw new IOException('A temporary file could not be created.');
68277 }
68278
68279
68280  for ($i = 0; $i < 10; ++$i) {
68281
68282  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
68283
68284
68285  
68286  $handle = @fopen($tmpFile, 'x+');
68287
68288
68289  if (false === $handle) {
68290 continue;
68291 }
68292
68293
68294  @fclose($handle);
68295
68296 return $tmpFile;
68297 }
68298
68299 throw new IOException('A temporary file could not be created.');
68300 }
68301
68302
68303
68304
68305
68306
68307
68308
68309
68310
68311
68312 public function dumpFile($filename, $content, $mode = 0666)
68313 {
68314 $dir = \dirname($filename);
68315
68316 if (!is_dir($dir)) {
68317 $this->mkdir($dir);
68318 }
68319
68320 if (!is_writable($dir)) {
68321 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
68322 }
68323
68324 $tmpFile = $this->tempnam($dir, basename($filename));
68325
68326 if (false === @file_put_contents($tmpFile, $content)) {
68327 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
68328 }
68329
68330 if (null !== $mode) {
68331 if (\func_num_args() > 2) {
68332 @trigger_error('Support for modifying file permissions is deprecated since Symfony 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
68333 }
68334
68335 $this->chmod($tmpFile, $mode);
68336 } elseif (file_exists($filename)) {
68337 @chmod($tmpFile, fileperms($filename));
68338 }
68339
68340 $this->rename($tmpFile, $filename, true);
68341 }
68342
68343
68344
68345
68346
68347
68348 private function toIterator($files)
68349 {
68350 if (!$files instanceof \Traversable) {
68351 $files = new \ArrayObject(\is_array($files) ? $files : array($files));
68352 }
68353
68354 return $files;
68355 }
68356
68357
68358
68359
68360
68361
68362
68363
68364 private function getSchemeAndHierarchy($filename)
68365 {
68366 $components = explode('://', $filename, 2);
68367
68368 return 2 === \count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
68369 }
68370
68371 private static function box($func)
68372 {
68373 self::$lastError = null;
68374 \set_error_handler(__CLASS__.'::handleError');
68375 try {
68376 $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
68377 \restore_error_handler();
68378
68379 return $result;
68380 } catch (\Throwable $e) {
68381 } catch (\Exception $e) {
68382 }
68383 \restore_error_handler();
68384
68385 throw $e;
68386 }
68387
68388
68389
68390
68391 public static function handleError($type, $msg)
68392 {
68393 self::$lastError = $msg;
68394 }
68395 }
68396 Copyright (c) 2004-2018 Fabien Potencier
68397
68398 Permission is hereby granted, free of charge, to any person obtaining a copy
68399 of this software and associated documentation files (the "Software"), to deal
68400 in the Software without restriction, including without limitation the rights
68401 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68402 copies of the Software, and to permit persons to whom the Software is furnished
68403 to do so, subject to the following conditions:
68404
68405 The above copyright notice and this permission notice shall be included in all
68406 copies or substantial portions of the Software.
68407
68408 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68409 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68410 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68411 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68412 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68413 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68414 THE SOFTWARE.
68415 <?php
68416
68417
68418
68419
68420
68421
68422
68423
68424
68425
68426 namespace Symfony\Component\Filesystem;
68427
68428 use Symfony\Component\Filesystem\Exception\IOException;
68429
68430
68431
68432
68433
68434
68435
68436
68437
68438
68439
68440
68441
68442
68443 class LockHandler
68444 {
68445 private $file;
68446 private $handle;
68447
68448
68449
68450
68451
68452
68453
68454 public function __construct($name, $lockPath = null)
68455 {
68456 $lockPath = $lockPath ?: sys_get_temp_dir();
68457
68458 if (!is_dir($lockPath)) {
68459 $fs = new Filesystem();
68460 $fs->mkdir($lockPath);
68461 }
68462
68463 if (!is_writable($lockPath)) {
68464 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
68465 }
68466
68467 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
68468 }
68469
68470
68471
68472
68473
68474
68475
68476
68477
68478
68479 public function lock($blocking = false)
68480 {
68481 if ($this->handle) {
68482 return true;
68483 }
68484
68485 $error = null;
68486
68487
68488  set_error_handler(function ($errno, $msg) use (&$error) {
68489 $error = $msg;
68490 });
68491
68492 if (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
68493 if ($this->handle = fopen($this->file, 'x')) {
68494 chmod($this->file, 0666);
68495 } elseif (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) {
68496 usleep(100); 
68497  $this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r');
68498 }
68499 }
68500 restore_error_handler();
68501
68502 if (!$this->handle) {
68503 throw new IOException($error, 0, null, $this->file);
68504 }
68505
68506
68507  
68508  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
68509 fclose($this->handle);
68510 $this->handle = null;
68511
68512 return false;
68513 }
68514
68515 return true;
68516 }
68517
68518
68519
68520
68521 public function release()
68522 {
68523 if ($this->handle) {
68524 flock($this->handle, LOCK_UN | LOCK_NB);
68525 fclose($this->handle);
68526 $this->handle = null;
68527 }
68528 }
68529 }
68530 <?php
68531
68532
68533
68534
68535
68536
68537
68538
68539
68540
68541 namespace Symfony\Component\Finder\Adapter;
68542
68543 @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);
68544
68545
68546
68547
68548
68549
68550
68551
68552 abstract class AbstractAdapter implements AdapterInterface
68553 {
68554 protected $followLinks = false;
68555 protected $mode = 0;
68556 protected $minDepth = 0;
68557 protected $maxDepth = PHP_INT_MAX;
68558 protected $exclude = array();
68559 protected $names = array();
68560 protected $notNames = array();
68561 protected $contains = array();
68562 protected $notContains = array();
68563 protected $sizes = array();
68564 protected $dates = array();
68565 protected $filters = array();
68566 protected $sort = false;
68567 protected $paths = array();
68568 protected $notPaths = array();
68569 protected $ignoreUnreadableDirs = false;
68570
68571 private static $areSupported = array();
68572
68573
68574
68575
68576 public function isSupported()
68577 {
68578 $name = $this->getName();
68579
68580 if (!array_key_exists($name, self::$areSupported)) {
68581 self::$areSupported[$name] = $this->canBeUsed();
68582 }
68583
68584 return self::$areSupported[$name];
68585 }
68586
68587
68588
68589
68590 public function setFollowLinks($followLinks)
68591 {
68592 $this->followLinks = $followLinks;
68593
68594 return $this;
68595 }
68596
68597
68598
68599
68600 public function setMode($mode)
68601 {
68602 $this->mode = $mode;
68603
68604 return $this;
68605 }
68606
68607
68608
68609
68610 public function setDepths(array $depths)
68611 {
68612 $this->minDepth = 0;
68613 $this->maxDepth = PHP_INT_MAX;
68614
68615 foreach ($depths as $comparator) {
68616 switch ($comparator->getOperator()) {
68617 case '>':
68618 $this->minDepth = $comparator->getTarget() + 1;
68619 break;
68620 case '>=':
68621 $this->minDepth = $comparator->getTarget();
68622 break;
68623 case '<':
68624 $this->maxDepth = $comparator->getTarget() - 1;
68625 break;
68626 case '<=':
68627 $this->maxDepth = $comparator->getTarget();
68628 break;
68629 default:
68630 $this->minDepth = $this->maxDepth = $comparator->getTarget();
68631 }
68632 }
68633
68634 return $this;
68635 }
68636
68637
68638
68639
68640 public function setExclude(array $exclude)
68641 {
68642 $this->exclude = $exclude;
68643
68644 return $this;
68645 }
68646
68647
68648
68649
68650 public function setNames(array $names)
68651 {
68652 $this->names = $names;
68653
68654 return $this;
68655 }
68656
68657
68658
68659
68660 public function setNotNames(array $notNames)
68661 {
68662 $this->notNames = $notNames;
68663
68664 return $this;
68665 }
68666
68667
68668
68669
68670 public function setContains(array $contains)
68671 {
68672 $this->contains = $contains;
68673
68674 return $this;
68675 }
68676
68677
68678
68679
68680 public function setNotContains(array $notContains)
68681 {
68682 $this->notContains = $notContains;
68683
68684 return $this;
68685 }
68686
68687
68688
68689
68690 public function setSizes(array $sizes)
68691 {
68692 $this->sizes = $sizes;
68693
68694 return $this;
68695 }
68696
68697
68698
68699
68700 public function setDates(array $dates)
68701 {
68702 $this->dates = $dates;
68703
68704 return $this;
68705 }
68706
68707
68708
68709
68710 public function setFilters(array $filters)
68711 {
68712 $this->filters = $filters;
68713
68714 return $this;
68715 }
68716
68717
68718
68719
68720 public function setSort($sort)
68721 {
68722 $this->sort = $sort;
68723
68724 return $this;
68725 }
68726
68727
68728
68729
68730 public function setPath(array $paths)
68731 {
68732 $this->paths = $paths;
68733
68734 return $this;
68735 }
68736
68737
68738
68739
68740 public function setNotPath(array $notPaths)
68741 {
68742 $this->notPaths = $notPaths;
68743
68744 return $this;
68745 }
68746
68747
68748
68749
68750 public function ignoreUnreadableDirs($ignore = true)
68751 {
68752 $this->ignoreUnreadableDirs = (bool) $ignore;
68753
68754 return $this;
68755 }
68756
68757
68758
68759
68760
68761
68762
68763
68764
68765
68766
68767
68768 abstract protected function canBeUsed();
68769 }
68770 <?php
68771
68772
68773
68774
68775
68776
68777
68778
68779
68780
68781 namespace Symfony\Component\Finder\Adapter;
68782
68783 @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);
68784
68785 use Symfony\Component\Finder\Comparator\DateComparator;
68786 use Symfony\Component\Finder\Comparator\NumberComparator;
68787 use Symfony\Component\Finder\Exception\AccessDeniedException;
68788 use Symfony\Component\Finder\Expression\Expression;
68789 use Symfony\Component\Finder\Iterator;
68790 use Symfony\Component\Finder\Shell\Command;
68791 use Symfony\Component\Finder\Shell\Shell;
68792
68793
68794
68795
68796
68797
68798
68799
68800 abstract class AbstractFindAdapter extends AbstractAdapter
68801 {
68802 protected $shell;
68803
68804 public function __construct()
68805 {
68806 $this->shell = new Shell();
68807 }
68808
68809
68810
68811
68812 public function searchInDirectory($dir)
68813 {
68814
68815  $dir = realpath($dir);
68816
68817
68818  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
68819 return new Iterator\FilePathsIterator(array(), $dir);
68820 }
68821
68822 $command = Command::create();
68823 $find = $this->buildFindCommand($command, $dir);
68824
68825 if ($this->followLinks) {
68826 $find->add('-follow');
68827 }
68828
68829 $find->add('-mindepth')->add($this->minDepth + 1);
68830
68831 if (PHP_INT_MAX !== $this->maxDepth) {
68832 $find->add('-maxdepth')->add($this->maxDepth + 1);
68833 }
68834
68835 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
68836 $find->add('-type d');
68837 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
68838 $find->add('-type f');
68839 }
68840
68841 $this->buildNamesFiltering($find, $this->names);
68842 $this->buildNamesFiltering($find, $this->notNames, true);
68843 $this->buildPathsFiltering($find, $dir, $this->paths);
68844 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
68845 $this->buildSizesFiltering($find, $this->sizes);
68846 $this->buildDatesFiltering($find, $this->dates);
68847
68848 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
68849 $useSort = \is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
68850
68851 if ($useGrep && ($this->contains || $this->notContains)) {
68852 $grep = $command->ins('grep');
68853 $this->buildContentFiltering($grep, $this->contains);
68854 $this->buildContentFiltering($grep, $this->notContains, true);
68855 }
68856
68857 if ($useSort) {
68858 $this->buildSorting($command, $this->sort);
68859 }
68860
68861 $command->setErrorHandler(
68862 $this->ignoreUnreadableDirs
68863
68864  ? function ($stderr) { }
68865 : function ($stderr) { throw new AccessDeniedException($stderr); }
68866 );
68867
68868 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
68869 $iterator = new Iterator\FilePathsIterator($paths, $dir);
68870
68871 if ($this->exclude) {
68872 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
68873 }
68874
68875 if (!$useGrep && ($this->contains || $this->notContains)) {
68876 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
68877 }
68878
68879 if ($this->filters) {
68880 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
68881 }
68882
68883 if (!$useSort && $this->sort) {
68884 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
68885 $iterator = $iteratorAggregate->getIterator();
68886 }
68887
68888 return $iterator;
68889 }
68890
68891
68892
68893
68894 protected function canBeUsed()
68895 {
68896 return $this->shell->testCommand('find');
68897 }
68898
68899
68900
68901
68902
68903
68904
68905 protected function buildFindCommand(Command $command, $dir)
68906 {
68907 return $command
68908 ->ins('find')
68909 ->add('find ')
68910 ->arg($dir)
68911 ->add('-noleaf'); 
68912  }
68913
68914
68915
68916
68917
68918
68919 private function buildNamesFiltering(Command $command, array $names, $not = false)
68920 {
68921 if (0 === \count($names)) {
68922 return;
68923 }
68924
68925 $command->add($not ? '-not' : null)->cmd('(');
68926
68927 foreach ($names as $i => $name) {
68928 $expr = Expression::create($name);
68929
68930
68931  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
68932 $expr = Expression::create($expr->getGlob()->toRegex(false));
68933 }
68934
68935
68936  
68937  
68938  if ($expr->isRegex()) {
68939 $regex = $expr->getRegex();
68940 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
68941 ->setStartFlag(false)
68942 ->setStartJoker(true)
68943 ->replaceJokers('[^/]');
68944 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
68945 $regex->setEndJoker(false)->append('[^/]*');
68946 }
68947 }
68948
68949 $command
68950 ->add($i > 0 ? '-or' : null)
68951 ->add($expr->isRegex()
68952 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
68953 : ($expr->isCaseSensitive() ? '-name' : '-iname')
68954 )
68955 ->arg($expr->renderPattern());
68956 }
68957
68958 $command->cmd(')');
68959 }
68960
68961
68962
68963
68964
68965
68966
68967 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
68968 {
68969 if (0 === \count($paths)) {
68970 return;
68971 }
68972
68973 $command->add($not ? '-not' : null)->cmd('(');
68974
68975 foreach ($paths as $i => $path) {
68976 $expr = Expression::create($path);
68977
68978
68979  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
68980 $expr = Expression::create($expr->getGlob()->toRegex(false));
68981 }
68982
68983
68984  if ($expr->isRegex()) {
68985 $regex = $expr->getRegex();
68986 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).\DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
68987 } else {
68988 $expr->prepend('*')->append('*');
68989 }
68990
68991 $command
68992 ->add($i > 0 ? '-or' : null)
68993 ->add($expr->isRegex()
68994 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
68995 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
68996 )
68997 ->arg($expr->renderPattern());
68998 }
68999
69000 $command->cmd(')');
69001 }
69002
69003
69004
69005
69006
69007 private function buildSizesFiltering(Command $command, array $sizes)
69008 {
69009 foreach ($sizes as $i => $size) {
69010 $command->add($i > 0 ? '-and' : null);
69011
69012 switch ($size->getOperator()) {
69013 case '<=':
69014 $command->add('-size -'.($size->getTarget() + 1).'c');
69015 break;
69016 case '>=':
69017 $command->add('-size +'.($size->getTarget() - 1).'c');
69018 break;
69019 case '>':
69020 $command->add('-size +'.$size->getTarget().'c');
69021 break;
69022 case '!=':
69023 $command->add('-size -'.$size->getTarget().'c');
69024 $command->add('-size +'.$size->getTarget().'c');
69025 break;
69026 case '<':
69027 default:
69028 $command->add('-size -'.$size->getTarget().'c');
69029 }
69030 }
69031 }
69032
69033
69034
69035
69036
69037 private function buildDatesFiltering(Command $command, array $dates)
69038 {
69039 foreach ($dates as $i => $date) {
69040 $command->add($i > 0 ? '-and' : null);
69041
69042 $mins = (int) round((time() - $date->getTarget()) / 60);
69043
69044 if (0 > $mins) {
69045
69046  $command->add(' -mmin -0');
69047
69048  return;
69049 }
69050
69051 switch ($date->getOperator()) {
69052 case '<=':
69053 $command->add('-mmin +'.($mins - 1));
69054 break;
69055 case '>=':
69056 $command->add('-mmin -'.($mins + 1));
69057 break;
69058 case '>':
69059 $command->add('-mmin -'.$mins);
69060 break;
69061 case '!=':
69062 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
69063 break;
69064 case '<':
69065 default:
69066 $command->add('-mmin +'.$mins);
69067 }
69068 }
69069 }
69070
69071
69072
69073
69074
69075
69076
69077 private function buildSorting(Command $command, $sort)
69078 {
69079 $this->buildFormatSorting($command, $sort);
69080 }
69081
69082
69083
69084
69085
69086 abstract protected function buildFormatSorting(Command $command, $sort);
69087
69088
69089
69090
69091
69092
69093 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
69094 }
69095 <?php
69096
69097
69098
69099
69100
69101
69102
69103
69104
69105
69106 namespace Symfony\Component\Finder\Adapter;
69107
69108
69109
69110
69111
69112
69113 interface AdapterInterface
69114 {
69115
69116
69117
69118
69119
69120 public function setFollowLinks($followLinks);
69121
69122
69123
69124
69125
69126
69127 public function setMode($mode);
69128
69129
69130
69131
69132 public function setExclude(array $exclude);
69133
69134
69135
69136
69137 public function setDepths(array $depths);
69138
69139
69140
69141
69142 public function setNames(array $names);
69143
69144
69145
69146
69147 public function setNotNames(array $notNames);
69148
69149
69150
69151
69152 public function setContains(array $contains);
69153
69154
69155
69156
69157 public function setNotContains(array $notContains);
69158
69159
69160
69161
69162 public function setSizes(array $sizes);
69163
69164
69165
69166
69167 public function setDates(array $dates);
69168
69169
69170
69171
69172 public function setFilters(array $filters);
69173
69174
69175
69176
69177
69178
69179 public function setSort($sort);
69180
69181
69182
69183
69184 public function setPath(array $paths);
69185
69186
69187
69188
69189 public function setNotPath(array $notPaths);
69190
69191
69192
69193
69194
69195
69196 public function ignoreUnreadableDirs($ignore = true);
69197
69198
69199
69200
69201
69202
69203 public function searchInDirectory($dir);
69204
69205
69206
69207
69208
69209
69210 public function isSupported();
69211
69212
69213
69214
69215
69216
69217 public function getName();
69218 }
69219 <?php
69220
69221
69222
69223
69224
69225
69226
69227
69228
69229
69230 namespace Symfony\Component\Finder\Adapter;
69231
69232 @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);
69233
69234 use Symfony\Component\Finder\Expression\Expression;
69235 use Symfony\Component\Finder\Iterator\SortableIterator;
69236 use Symfony\Component\Finder\Shell\Command;
69237 use Symfony\Component\Finder\Shell\Shell;
69238
69239
69240
69241
69242
69243
69244
69245
69246 class BsdFindAdapter extends AbstractFindAdapter
69247 {
69248
69249
69250
69251 public function getName()
69252 {
69253 return 'bsd_find';
69254 }
69255
69256
69257
69258
69259 protected function canBeUsed()
69260 {
69261 return \in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
69262 }
69263
69264
69265
69266
69267 protected function buildFormatSorting(Command $command, $sort)
69268 {
69269 switch ($sort) {
69270 case SortableIterator::SORT_BY_NAME:
69271 $command->ins('sort')->add('| sort');
69272
69273 return;
69274 case SortableIterator::SORT_BY_TYPE:
69275 $format = '%HT';
69276 break;
69277 case SortableIterator::SORT_BY_ACCESSED_TIME:
69278 $format = '%a';
69279 break;
69280 case SortableIterator::SORT_BY_CHANGED_TIME:
69281 $format = '%c';
69282 break;
69283 case SortableIterator::SORT_BY_MODIFIED_TIME:
69284 $format = '%m';
69285 break;
69286 default:
69287 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
69288 }
69289
69290 $command
69291 ->add('-print0 | xargs -0 stat -f')
69292 ->arg($format.'%t%N')
69293 ->add('| sort | cut -f 2');
69294 }
69295
69296
69297
69298
69299 protected function buildFindCommand(Command $command, $dir)
69300 {
69301 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
69302
69303 return $command;
69304 }
69305
69306
69307
69308
69309 protected function buildContentFiltering(Command $command, array $contains, $not = false)
69310 {
69311 foreach ($contains as $contain) {
69312 $expr = Expression::create($contain);
69313
69314
69315  $command
69316 ->add('| grep -v \'^$\'')
69317 ->add('| xargs -I{} grep -I')
69318 ->add($expr->isCaseSensitive() ? null : '-i')
69319 ->add($not ? '-L' : '-l')
69320 ->add('-Ee')->arg($expr->renderPattern())
69321 ->add('{}')
69322 ;
69323 }
69324 }
69325 }
69326 <?php
69327
69328
69329
69330
69331
69332
69333
69334
69335
69336
69337 namespace Symfony\Component\Finder\Adapter;
69338
69339 @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);
69340
69341 use Symfony\Component\Finder\Expression\Expression;
69342 use Symfony\Component\Finder\Iterator\SortableIterator;
69343 use Symfony\Component\Finder\Shell\Command;
69344 use Symfony\Component\Finder\Shell\Shell;
69345
69346
69347
69348
69349
69350
69351
69352
69353 class GnuFindAdapter extends AbstractFindAdapter
69354 {
69355
69356
69357
69358 public function getName()
69359 {
69360 return 'gnu_find';
69361 }
69362
69363
69364
69365
69366 protected function buildFormatSorting(Command $command, $sort)
69367 {
69368 switch ($sort) {
69369 case SortableIterator::SORT_BY_NAME:
69370 $command->ins('sort')->add('| sort');
69371
69372 return;
69373 case SortableIterator::SORT_BY_TYPE:
69374 $format = '%y';
69375 break;
69376 case SortableIterator::SORT_BY_ACCESSED_TIME:
69377 $format = '%A@';
69378 break;
69379 case SortableIterator::SORT_BY_CHANGED_TIME:
69380 $format = '%C@';
69381 break;
69382 case SortableIterator::SORT_BY_MODIFIED_TIME:
69383 $format = '%T@';
69384 break;
69385 default:
69386 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
69387 }
69388
69389 $command
69390 ->get('find')
69391 ->add('-printf')
69392 ->arg($format.' %h/%f\\n')
69393 ->add('| sort | cut')
69394 ->arg('-d ')
69395 ->arg('-f2-')
69396 ;
69397 }
69398
69399
69400
69401
69402 protected function canBeUsed()
69403 {
69404 return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
69405 }
69406
69407
69408
69409
69410 protected function buildFindCommand(Command $command, $dir)
69411 {
69412 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
69413 }
69414
69415
69416
69417
69418 protected function buildContentFiltering(Command $command, array $contains, $not = false)
69419 {
69420 foreach ($contains as $contain) {
69421 $expr = Expression::create($contain);
69422
69423
69424  $command
69425 ->add('| xargs -I{} -r grep -I')
69426 ->add($expr->isCaseSensitive() ? null : '-i')
69427 ->add($not ? '-L' : '-l')
69428 ->add('-Ee')->arg($expr->renderPattern())
69429 ->add('{}')
69430 ;
69431 }
69432 }
69433 }
69434 <?php
69435
69436
69437
69438
69439
69440
69441
69442
69443
69444
69445 namespace Symfony\Component\Finder\Adapter;
69446
69447 @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);
69448
69449 use Symfony\Component\Finder\Iterator;
69450
69451
69452
69453
69454
69455
69456
69457
69458 class PhpAdapter extends AbstractAdapter
69459 {
69460
69461
69462
69463 public function searchInDirectory($dir)
69464 {
69465 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
69466
69467 if ($this->followLinks) {
69468 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
69469 }
69470
69471 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
69472
69473 if ($this->exclude) {
69474 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
69475 }
69476
69477 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
69478
69479 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
69480 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
69481 }
69482
69483 if ($this->mode) {
69484 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
69485 }
69486
69487 if ($this->names || $this->notNames) {
69488 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
69489 }
69490
69491 if ($this->contains || $this->notContains) {
69492 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
69493 }
69494
69495 if ($this->sizes) {
69496 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
69497 }
69498
69499 if ($this->dates) {
69500 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
69501 }
69502
69503 if ($this->filters) {
69504 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
69505 }
69506
69507 if ($this->paths || $this->notPaths) {
69508 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
69509 }
69510
69511 if ($this->sort) {
69512 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
69513 $iterator = $iteratorAggregate->getIterator();
69514 }
69515
69516 return $iterator;
69517 }
69518
69519
69520
69521
69522 public function getName()
69523 {
69524 return 'php';
69525 }
69526
69527
69528
69529
69530 protected function canBeUsed()
69531 {
69532 return true;
69533 }
69534 }
69535 <?php
69536
69537
69538
69539
69540
69541
69542
69543
69544
69545
69546 namespace Symfony\Component\Finder\Comparator;
69547
69548
69549
69550
69551
69552
69553 class Comparator
69554 {
69555 private $target;
69556 private $operator = '==';
69557
69558
69559
69560
69561
69562
69563 public function getTarget()
69564 {
69565 return $this->target;
69566 }
69567
69568
69569
69570
69571
69572
69573 public function setTarget($target)
69574 {
69575 $this->target = $target;
69576 }
69577
69578
69579
69580
69581
69582
69583 public function getOperator()
69584 {
69585 return $this->operator;
69586 }
69587
69588
69589
69590
69591
69592
69593
69594
69595 public function setOperator($operator)
69596 {
69597 if (!$operator) {
69598 $operator = '==';
69599 }
69600
69601 if (!\in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
69602 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
69603 }
69604
69605 $this->operator = $operator;
69606 }
69607
69608
69609
69610
69611
69612
69613
69614
69615 public function test($test)
69616 {
69617 switch ($this->operator) {
69618 case '>':
69619 return $test > $this->target;
69620 case '>=':
69621 return $test >= $this->target;
69622 case '<':
69623 return $test < $this->target;
69624 case '<=':
69625 return $test <= $this->target;
69626 case '!=':
69627 return $test != $this->target;
69628 }
69629
69630 return $test == $this->target;
69631 }
69632 }
69633 <?php
69634
69635
69636
69637
69638
69639
69640
69641
69642
69643
69644 namespace Symfony\Component\Finder\Comparator;
69645
69646
69647
69648
69649
69650
69651 class DateComparator extends Comparator
69652 {
69653
69654
69655
69656
69657
69658 public function __construct($test)
69659 {
69660 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
69661 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
69662 }
69663
69664 try {
69665 $date = new \DateTime($matches[2]);
69666 $target = $date->format('U');
69667 } catch (\Exception $e) {
69668 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
69669 }
69670
69671 $operator = isset($matches[1]) ? $matches[1] : '==';
69672 if ('since' === $operator || 'after' === $operator) {
69673 $operator = '>';
69674 }
69675
69676 if ('until' === $operator || 'before' === $operator) {
69677 $operator = '<';
69678 }
69679
69680 $this->setOperator($operator);
69681 $this->setTarget($target);
69682 }
69683 }
69684 <?php
69685
69686
69687
69688
69689
69690
69691
69692
69693
69694
69695 namespace Symfony\Component\Finder\Comparator;
69696
69697
69698
69699
69700
69701
69702
69703
69704
69705
69706
69707
69708
69709
69710
69711
69712
69713
69714
69715
69716
69717
69718 class NumberComparator extends Comparator
69719 {
69720
69721
69722
69723
69724
69725 public function __construct($test)
69726 {
69727 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
69728 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
69729 }
69730
69731 $target = $matches[2];
69732 if (!is_numeric($target)) {
69733 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
69734 }
69735 if (isset($matches[3])) {
69736
69737  switch (strtolower($matches[3])) {
69738 case 'k':
69739 $target *= 1000;
69740 break;
69741 case 'ki':
69742 $target *= 1024;
69743 break;
69744 case 'm':
69745 $target *= 1000000;
69746 break;
69747 case 'mi':
69748 $target *= 1024 * 1024;
69749 break;
69750 case 'g':
69751 $target *= 1000000000;
69752 break;
69753 case 'gi':
69754 $target *= 1024 * 1024 * 1024;
69755 break;
69756 }
69757 }
69758
69759 $this->setTarget($target);
69760 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
69761 }
69762 }
69763 <?php
69764
69765
69766
69767
69768
69769
69770
69771
69772
69773
69774 namespace Symfony\Component\Finder\Exception;
69775
69776
69777
69778
69779 class AccessDeniedException extends \UnexpectedValueException
69780 {
69781 }
69782 <?php
69783
69784
69785
69786
69787
69788
69789
69790
69791
69792
69793 namespace Symfony\Component\Finder\Exception;
69794
69795 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69796
69797 use Symfony\Component\Finder\Adapter\AdapterInterface;
69798
69799
69800
69801
69802
69803
69804
69805
69806 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
69807 {
69808 private $adapter;
69809
69810
69811
69812
69813
69814
69815 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
69816 {
69817 $this->adapter = $adapter;
69818 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
69819 }
69820
69821
69822
69823
69824 public function getAdapter()
69825 {
69826 return $this->adapter;
69827 }
69828 }
69829 <?php
69830
69831
69832
69833
69834
69835
69836
69837
69838
69839
69840 namespace Symfony\Component\Finder\Exception;
69841
69842
69843
69844
69845 interface ExceptionInterface
69846 {
69847
69848
69849
69850 public function getAdapter();
69851 }
69852 <?php
69853
69854
69855
69856
69857
69858
69859
69860
69861
69862
69863 namespace Symfony\Component\Finder\Exception;
69864
69865 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69866
69867
69868
69869
69870
69871
69872 class OperationNotPermitedException extends AdapterFailureException
69873 {
69874 }
69875 <?php
69876
69877
69878
69879
69880
69881
69882
69883
69884
69885
69886 namespace Symfony\Component\Finder\Exception;
69887
69888 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69889
69890 use Symfony\Component\Finder\Adapter\AdapterInterface;
69891 use Symfony\Component\Finder\Shell\Command;
69892
69893
69894
69895
69896
69897
69898 class ShellCommandFailureException extends AdapterFailureException
69899 {
69900 private $command;
69901
69902 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
69903 {
69904 $this->command = $command;
69905 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
69906 }
69907
69908
69909
69910
69911 public function getCommand()
69912 {
69913 return $this->command;
69914 }
69915 }
69916 <?php
69917
69918
69919
69920
69921
69922
69923
69924
69925
69926
69927 namespace Symfony\Component\Finder\Expression;
69928
69929 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
69930
69931
69932
69933
69934 class Expression implements ValueInterface
69935 {
69936 const TYPE_REGEX = 1;
69937 const TYPE_GLOB = 2;
69938
69939
69940
69941
69942 private $value;
69943
69944
69945
69946
69947
69948
69949 public static function create($expr)
69950 {
69951 return new self($expr);
69952 }
69953
69954
69955
69956
69957 public function __construct($expr)
69958 {
69959 try {
69960 $this->value = Regex::create($expr);
69961 } catch (\InvalidArgumentException $e) {
69962 $this->value = new Glob($expr);
69963 }
69964 }
69965
69966
69967
69968
69969 public function __toString()
69970 {
69971 return $this->render();
69972 }
69973
69974
69975
69976
69977 public function render()
69978 {
69979 return $this->value->render();
69980 }
69981
69982
69983
69984
69985 public function renderPattern()
69986 {
69987 return $this->value->renderPattern();
69988 }
69989
69990
69991
69992
69993 public function isCaseSensitive()
69994 {
69995 return $this->value->isCaseSensitive();
69996 }
69997
69998
69999
70000
70001 public function getType()
70002 {
70003 return $this->value->getType();
70004 }
70005
70006
70007
70008
70009 public function prepend($expr)
70010 {
70011 $this->value->prepend($expr);
70012
70013 return $this;
70014 }
70015
70016
70017
70018
70019 public function append($expr)
70020 {
70021 $this->value->append($expr);
70022
70023 return $this;
70024 }
70025
70026
70027
70028
70029 public function isRegex()
70030 {
70031 return self::TYPE_REGEX === $this->value->getType();
70032 }
70033
70034
70035
70036
70037 public function isGlob()
70038 {
70039 return self::TYPE_GLOB === $this->value->getType();
70040 }
70041
70042
70043
70044
70045
70046
70047 public function getGlob()
70048 {
70049 if (self::TYPE_GLOB !== $this->value->getType()) {
70050 throw new \LogicException('Regex can\'t be transformed to glob.');
70051 }
70052
70053 return $this->value;
70054 }
70055
70056
70057
70058
70059 public function getRegex()
70060 {
70061 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
70062 }
70063 }
70064 <?php
70065
70066
70067
70068
70069
70070
70071
70072
70073
70074
70075 namespace Symfony\Component\Finder\Expression;
70076
70077 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70078
70079 use Symfony\Component\Finder\Glob as FinderGlob;
70080
70081
70082
70083
70084 class Glob implements ValueInterface
70085 {
70086 private $pattern;
70087
70088
70089
70090
70091 public function __construct($pattern)
70092 {
70093 $this->pattern = $pattern;
70094 }
70095
70096
70097
70098
70099 public function render()
70100 {
70101 return $this->pattern;
70102 }
70103
70104
70105
70106
70107 public function renderPattern()
70108 {
70109 return $this->pattern;
70110 }
70111
70112
70113
70114
70115 public function getType()
70116 {
70117 return Expression::TYPE_GLOB;
70118 }
70119
70120
70121
70122
70123 public function isCaseSensitive()
70124 {
70125 return true;
70126 }
70127
70128
70129
70130
70131 public function prepend($expr)
70132 {
70133 $this->pattern = $expr.$this->pattern;
70134
70135 return $this;
70136 }
70137
70138
70139
70140
70141 public function append($expr)
70142 {
70143 $this->pattern .= $expr;
70144
70145 return $this;
70146 }
70147
70148
70149
70150
70151
70152
70153 public function isExpandable()
70154 {
70155 return false !== strpos($this->pattern, '{')
70156 && false !== strpos($this->pattern, '}');
70157 }
70158
70159
70160
70161
70162
70163
70164
70165 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
70166 {
70167 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
70168
70169 return new Regex($regex);
70170 }
70171 }
70172 <?php
70173
70174
70175
70176
70177
70178
70179
70180
70181
70182
70183 namespace Symfony\Component\Finder\Expression;
70184
70185 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70186
70187
70188
70189
70190 class Regex implements ValueInterface
70191 {
70192 const START_FLAG = '^';
70193 const END_FLAG = '$';
70194 const BOUNDARY = '~';
70195 const JOKER = '.*';
70196 const ESCAPING = '\\';
70197
70198
70199
70200
70201 private $pattern;
70202
70203
70204
70205
70206 private $options;
70207
70208
70209
70210
70211 private $startFlag;
70212
70213
70214
70215
70216 private $endFlag;
70217
70218
70219
70220
70221 private $startJoker;
70222
70223
70224
70225
70226 private $endJoker;
70227
70228
70229
70230
70231
70232
70233
70234
70235 public static function create($expr)
70236 {
70237 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
70238 $start = substr($m[1], 0, 1);
70239 $end = substr($m[1], -1);
70240
70241 if (
70242 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
70243 || ('{' === $start && '}' === $end)
70244 || ('(' === $start && ')' === $end)
70245 ) {
70246 return new self(substr($m[1], 1, -1), $m[2], $end);
70247 }
70248 }
70249
70250 throw new \InvalidArgumentException('Given expression is not a regex.');
70251 }
70252
70253
70254
70255
70256
70257
70258 public function __construct($pattern, $options = '', $delimiter = null)
70259 {
70260 if (null !== $delimiter) {
70261
70262  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
70263 }
70264
70265 $this->parsePattern($pattern);
70266 $this->options = $options;
70267 }
70268
70269
70270
70271
70272 public function __toString()
70273 {
70274 return $this->render();
70275 }
70276
70277
70278
70279
70280 public function render()
70281 {
70282 return self::BOUNDARY
70283 .$this->renderPattern()
70284 .self::BOUNDARY
70285 .$this->options;
70286 }
70287
70288
70289
70290
70291 public function renderPattern()
70292 {
70293 return ($this->startFlag ? self::START_FLAG : '')
70294 .($this->startJoker ? self::JOKER : '')
70295 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
70296 .($this->endJoker ? self::JOKER : '')
70297 .($this->endFlag ? self::END_FLAG : '');
70298 }
70299
70300
70301
70302
70303 public function isCaseSensitive()
70304 {
70305 return !$this->hasOption('i');
70306 }
70307
70308
70309
70310
70311 public function getType()
70312 {
70313 return Expression::TYPE_REGEX;
70314 }
70315
70316
70317
70318
70319 public function prepend($expr)
70320 {
70321 $this->pattern = $expr.$this->pattern;
70322
70323 return $this;
70324 }
70325
70326
70327
70328
70329 public function append($expr)
70330 {
70331 $this->pattern .= $expr;
70332
70333 return $this;
70334 }
70335
70336
70337
70338
70339
70340
70341 public function hasOption($option)
70342 {
70343 return false !== strpos($this->options, $option);
70344 }
70345
70346
70347
70348
70349
70350
70351 public function addOption($option)
70352 {
70353 if (!$this->hasOption($option)) {
70354 $this->options .= $option;
70355 }
70356
70357 return $this;
70358 }
70359
70360
70361
70362
70363
70364
70365 public function removeOption($option)
70366 {
70367 $this->options = str_replace($option, '', $this->options);
70368
70369 return $this;
70370 }
70371
70372
70373
70374
70375
70376
70377 public function setStartFlag($startFlag)
70378 {
70379 $this->startFlag = $startFlag;
70380
70381 return $this;
70382 }
70383
70384
70385
70386
70387 public function hasStartFlag()
70388 {
70389 return $this->startFlag;
70390 }
70391
70392
70393
70394
70395
70396
70397 public function setEndFlag($endFlag)
70398 {
70399 $this->endFlag = (bool) $endFlag;
70400
70401 return $this;
70402 }
70403
70404
70405
70406
70407 public function hasEndFlag()
70408 {
70409 return $this->endFlag;
70410 }
70411
70412
70413
70414
70415
70416
70417 public function setStartJoker($startJoker)
70418 {
70419 $this->startJoker = $startJoker;
70420
70421 return $this;
70422 }
70423
70424
70425
70426
70427 public function hasStartJoker()
70428 {
70429 return $this->startJoker;
70430 }
70431
70432
70433
70434
70435
70436
70437 public function setEndJoker($endJoker)
70438 {
70439 $this->endJoker = (bool) $endJoker;
70440
70441 return $this;
70442 }
70443
70444
70445
70446
70447 public function hasEndJoker()
70448 {
70449 return $this->endJoker;
70450 }
70451
70452
70453
70454
70455 public function replaceJokers($replacement)
70456 {
70457 $replace = function ($subject) use ($replacement) {
70458 $subject = $subject[0];
70459 $replace = 0 === substr_count($subject, '\\') % 2;
70460
70461 return $replace ? str_replace('.', $replacement, $subject) : $subject;
70462 };
70463
70464 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
70465
70466 return $this;
70467 }
70468
70469
70470
70471
70472 private function parsePattern($pattern)
70473 {
70474 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
70475 $pattern = substr($pattern, 1);
70476 }
70477
70478 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
70479 $pattern = substr($pattern, 2);
70480 }
70481
70482 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
70483 $pattern = substr($pattern, 0, -1);
70484 }
70485
70486 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
70487 $pattern = substr($pattern, 0, -2);
70488 }
70489
70490 $this->pattern = $pattern;
70491 }
70492 }
70493 <?php
70494
70495
70496
70497
70498
70499
70500
70501
70502
70503
70504 namespace Symfony\Component\Finder\Expression;
70505
70506 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70507
70508
70509
70510
70511 interface ValueInterface
70512 {
70513
70514
70515
70516
70517
70518 public function render();
70519
70520
70521
70522
70523
70524
70525 public function renderPattern();
70526
70527
70528
70529
70530
70531
70532 public function isCaseSensitive();
70533
70534
70535
70536
70537
70538
70539 public function getType();
70540
70541
70542
70543
70544
70545
70546 public function prepend($expr);
70547
70548
70549
70550
70551
70552
70553 public function append($expr);
70554 }
70555 <?php
70556
70557
70558
70559
70560
70561
70562
70563
70564
70565
70566 namespace Symfony\Component\Finder;
70567
70568 use Symfony\Component\Finder\Adapter\AdapterInterface;
70569 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
70570 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
70571 use Symfony\Component\Finder\Adapter\PhpAdapter;
70572 use Symfony\Component\Finder\Comparator\DateComparator;
70573 use Symfony\Component\Finder\Comparator\NumberComparator;
70574 use Symfony\Component\Finder\Exception\ExceptionInterface;
70575 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
70576 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
70577 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
70578 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
70579 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
70580 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
70581 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
70582 use Symfony\Component\Finder\Iterator\SortableIterator;
70583
70584
70585
70586
70587
70588
70589
70590
70591
70592
70593
70594
70595
70596
70597 class Finder implements \IteratorAggregate, \Countable
70598 {
70599 const IGNORE_VCS_FILES = 1;
70600 const IGNORE_DOT_FILES = 2;
70601
70602 private $mode = 0;
70603 private $names = array();
70604 private $notNames = array();
70605 private $exclude = array();
70606 private $filters = array();
70607 private $depths = array();
70608 private $sizes = array();
70609 private $followLinks = false;
70610 private $sort = false;
70611 private $ignore = 0;
70612 private $dirs = array();
70613 private $dates = array();
70614 private $iterators = array();
70615 private $contains = array();
70616 private $notContains = array();
70617 private $adapters = null;
70618 private $paths = array();
70619 private $notPaths = array();
70620 private $ignoreUnreadableDirs = false;
70621
70622 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
70623
70624 public function __construct()
70625 {
70626 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
70627 }
70628
70629
70630
70631
70632
70633
70634 public static function create()
70635 {
70636 return new static();
70637 }
70638
70639
70640
70641
70642
70643
70644
70645
70646
70647
70648
70649 public function addAdapter(AdapterInterface $adapter, $priority = 0)
70650 {
70651 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70652
70653 $this->initDefaultAdapters();
70654
70655 $this->adapters[$adapter->getName()] = array(
70656 'adapter' => $adapter,
70657 'priority' => $priority,
70658 'selected' => false,
70659 );
70660
70661 return $this->sortAdapters();
70662 }
70663
70664
70665
70666
70667
70668
70669
70670
70671 public function useBestAdapter()
70672 {
70673 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70674
70675 $this->initDefaultAdapters();
70676
70677 $this->resetAdapterSelection();
70678
70679 return $this->sortAdapters();
70680 }
70681
70682
70683
70684
70685
70686
70687
70688
70689
70690
70691
70692
70693 public function setAdapter($name)
70694 {
70695 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70696
70697 $this->initDefaultAdapters();
70698
70699 if (!isset($this->adapters[$name])) {
70700 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
70701 }
70702
70703 $this->resetAdapterSelection();
70704 $this->adapters[$name]['selected'] = true;
70705
70706 return $this->sortAdapters();
70707 }
70708
70709
70710
70711
70712
70713
70714
70715
70716 public function removeAdapters()
70717 {
70718 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70719
70720 $this->adapters = array();
70721
70722 return $this;
70723 }
70724
70725
70726
70727
70728
70729
70730
70731
70732 public function getAdapters()
70733 {
70734 @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
70735
70736 $this->initDefaultAdapters();
70737
70738 return array_values(array_map(function (array $adapter) {
70739 return $adapter['adapter'];
70740 }, $this->adapters));
70741 }
70742
70743
70744
70745
70746
70747
70748 public function directories()
70749 {
70750 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
70751
70752 return $this;
70753 }
70754
70755
70756
70757
70758
70759
70760 public function files()
70761 {
70762 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
70763
70764 return $this;
70765 }
70766
70767
70768
70769
70770
70771
70772
70773
70774
70775
70776
70777
70778
70779
70780
70781
70782 public function depth($level)
70783 {
70784 $this->depths[] = new Comparator\NumberComparator($level);
70785
70786 return $this;
70787 }
70788
70789
70790
70791
70792
70793
70794
70795
70796
70797
70798
70799
70800
70801
70802
70803
70804
70805
70806
70807 public function date($date)
70808 {
70809 $this->dates[] = new Comparator\DateComparator($date);
70810
70811 return $this;
70812 }
70813
70814
70815
70816
70817
70818
70819
70820
70821
70822
70823
70824
70825
70826
70827
70828
70829 public function name($pattern)
70830 {
70831 $this->names[] = $pattern;
70832
70833 return $this;
70834 }
70835
70836
70837
70838
70839
70840
70841
70842
70843
70844
70845 public function notName($pattern)
70846 {
70847 $this->notNames[] = $pattern;
70848
70849 return $this;
70850 }
70851
70852
70853
70854
70855
70856
70857
70858
70859
70860
70861
70862
70863
70864
70865
70866 public function contains($pattern)
70867 {
70868 $this->contains[] = $pattern;
70869
70870 return $this;
70871 }
70872
70873
70874
70875
70876
70877
70878
70879
70880
70881
70882
70883
70884
70885
70886
70887 public function notContains($pattern)
70888 {
70889 $this->notContains[] = $pattern;
70890
70891 return $this;
70892 }
70893
70894
70895
70896
70897
70898
70899
70900
70901
70902
70903
70904
70905
70906
70907
70908
70909
70910 public function path($pattern)
70911 {
70912 $this->paths[] = $pattern;
70913
70914 return $this;
70915 }
70916
70917
70918
70919
70920
70921
70922
70923
70924
70925
70926
70927
70928
70929
70930
70931
70932
70933 public function notPath($pattern)
70934 {
70935 $this->notPaths[] = $pattern;
70936
70937 return $this;
70938 }
70939
70940
70941
70942
70943
70944
70945
70946
70947
70948
70949
70950
70951
70952
70953
70954 public function size($size)
70955 {
70956 $this->sizes[] = new Comparator\NumberComparator($size);
70957
70958 return $this;
70959 }
70960
70961
70962
70963
70964
70965
70966
70967
70968
70969
70970
70971
70972
70973
70974 public function exclude($dirs)
70975 {
70976 $this->exclude = array_merge($this->exclude, (array) $dirs);
70977
70978 return $this;
70979 }
70980
70981
70982
70983
70984
70985
70986
70987
70988
70989
70990
70991
70992 public function ignoreDotFiles($ignoreDotFiles)
70993 {
70994 if ($ignoreDotFiles) {
70995 $this->ignore |= static::IGNORE_DOT_FILES;
70996 } else {
70997 $this->ignore &= ~static::IGNORE_DOT_FILES;
70998 }
70999
71000 return $this;
71001 }
71002
71003
71004
71005
71006
71007
71008
71009
71010
71011
71012
71013
71014 public function ignoreVCS($ignoreVCS)
71015 {
71016 if ($ignoreVCS) {
71017 $this->ignore |= static::IGNORE_VCS_FILES;
71018 } else {
71019 $this->ignore &= ~static::IGNORE_VCS_FILES;
71020 }
71021
71022 return $this;
71023 }
71024
71025
71026
71027
71028
71029
71030
71031
71032 public static function addVCSPattern($pattern)
71033 {
71034 foreach ((array) $pattern as $p) {
71035 self::$vcsPatterns[] = $p;
71036 }
71037
71038 self::$vcsPatterns = array_unique(self::$vcsPatterns);
71039 }
71040
71041
71042
71043
71044
71045
71046
71047
71048
71049
71050
71051
71052 public function sort(\Closure $closure)
71053 {
71054 $this->sort = $closure;
71055
71056 return $this;
71057 }
71058
71059
71060
71061
71062
71063
71064
71065
71066
71067
71068 public function sortByName()
71069 {
71070 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
71071
71072 return $this;
71073 }
71074
71075
71076
71077
71078
71079
71080
71081
71082
71083
71084 public function sortByType()
71085 {
71086 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
71087
71088 return $this;
71089 }
71090
71091
71092
71093
71094
71095
71096
71097
71098
71099
71100
71101
71102 public function sortByAccessedTime()
71103 {
71104 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
71105
71106 return $this;
71107 }
71108
71109
71110
71111
71112
71113
71114
71115
71116
71117
71118
71119
71120
71121
71122 public function sortByChangedTime()
71123 {
71124 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
71125
71126 return $this;
71127 }
71128
71129
71130
71131
71132
71133
71134
71135
71136
71137
71138
71139
71140 public function sortByModifiedTime()
71141 {
71142 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
71143
71144 return $this;
71145 }
71146
71147
71148
71149
71150
71151
71152
71153
71154
71155
71156
71157 public function filter(\Closure $closure)
71158 {
71159 $this->filters[] = $closure;
71160
71161 return $this;
71162 }
71163
71164
71165
71166
71167
71168
71169 public function followLinks()
71170 {
71171 $this->followLinks = true;
71172
71173 return $this;
71174 }
71175
71176
71177
71178
71179
71180
71181
71182
71183
71184
71185 public function ignoreUnreadableDirs($ignore = true)
71186 {
71187 $this->ignoreUnreadableDirs = (bool) $ignore;
71188
71189 return $this;
71190 }
71191
71192
71193
71194
71195
71196
71197
71198
71199
71200
71201 public function in($dirs)
71202 {
71203 $resolvedDirs = array();
71204
71205 foreach ((array) $dirs as $dir) {
71206 if (is_dir($dir)) {
71207 $resolvedDirs[] = $this->normalizeDir($dir);
71208 } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
71209 $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob));
71210 } else {
71211 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
71212 }
71213 }
71214
71215 $this->dirs = array_merge($this->dirs, $resolvedDirs);
71216
71217 return $this;
71218 }
71219
71220
71221
71222
71223
71224
71225
71226
71227
71228
71229 public function getIterator()
71230 {
71231 if (0 === \count($this->dirs) && 0 === \count($this->iterators)) {
71232 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
71233 }
71234
71235 if (1 === \count($this->dirs) && 0 === \count($this->iterators)) {
71236 return $this->searchInDirectory($this->dirs[0]);
71237 }
71238
71239 $iterator = new \AppendIterator();
71240 foreach ($this->dirs as $dir) {
71241 $iterator->append($this->searchInDirectory($dir));
71242 }
71243
71244 foreach ($this->iterators as $it) {
71245 $iterator->append($it);
71246 }
71247
71248 return $iterator;
71249 }
71250
71251
71252
71253
71254
71255
71256
71257
71258
71259
71260
71261
71262 public function append($iterator)
71263 {
71264 if ($iterator instanceof \IteratorAggregate) {
71265 $this->iterators[] = $iterator->getIterator();
71266 } elseif ($iterator instanceof \Iterator) {
71267 $this->iterators[] = $iterator;
71268 } elseif ($iterator instanceof \Traversable || \is_array($iterator)) {
71269 $it = new \ArrayIterator();
71270 foreach ($iterator as $file) {
71271 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
71272 }
71273 $this->iterators[] = $it;
71274 } else {
71275 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
71276 }
71277
71278 return $this;
71279 }
71280
71281
71282
71283
71284
71285
71286 public function count()
71287 {
71288 return iterator_count($this->getIterator());
71289 }
71290
71291
71292
71293
71294 private function sortAdapters()
71295 {
71296 uasort($this->adapters, function (array $a, array $b) {
71297 if ($a['selected'] || $b['selected']) {
71298 return $a['selected'] ? -1 : 1;
71299 }
71300
71301 return $a['priority'] > $b['priority'] ? -1 : 1;
71302 });
71303
71304 return $this;
71305 }
71306
71307
71308
71309
71310
71311
71312 private function searchInDirectory($dir)
71313 {
71314 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
71315 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
71316 }
71317
71318 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
71319 $this->notPaths[] = '#(^|/)\..+(/|$)#';
71320 }
71321
71322 if ($this->adapters) {
71323 foreach ($this->adapters as $adapter) {
71324 if ($adapter['adapter']->isSupported()) {
71325 try {
71326 return $this
71327 ->buildAdapter($adapter['adapter'])
71328 ->searchInDirectory($dir);
71329 } catch (ExceptionInterface $e) {
71330 }
71331 }
71332 }
71333 }
71334
71335 $minDepth = 0;
71336 $maxDepth = PHP_INT_MAX;
71337
71338 foreach ($this->depths as $comparator) {
71339 switch ($comparator->getOperator()) {
71340 case '>':
71341 $minDepth = $comparator->getTarget() + 1;
71342 break;
71343 case '>=':
71344 $minDepth = $comparator->getTarget();
71345 break;
71346 case '<':
71347 $maxDepth = $comparator->getTarget() - 1;
71348 break;
71349 case '<=':
71350 $maxDepth = $comparator->getTarget();
71351 break;
71352 default:
71353 $minDepth = $maxDepth = $comparator->getTarget();
71354 }
71355 }
71356
71357 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
71358
71359 if ($this->followLinks) {
71360 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
71361 }
71362
71363 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
71364
71365 if ($this->exclude) {
71366 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
71367 }
71368
71369 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
71370
71371 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
71372 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
71373 }
71374
71375 if ($this->mode) {
71376 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
71377 }
71378
71379 if ($this->names || $this->notNames) {
71380 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
71381 }
71382
71383 if ($this->contains || $this->notContains) {
71384 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
71385 }
71386
71387 if ($this->sizes) {
71388 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
71389 }
71390
71391 if ($this->dates) {
71392 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
71393 }
71394
71395 if ($this->filters) {
71396 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
71397 }
71398
71399 if ($this->paths || $this->notPaths) {
71400 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
71401 }
71402
71403 if ($this->sort) {
71404 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
71405 $iterator = $iteratorAggregate->getIterator();
71406 }
71407
71408 return $iterator;
71409 }
71410
71411
71412
71413
71414 private function buildAdapter(AdapterInterface $adapter)
71415 {
71416 return $adapter
71417 ->setFollowLinks($this->followLinks)
71418 ->setDepths($this->depths)
71419 ->setMode($this->mode)
71420 ->setExclude($this->exclude)
71421 ->setNames($this->names)
71422 ->setNotNames($this->notNames)
71423 ->setContains($this->contains)
71424 ->setNotContains($this->notContains)
71425 ->setSizes($this->sizes)
71426 ->setDates($this->dates)
71427 ->setFilters($this->filters)
71428 ->setSort($this->sort)
71429 ->setPath($this->paths)
71430 ->setNotPath($this->notPaths)
71431 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
71432 }
71433
71434
71435
71436
71437 private function resetAdapterSelection()
71438 {
71439 $this->adapters = array_map(function (array $properties) {
71440 $properties['selected'] = false;
71441
71442 return $properties;
71443 }, $this->adapters);
71444 }
71445
71446 private function initDefaultAdapters()
71447 {
71448 if (null === $this->adapters) {
71449 $this->adapters = array();
71450 $this
71451 ->addAdapter(new GnuFindAdapter())
71452 ->addAdapter(new BsdFindAdapter())
71453 ->addAdapter(new PhpAdapter(), -50)
71454 ->setAdapter('php')
71455 ;
71456 }
71457 }
71458
71459
71460
71461
71462
71463
71464
71465
71466 private function normalizeDir($dir)
71467 {
71468 return rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
71469 }
71470 }
71471 <?php
71472
71473
71474
71475
71476
71477
71478
71479
71480
71481
71482 namespace Symfony\Component\Finder;
71483
71484
71485
71486
71487
71488
71489
71490
71491
71492
71493
71494
71495
71496
71497
71498
71499
71500
71501
71502
71503
71504
71505
71506 class Glob
71507 {
71508
71509
71510
71511
71512
71513
71514
71515
71516
71517
71518 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
71519 {
71520 $firstByte = true;
71521 $escaping = false;
71522 $inCurlies = 0;
71523 $regex = '';
71524 $sizeGlob = \strlen($glob);
71525 for ($i = 0; $i < $sizeGlob; ++$i) {
71526 $car = $glob[$i];
71527 if ($firstByte) {
71528 if ($strictLeadingDot && '.' !== $car) {
71529 $regex .= '(?=[^\.])';
71530 }
71531
71532 $firstByte = false;
71533 }
71534
71535 if ('/' === $car) {
71536 $firstByte = true;
71537 }
71538
71539 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
71540 $regex .= "\\$car";
71541 } elseif ('*' === $car) {
71542 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
71543 } elseif ('?' === $car) {
71544 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
71545 } elseif ('{' === $car) {
71546 $regex .= $escaping ? '\\{' : '(';
71547 if (!$escaping) {
71548 ++$inCurlies;
71549 }
71550 } elseif ('}' === $car && $inCurlies) {
71551 $regex .= $escaping ? '}' : ')';
71552 if (!$escaping) {
71553 --$inCurlies;
71554 }
71555 } elseif (',' === $car && $inCurlies) {
71556 $regex .= $escaping ? ',' : '|';
71557 } elseif ('\\' === $car) {
71558 if ($escaping) {
71559 $regex .= '\\\\';
71560 $escaping = false;
71561 } else {
71562 $escaping = true;
71563 }
71564
71565 continue;
71566 } else {
71567 $regex .= $car;
71568 }
71569 $escaping = false;
71570 }
71571
71572 return $delimiter.'^'.$regex.'$'.$delimiter;
71573 }
71574 }
71575 <?php
71576
71577
71578
71579
71580
71581
71582
71583
71584
71585
71586 namespace Symfony\Component\Finder\Iterator;
71587
71588
71589
71590
71591
71592
71593
71594
71595
71596 class CustomFilterIterator extends FilterIterator
71597 {
71598 private $filters = array();
71599
71600
71601
71602
71603
71604
71605
71606 public function __construct(\Iterator $iterator, array $filters)
71607 {
71608 foreach ($filters as $filter) {
71609 if (!\is_callable($filter)) {
71610 throw new \InvalidArgumentException('Invalid PHP callback.');
71611 }
71612 }
71613 $this->filters = $filters;
71614
71615 parent::__construct($iterator);
71616 }
71617
71618
71619
71620
71621
71622
71623 public function accept()
71624 {
71625 $fileinfo = $this->current();
71626
71627 foreach ($this->filters as $filter) {
71628 if (false === \call_user_func($filter, $fileinfo)) {
71629 return false;
71630 }
71631 }
71632
71633 return true;
71634 }
71635 }
71636 <?php
71637
71638
71639
71640
71641
71642
71643
71644
71645
71646
71647 namespace Symfony\Component\Finder\Iterator;
71648
71649 use Symfony\Component\Finder\Comparator\DateComparator;
71650
71651
71652
71653
71654
71655
71656 class DateRangeFilterIterator extends FilterIterator
71657 {
71658 private $comparators = array();
71659
71660
71661
71662
71663
71664 public function __construct(\Iterator $iterator, array $comparators)
71665 {
71666 $this->comparators = $comparators;
71667
71668 parent::__construct($iterator);
71669 }
71670
71671
71672
71673
71674
71675
71676 public function accept()
71677 {
71678 $fileinfo = $this->current();
71679
71680 if (!file_exists($fileinfo->getPathname())) {
71681 return false;
71682 }
71683
71684 $filedate = $fileinfo->getMTime();
71685 foreach ($this->comparators as $compare) {
71686 if (!$compare->test($filedate)) {
71687 return false;
71688 }
71689 }
71690
71691 return true;
71692 }
71693 }
71694 <?php
71695
71696
71697
71698
71699
71700
71701
71702
71703
71704
71705 namespace Symfony\Component\Finder\Iterator;
71706
71707
71708
71709
71710
71711
71712 class DepthRangeFilterIterator extends FilterIterator
71713 {
71714 private $minDepth = 0;
71715
71716
71717
71718
71719
71720
71721 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
71722 {
71723 $this->minDepth = $minDepth;
71724 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
71725
71726 parent::__construct($iterator);
71727 }
71728
71729
71730
71731
71732
71733
71734 public function accept()
71735 {
71736 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
71737 }
71738 }
71739 <?php
71740
71741
71742
71743
71744
71745
71746
71747
71748
71749
71750 namespace Symfony\Component\Finder\Iterator;
71751
71752
71753
71754
71755
71756
71757 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
71758 {
71759 private $iterator;
71760 private $isRecursive;
71761 private $excludedDirs = array();
71762 private $excludedPattern;
71763
71764
71765
71766
71767
71768 public function __construct(\Iterator $iterator, array $directories)
71769 {
71770 $this->iterator = $iterator;
71771 $this->isRecursive = $iterator instanceof \RecursiveIterator;
71772 $patterns = array();
71773 foreach ($directories as $directory) {
71774 $directory = rtrim($directory, '/');
71775 if (!$this->isRecursive || false !== strpos($directory, '/')) {
71776 $patterns[] = preg_quote($directory, '#');
71777 } else {
71778 $this->excludedDirs[$directory] = true;
71779 }
71780 }
71781 if ($patterns) {
71782 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
71783 }
71784
71785 parent::__construct($iterator);
71786 }
71787
71788
71789
71790
71791
71792
71793 public function accept()
71794 {
71795 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
71796 return false;
71797 }
71798
71799 if ($this->excludedPattern) {
71800 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
71801 $path = str_replace('\\', '/', $path);
71802
71803 return !preg_match($this->excludedPattern, $path);
71804 }
71805
71806 return true;
71807 }
71808
71809 public function hasChildren()
71810 {
71811 return $this->isRecursive && $this->iterator->hasChildren();
71812 }
71813
71814 public function getChildren()
71815 {
71816 $children = new self($this->iterator->getChildren(), array());
71817 $children->excludedDirs = $this->excludedDirs;
71818 $children->excludedPattern = $this->excludedPattern;
71819
71820 return $children;
71821 }
71822 }
71823 <?php
71824
71825
71826
71827
71828
71829
71830
71831
71832
71833
71834 namespace Symfony\Component\Finder\Iterator;
71835
71836 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
71837
71838 use Symfony\Component\Finder\SplFileInfo;
71839
71840
71841
71842
71843
71844
71845
71846
71847 class FilePathsIterator extends \ArrayIterator
71848 {
71849
71850
71851
71852 private $baseDir;
71853
71854
71855
71856
71857 private $baseDirLength;
71858
71859
71860
71861
71862 private $subPath;
71863
71864
71865
71866
71867 private $subPathname;
71868
71869
71870
71871
71872 private $current;
71873
71874
71875
71876
71877
71878 public function __construct(array $paths, $baseDir)
71879 {
71880 $this->baseDir = $baseDir;
71881 $this->baseDirLength = \strlen($baseDir);
71882
71883 parent::__construct($paths);
71884 }
71885
71886
71887
71888
71889
71890
71891
71892 public function __call($name, array $arguments)
71893 {
71894 return \call_user_func_array(array($this->current(), $name), $arguments);
71895 }
71896
71897
71898
71899
71900
71901
71902 public function current()
71903 {
71904 return $this->current;
71905 }
71906
71907
71908
71909
71910 public function key()
71911 {
71912 return $this->current->getPathname();
71913 }
71914
71915 public function next()
71916 {
71917 parent::next();
71918 $this->buildProperties();
71919 }
71920
71921 public function rewind()
71922 {
71923 parent::rewind();
71924 $this->buildProperties();
71925 }
71926
71927
71928
71929
71930 public function getSubPath()
71931 {
71932 return $this->subPath;
71933 }
71934
71935
71936
71937
71938 public function getSubPathname()
71939 {
71940 return $this->subPathname;
71941 }
71942
71943 private function buildProperties()
71944 {
71945 $absolutePath = parent::current();
71946
71947 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
71948 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
71949 $dir = \dirname($this->subPathname);
71950 $this->subPath = '.' === $dir ? '' : $dir;
71951 } else {
71952 $this->subPath = $this->subPathname = '';
71953 }
71954
71955 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
71956 }
71957 }
71958 <?php
71959
71960
71961
71962
71963
71964
71965
71966
71967
71968
71969 namespace Symfony\Component\Finder\Iterator;
71970
71971
71972
71973
71974
71975
71976 class FileTypeFilterIterator extends FilterIterator
71977 {
71978 const ONLY_FILES = 1;
71979 const ONLY_DIRECTORIES = 2;
71980
71981 private $mode;
71982
71983
71984
71985
71986
71987 public function __construct(\Iterator $iterator, $mode)
71988 {
71989 $this->mode = $mode;
71990
71991 parent::__construct($iterator);
71992 }
71993
71994
71995
71996
71997
71998
71999 public function accept()
72000 {
72001 $fileinfo = $this->current();
72002 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
72003 return false;
72004 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
72005 return false;
72006 }
72007
72008 return true;
72009 }
72010 }
72011 <?php
72012
72013
72014
72015
72016
72017
72018
72019
72020
72021
72022 namespace Symfony\Component\Finder\Iterator;
72023
72024
72025
72026
72027
72028
72029
72030 class FilecontentFilterIterator extends MultiplePcreFilterIterator
72031 {
72032
72033
72034
72035
72036
72037 public function accept()
72038 {
72039 if (!$this->matchRegexps && !$this->noMatchRegexps) {
72040 return true;
72041 }
72042
72043 $fileinfo = $this->current();
72044
72045 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
72046 return false;
72047 }
72048
72049 $content = $fileinfo->getContents();
72050 if (!$content) {
72051 return false;
72052 }
72053
72054 return $this->isAccepted($content);
72055 }
72056
72057
72058
72059
72060
72061
72062
72063
72064 protected function toRegex($str)
72065 {
72066 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
72067 }
72068 }
72069 <?php
72070
72071
72072
72073
72074
72075
72076
72077
72078
72079
72080 namespace Symfony\Component\Finder\Iterator;
72081
72082 use Symfony\Component\Finder\Glob;
72083
72084
72085
72086
72087
72088
72089 class FilenameFilterIterator extends MultiplePcreFilterIterator
72090 {
72091
72092
72093
72094
72095
72096 public function accept()
72097 {
72098 return $this->isAccepted($this->current()->getFilename());
72099 }
72100
72101
72102
72103
72104
72105
72106
72107
72108
72109
72110
72111 protected function toRegex($str)
72112 {
72113 return $this->isRegex($str) ? $str : Glob::toRegex($str);
72114 }
72115 }
72116 <?php
72117
72118
72119
72120
72121
72122
72123
72124
72125
72126
72127 namespace Symfony\Component\Finder\Iterator;
72128
72129
72130
72131
72132
72133
72134
72135
72136
72137 abstract class FilterIterator extends \FilterIterator
72138 {
72139
72140
72141
72142
72143
72144
72145 public function rewind()
72146 {
72147 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
72148 parent::rewind();
72149
72150 return;
72151 }
72152
72153 $iterator = $this;
72154 while ($iterator instanceof \OuterIterator) {
72155 $innerIterator = $iterator->getInnerIterator();
72156
72157 if ($innerIterator instanceof RecursiveDirectoryIterator) {
72158
72159  if ($innerIterator->isRewindable()) {
72160 $innerIterator->next();
72161 $innerIterator->rewind();
72162 }
72163 } elseif ($innerIterator instanceof \FilesystemIterator) {
72164 $innerIterator->next();
72165 $innerIterator->rewind();
72166 }
72167
72168 $iterator = $innerIterator;
72169 }
72170
72171 parent::rewind();
72172 }
72173 }
72174 <?php
72175
72176
72177
72178
72179
72180
72181
72182
72183
72184
72185 namespace Symfony\Component\Finder\Iterator;
72186
72187
72188
72189
72190
72191
72192 abstract class MultiplePcreFilterIterator extends FilterIterator
72193 {
72194 protected $matchRegexps = array();
72195 protected $noMatchRegexps = array();
72196
72197
72198
72199
72200
72201
72202 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
72203 {
72204 foreach ($matchPatterns as $pattern) {
72205 $this->matchRegexps[] = $this->toRegex($pattern);
72206 }
72207
72208 foreach ($noMatchPatterns as $pattern) {
72209 $this->noMatchRegexps[] = $this->toRegex($pattern);
72210 }
72211
72212 parent::__construct($iterator);
72213 }
72214
72215
72216
72217
72218
72219
72220
72221
72222
72223
72224
72225
72226 protected function isAccepted($string)
72227 {
72228
72229  foreach ($this->noMatchRegexps as $regex) {
72230 if (preg_match($regex, $string)) {
72231 return false;
72232 }
72233 }
72234
72235
72236  if ($this->matchRegexps) {
72237 foreach ($this->matchRegexps as $regex) {
72238 if (preg_match($regex, $string)) {
72239 return true;
72240 }
72241 }
72242
72243 return false;
72244 }
72245
72246
72247  return true;
72248 }
72249
72250
72251
72252
72253
72254
72255
72256
72257 protected function isRegex($str)
72258 {
72259 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
72260 $start = substr($m[1], 0, 1);
72261 $end = substr($m[1], -1);
72262
72263 if ($start === $end) {
72264 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
72265 }
72266
72267 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
72268 if ($start === $delimiters[0] && $end === $delimiters[1]) {
72269 return true;
72270 }
72271 }
72272 }
72273
72274 return false;
72275 }
72276
72277
72278
72279
72280
72281
72282
72283
72284 abstract protected function toRegex($str);
72285 }
72286 <?php
72287
72288
72289
72290
72291
72292
72293
72294
72295
72296
72297 namespace Symfony\Component\Finder\Iterator;
72298
72299
72300
72301
72302
72303
72304
72305 class PathFilterIterator extends MultiplePcreFilterIterator
72306 {
72307
72308
72309
72310
72311
72312 public function accept()
72313 {
72314 $filename = $this->current()->getRelativePathname();
72315
72316 if ('\\' === \DIRECTORY_SEPARATOR) {
72317 $filename = str_replace('\\', '/', $filename);
72318 }
72319
72320 return $this->isAccepted($filename);
72321 }
72322
72323
72324
72325
72326
72327
72328
72329
72330
72331
72332
72333
72334
72335
72336
72337 protected function toRegex($str)
72338 {
72339 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
72340 }
72341 }
72342 <?php
72343
72344
72345
72346
72347
72348
72349
72350
72351
72352
72353 namespace Symfony\Component\Finder\Iterator;
72354
72355 use Symfony\Component\Finder\Exception\AccessDeniedException;
72356 use Symfony\Component\Finder\SplFileInfo;
72357
72358
72359
72360
72361
72362
72363 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
72364 {
72365
72366
72367
72368 private $ignoreUnreadableDirs;
72369
72370
72371
72372
72373 private $rewindable;
72374
72375
72376  private $rootPath;
72377 private $subPath;
72378 private $directorySeparator = '/';
72379
72380
72381
72382
72383
72384
72385
72386
72387 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
72388 {
72389 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
72390 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
72391 }
72392
72393 parent::__construct($path, $flags);
72394 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
72395 $this->rootPath = (string) $path;
72396 if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
72397 $this->directorySeparator = \DIRECTORY_SEPARATOR;
72398 }
72399 }
72400
72401
72402
72403
72404
72405
72406 public function current()
72407 {
72408
72409
72410 if (null === $subPathname = $this->subPath) {
72411 $subPathname = $this->subPath = (string) $this->getSubPath();
72412 }
72413 if ('' !== $subPathname) {
72414 $subPathname .= $this->directorySeparator;
72415 }
72416 $subPathname .= $this->getFilename();
72417
72418 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
72419 }
72420
72421
72422
72423
72424
72425
72426 public function getChildren()
72427 {
72428 try {
72429 $children = parent::getChildren();
72430
72431 if ($children instanceof self) {
72432
72433  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
72434
72435
72436  $children->rewindable = &$this->rewindable;
72437 $children->rootPath = $this->rootPath;
72438 }
72439
72440 return $children;
72441 } catch (\UnexpectedValueException $e) {
72442 if ($this->ignoreUnreadableDirs) {
72443
72444  return new \RecursiveArrayIterator(array());
72445 } else {
72446 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
72447 }
72448 }
72449 }
72450
72451
72452
72453
72454 public function rewind()
72455 {
72456 if (false === $this->isRewindable()) {
72457 return;
72458 }
72459
72460
72461  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
72462 parent::next();
72463 }
72464
72465 parent::rewind();
72466 }
72467
72468
72469
72470
72471
72472
72473 public function isRewindable()
72474 {
72475 if (null !== $this->rewindable) {
72476 return $this->rewindable;
72477 }
72478
72479
72480  if ('' === $this->getPath()) {
72481 return $this->rewindable = false;
72482 }
72483
72484 if (false !== $stream = @opendir($this->getPath())) {
72485 $infos = stream_get_meta_data($stream);
72486 closedir($stream);
72487
72488 if ($infos['seekable']) {
72489 return $this->rewindable = true;
72490 }
72491 }
72492
72493 return $this->rewindable = false;
72494 }
72495 }
72496 <?php
72497
72498
72499
72500
72501
72502
72503
72504
72505
72506
72507 namespace Symfony\Component\Finder\Iterator;
72508
72509 use Symfony\Component\Finder\Comparator\NumberComparator;
72510
72511
72512
72513
72514
72515
72516 class SizeRangeFilterIterator extends FilterIterator
72517 {
72518 private $comparators = array();
72519
72520
72521
72522
72523
72524 public function __construct(\Iterator $iterator, array $comparators)
72525 {
72526 $this->comparators = $comparators;
72527
72528 parent::__construct($iterator);
72529 }
72530
72531
72532
72533
72534
72535
72536 public function accept()
72537 {
72538 $fileinfo = $this->current();
72539 if (!$fileinfo->isFile()) {
72540 return true;
72541 }
72542
72543 $filesize = $fileinfo->getSize();
72544 foreach ($this->comparators as $compare) {
72545 if (!$compare->test($filesize)) {
72546 return false;
72547 }
72548 }
72549
72550 return true;
72551 }
72552 }
72553 <?php
72554
72555
72556
72557
72558
72559
72560
72561
72562
72563
72564 namespace Symfony\Component\Finder\Iterator;
72565
72566
72567
72568
72569
72570
72571 class SortableIterator implements \IteratorAggregate
72572 {
72573 const SORT_BY_NAME = 1;
72574 const SORT_BY_TYPE = 2;
72575 const SORT_BY_ACCESSED_TIME = 3;
72576 const SORT_BY_CHANGED_TIME = 4;
72577 const SORT_BY_MODIFIED_TIME = 5;
72578
72579 private $iterator;
72580 private $sort;
72581
72582
72583
72584
72585
72586
72587
72588 public function __construct(\Traversable $iterator, $sort)
72589 {
72590 $this->iterator = $iterator;
72591
72592 if (self::SORT_BY_NAME === $sort) {
72593 $this->sort = function ($a, $b) {
72594 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
72595 };
72596 } elseif (self::SORT_BY_TYPE === $sort) {
72597 $this->sort = function ($a, $b) {
72598 if ($a->isDir() && $b->isFile()) {
72599 return -1;
72600 } elseif ($a->isFile() && $b->isDir()) {
72601 return 1;
72602 }
72603
72604 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
72605 };
72606 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
72607 $this->sort = function ($a, $b) {
72608 return $a->getATime() - $b->getATime();
72609 };
72610 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
72611 $this->sort = function ($a, $b) {
72612 return $a->getCTime() - $b->getCTime();
72613 };
72614 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
72615 $this->sort = function ($a, $b) {
72616 return $a->getMTime() - $b->getMTime();
72617 };
72618 } elseif (\is_callable($sort)) {
72619 $this->sort = $sort;
72620 } else {
72621 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
72622 }
72623 }
72624
72625 public function getIterator()
72626 {
72627 $array = iterator_to_array($this->iterator, true);
72628 uasort($array, $this->sort);
72629
72630 return new \ArrayIterator($array);
72631 }
72632 }
72633 Copyright (c) 2004-2018 Fabien Potencier
72634
72635 Permission is hereby granted, free of charge, to any person obtaining a copy
72636 of this software and associated documentation files (the "Software"), to deal
72637 in the Software without restriction, including without limitation the rights
72638 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72639 copies of the Software, and to permit persons to whom the Software is furnished
72640 to do so, subject to the following conditions:
72641
72642 The above copyright notice and this permission notice shall be included in all
72643 copies or substantial portions of the Software.
72644
72645 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72646 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72647 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
72648 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72649 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
72650 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
72651 THE SOFTWARE.
72652 <?php
72653
72654
72655
72656
72657
72658
72659
72660
72661
72662
72663 namespace Symfony\Component\Finder\Shell;
72664
72665 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
72666
72667
72668
72669
72670
72671
72672 class Command
72673 {
72674 private $parent;
72675 private $bits = array();
72676 private $labels = array();
72677
72678
72679
72680
72681 private $errorHandler;
72682
72683 public function __construct(Command $parent = null)
72684 {
72685 $this->parent = $parent;
72686 }
72687
72688
72689
72690
72691
72692
72693 public function __toString()
72694 {
72695 return $this->join();
72696 }
72697
72698
72699
72700
72701
72702
72703 public static function create(Command $parent = null)
72704 {
72705 return new self($parent);
72706 }
72707
72708
72709
72710
72711
72712
72713
72714
72715 public static function escape($input)
72716 {
72717 return escapeshellcmd($input);
72718 }
72719
72720
72721
72722
72723
72724
72725
72726
72727 public static function quote($input)
72728 {
72729 return escapeshellarg($input);
72730 }
72731
72732
72733
72734
72735
72736
72737
72738
72739 public function add($bit)
72740 {
72741 $this->bits[] = $bit;
72742
72743 return $this;
72744 }
72745
72746
72747
72748
72749
72750
72751
72752
72753 public function top($bit)
72754 {
72755 array_unshift($this->bits, $bit);
72756
72757 foreach ($this->labels as $label => $index) {
72758 ++$this->labels[$label];
72759 }
72760
72761 return $this;
72762 }
72763
72764
72765
72766
72767
72768
72769
72770
72771 public function arg($arg)
72772 {
72773 $this->bits[] = self::quote($arg);
72774
72775 return $this;
72776 }
72777
72778
72779
72780
72781
72782
72783
72784
72785 public function cmd($esc)
72786 {
72787 $this->bits[] = self::escape($esc);
72788
72789 return $this;
72790 }
72791
72792
72793
72794
72795
72796
72797
72798
72799
72800
72801 public function ins($label)
72802 {
72803 if (isset($this->labels[$label])) {
72804 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
72805 }
72806
72807 $this->bits[] = self::create($this);
72808 $this->labels[$label] = \count($this->bits) - 1;
72809
72810 return $this->bits[$this->labels[$label]];
72811 }
72812
72813
72814
72815
72816
72817
72818
72819
72820
72821
72822 public function get($label)
72823 {
72824 if (!isset($this->labels[$label])) {
72825 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
72826 }
72827
72828 return $this->bits[$this->labels[$label]];
72829 }
72830
72831
72832
72833
72834
72835
72836
72837
72838 public function end()
72839 {
72840 if (null === $this->parent) {
72841 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
72842 }
72843
72844 return $this->parent;
72845 }
72846
72847
72848
72849
72850
72851
72852 public function length()
72853 {
72854 return \count($this->bits);
72855 }
72856
72857
72858
72859
72860 public function setErrorHandler(\Closure $errorHandler)
72861 {
72862 $this->errorHandler = $errorHandler;
72863
72864 return $this;
72865 }
72866
72867
72868
72869
72870 public function getErrorHandler()
72871 {
72872 return $this->errorHandler;
72873 }
72874
72875
72876
72877
72878
72879
72880
72881
72882 public function execute()
72883 {
72884 if (null === $errorHandler = $this->errorHandler) {
72885 exec($this->join(), $output);
72886 } else {
72887 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
72888 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
72889
72890 if ($error = stream_get_contents($pipes[2])) {
72891 $errorHandler($error);
72892 }
72893
72894 proc_close($process);
72895 }
72896
72897 return $output ?: array();
72898 }
72899
72900
72901
72902
72903
72904
72905 public function join()
72906 {
72907 return implode(' ', array_filter(
72908 array_map(function ($bit) {
72909 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
72910 }, $this->bits),
72911 function ($bit) { return null !== $bit; }
72912 ));
72913 }
72914
72915
72916
72917
72918
72919
72920
72921
72922
72923 public function addAtIndex($bit, $index)
72924 {
72925 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
72926
72927 return $this;
72928 }
72929 }
72930 <?php
72931
72932
72933
72934
72935
72936
72937
72938
72939
72940
72941 namespace Symfony\Component\Finder\Shell;
72942
72943 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
72944
72945
72946
72947
72948
72949
72950 class Shell
72951 {
72952 const TYPE_UNIX = 1;
72953 const TYPE_DARWIN = 2;
72954 const TYPE_CYGWIN = 3;
72955 const TYPE_WINDOWS = 4;
72956 const TYPE_BSD = 5;
72957
72958
72959
72960
72961 private $type;
72962
72963
72964
72965
72966
72967
72968 public function getType()
72969 {
72970 if (null === $this->type) {
72971 $this->type = $this->guessType();
72972 }
72973
72974 return $this->type;
72975 }
72976
72977
72978
72979
72980
72981
72982
72983
72984 public function testCommand($command)
72985 {
72986 if (!\function_exists('exec')) {
72987 return false;
72988 }
72989
72990
72991  $testCommand = 'which ';
72992 if (self::TYPE_WINDOWS === $this->type) {
72993 $testCommand = 'where ';
72994 }
72995
72996 $command = escapeshellcmd($command);
72997
72998 exec($testCommand.$command, $output, $code);
72999
73000 return 0 === $code && \count($output) > 0;
73001 }
73002
73003
73004
73005
73006
73007
73008 private function guessType()
73009 {
73010 $os = strtolower(PHP_OS);
73011
73012 if (false !== strpos($os, 'cygwin')) {
73013 return self::TYPE_CYGWIN;
73014 }
73015
73016 if (false !== strpos($os, 'darwin')) {
73017 return self::TYPE_DARWIN;
73018 }
73019
73020 if (false !== strpos($os, 'bsd')) {
73021 return self::TYPE_BSD;
73022 }
73023
73024 if (0 === strpos($os, 'win')) {
73025 return self::TYPE_WINDOWS;
73026 }
73027
73028 return self::TYPE_UNIX;
73029 }
73030 }
73031 <?php
73032
73033
73034
73035
73036
73037
73038
73039
73040
73041
73042 namespace Symfony\Component\Finder;
73043
73044
73045
73046
73047
73048
73049 class SplFileInfo extends \SplFileInfo
73050 {
73051 private $relativePath;
73052 private $relativePathname;
73053
73054
73055
73056
73057
73058
73059 public function __construct($file, $relativePath, $relativePathname)
73060 {
73061 parent::__construct($file);
73062 $this->relativePath = $relativePath;
73063 $this->relativePathname = $relativePathname;
73064 }
73065
73066
73067
73068
73069
73070
73071
73072
73073 public function getRelativePath()
73074 {
73075 return $this->relativePath;
73076 }
73077
73078
73079
73080
73081
73082
73083
73084
73085 public function getRelativePathname()
73086 {
73087 return $this->relativePathname;
73088 }
73089
73090
73091
73092
73093
73094
73095
73096
73097 public function getContents()
73098 {
73099 set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
73100 $content = file_get_contents($this->getPathname());
73101 restore_error_handler();
73102 if (false === $content) {
73103 throw new \RuntimeException($error);
73104 }
73105
73106 return $content;
73107 }
73108 }
73109 <?php
73110
73111
73112
73113
73114
73115
73116
73117
73118
73119
73120 namespace Symfony\Polyfill\Ctype;
73121
73122
73123
73124
73125
73126
73127
73128
73129 final class Ctype
73130 {
73131
73132
73133
73134
73135
73136
73137
73138
73139
73140 public static function ctype_alnum($text)
73141 {
73142 $text = self::convert_int_to_char_for_ctype($text);
73143
73144 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
73145 }
73146
73147
73148
73149
73150
73151
73152
73153
73154
73155
73156 public static function ctype_alpha($text)
73157 {
73158 $text = self::convert_int_to_char_for_ctype($text);
73159
73160 return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
73161 }
73162
73163
73164
73165
73166
73167
73168
73169
73170
73171
73172 public static function ctype_cntrl($text)
73173 {
73174 $text = self::convert_int_to_char_for_ctype($text);
73175
73176 return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
73177 }
73178
73179
73180
73181
73182
73183
73184
73185
73186
73187
73188 public static function ctype_digit($text)
73189 {
73190 $text = self::convert_int_to_char_for_ctype($text);
73191
73192 return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
73193 }
73194
73195
73196
73197
73198
73199
73200
73201
73202
73203
73204 public static function ctype_graph($text)
73205 {
73206 $text = self::convert_int_to_char_for_ctype($text);
73207
73208 return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
73209 }
73210
73211
73212
73213
73214
73215
73216
73217
73218
73219
73220 public static function ctype_lower($text)
73221 {
73222 $text = self::convert_int_to_char_for_ctype($text);
73223
73224 return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
73225 }
73226
73227
73228
73229
73230
73231
73232
73233
73234
73235
73236 public static function ctype_print($text)
73237 {
73238 $text = self::convert_int_to_char_for_ctype($text);
73239
73240 return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
73241 }
73242
73243
73244
73245
73246
73247
73248
73249
73250
73251
73252 public static function ctype_punct($text)
73253 {
73254 $text = self::convert_int_to_char_for_ctype($text);
73255
73256 return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
73257 }
73258
73259
73260
73261
73262
73263
73264
73265
73266
73267
73268 public static function ctype_space($text)
73269 {
73270 $text = self::convert_int_to_char_for_ctype($text);
73271
73272 return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
73273 }
73274
73275
73276
73277
73278
73279
73280
73281
73282
73283
73284 public static function ctype_upper($text)
73285 {
73286 $text = self::convert_int_to_char_for_ctype($text);
73287
73288 return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
73289 }
73290
73291
73292
73293
73294
73295
73296
73297
73298
73299
73300 public static function ctype_xdigit($text)
73301 {
73302 $text = self::convert_int_to_char_for_ctype($text);
73303
73304 return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
73305 }
73306
73307
73308
73309
73310
73311
73312
73313
73314
73315
73316
73317
73318
73319 private static function convert_int_to_char_for_ctype($int)
73320 {
73321 if (!\is_int($int)) {
73322 return $int;
73323 }
73324
73325 if ($int < -128 || $int > 255) {
73326 return (string) $int;
73327 }
73328
73329 if ($int < 0) {
73330 $int += 256;
73331 }
73332
73333 return \chr($int);
73334 }
73335 }
73336 Copyright (c) 2018-2019 Fabien Potencier
73337
73338 Permission is hereby granted, free of charge, to any person obtaining a copy
73339 of this software and associated documentation files (the "Software"), to deal
73340 in the Software without restriction, including without limitation the rights
73341 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
73342 copies of the Software, and to permit persons to whom the Software is furnished
73343 to do so, subject to the following conditions:
73344
73345 The above copyright notice and this permission notice shall be included in all
73346 copies or substantial portions of the Software.
73347
73348 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73349 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
73350 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73351 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73352 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
73353 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
73354 THE SOFTWARE.
73355 <?php
73356
73357
73358
73359
73360
73361
73362
73363
73364
73365
73366 use Symfony\Polyfill\Ctype as p;
73367
73368 if (!function_exists('ctype_alnum')) {
73369 function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
73370 }
73371 if (!function_exists('ctype_alpha')) {
73372 function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
73373 }
73374 if (!function_exists('ctype_cntrl')) {
73375 function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
73376 }
73377 if (!function_exists('ctype_digit')) {
73378 function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
73379 }
73380 if (!function_exists('ctype_graph')) {
73381 function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
73382 }
73383 if (!function_exists('ctype_lower')) {
73384 function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
73385 }
73386 if (!function_exists('ctype_print')) {
73387 function ctype_print($text) { return p\Ctype::ctype_print($text); }
73388 }
73389 if (!function_exists('ctype_punct')) {
73390 function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
73391 }
73392 if (!function_exists('ctype_space')) {
73393 function ctype_space($text) { return p\Ctype::ctype_space($text); }
73394 }
73395 if (!function_exists('ctype_upper')) {
73396 function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
73397 }
73398 if (!function_exists('ctype_xdigit')) {
73399 function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
73400 }
73401 Copyright (c) 2015-2019 Fabien Potencier
73402
73403 Permission is hereby granted, free of charge, to any person obtaining a copy
73404 of this software and associated documentation files (the "Software"), to deal
73405 in the Software without restriction, including without limitation the rights
73406 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
73407 copies of the Software, and to permit persons to whom the Software is furnished
73408 to do so, subject to the following conditions:
73409
73410 The above copyright notice and this permission notice shall be included in all
73411 copies or substantial portions of the Software.
73412
73413 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73414 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
73415 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73416 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73417 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
73418 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
73419 THE SOFTWARE.
73420 <?php
73421
73422
73423
73424
73425
73426
73427
73428
73429
73430
73431 namespace Symfony\Polyfill\Mbstring;
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 final class Mbstring
73488 {
73489 const MB_CASE_FOLD = PHP_INT_MAX;
73490
73491 private static $encodingList = array('ASCII', 'UTF-8');
73492 private static $language = 'neutral';
73493 private static $internalEncoding = 'UTF-8';
73494 private static $caseFold = array(
73495 array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"),
73496 array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'),
73497 );
73498
73499 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
73500 {
73501 if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
73502 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
73503 } else {
73504 $fromEncoding = self::getEncoding($fromEncoding);
73505 }
73506
73507 $toEncoding = self::getEncoding($toEncoding);
73508
73509 if ('BASE64' === $fromEncoding) {
73510 $s = base64_decode($s);
73511 $fromEncoding = $toEncoding;
73512 }
73513
73514 if ('BASE64' === $toEncoding) {
73515 return base64_encode($s);
73516 }
73517
73518 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
73519 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
73520 $fromEncoding = 'Windows-1252';
73521 }
73522 if ('UTF-8' !== $fromEncoding) {
73523 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
73524 }
73525
73526 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
73527 }
73528
73529 if ('HTML-ENTITIES' === $fromEncoding) {
73530 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
73531 $fromEncoding = 'UTF-8';
73532 }
73533
73534 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
73535 }
73536
73537 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
73538 {
73539 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
73540
73541 $ok = true;
73542 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
73543 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
73544 $ok = false;
73545 }
73546 });
73547
73548 return $ok ? $fromEncoding : false;
73549 }
73550
73551 public static function mb_decode_mimeheader($s)
73552 {
73553 return iconv_mime_decode($s, 2, self::$internalEncoding);
73554 }
73555
73556 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
73557 {
73558 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
73559 }
73560
73561 public static function mb_decode_numericentity($s, $convmap, $encoding = null)
73562 {
73563 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
73564 trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
73565
73566 return null;
73567 }
73568
73569 if (!\is_array($convmap) || !$convmap) {
73570 return false;
73571 }
73572
73573 if (null !== $encoding && !\is_scalar($encoding)) {
73574 trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
73575
73576 return ''; 
73577  }
73578
73579 $s = (string) $s;
73580 if ('' === $s) {
73581 return '';
73582 }
73583
73584 $encoding = self::getEncoding($encoding);
73585
73586 if ('UTF-8' === $encoding) {
73587 $encoding = null;
73588 if (!preg_match('//u', $s)) {
73589 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
73590 }
73591 } else {
73592 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
73593 }
73594
73595 $cnt = floor(\count($convmap) / 4) * 4;
73596
73597 for ($i = 0; $i < $cnt; $i += 4) {
73598
73599  $convmap[$i] += $convmap[$i + 2];
73600 $convmap[$i + 1] += $convmap[$i + 2];
73601 }
73602
73603 $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
73604 $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
73605 for ($i = 0; $i < $cnt; $i += 4) {
73606 if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
73607 return Mbstring::mb_chr($c - $convmap[$i + 2]);
73608 }
73609 }
73610
73611 return $m[0];
73612 }, $s);
73613
73614 if (null === $encoding) {
73615 return $s;
73616 }
73617
73618 return iconv('UTF-8', $encoding.'//IGNORE', $s);
73619 }
73620
73621 public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
73622 {
73623 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
73624 trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING);
73625
73626 return null;
73627 }
73628
73629 if (!\is_array($convmap) || !$convmap) {
73630 return false;
73631 }
73632
73633 if (null !== $encoding && !\is_scalar($encoding)) {
73634 trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING);
73635
73636 return null; 
73637  }
73638
73639 if (null !== $is_hex && !\is_scalar($is_hex)) {
73640 trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING);
73641
73642 return null;
73643 }
73644
73645 $s = (string) $s;
73646 if ('' === $s) {
73647 return '';
73648 }
73649
73650 $encoding = self::getEncoding($encoding);
73651
73652 if ('UTF-8' === $encoding) {
73653 $encoding = null;
73654 if (!preg_match('//u', $s)) {
73655 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
73656 }
73657 } else {
73658 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
73659 }
73660
73661 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
73662
73663 $cnt = floor(\count($convmap) / 4) * 4;
73664 $i = 0;
73665 $len = \strlen($s);
73666 $result = '';
73667
73668 while ($i < $len) {
73669 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
73670 $uchr = substr($s, $i, $ulen);
73671 $i += $ulen;
73672 $c = self::mb_ord($uchr);
73673
73674 for ($j = 0; $j < $cnt; $j += 4) {
73675 if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
73676 $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
73677 $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
73678 continue 2;
73679 }
73680 }
73681 $result .= $uchr;
73682 }
73683
73684 if (null === $encoding) {
73685 return $result;
73686 }
73687
73688 return iconv('UTF-8', $encoding.'//IGNORE', $result);
73689 }
73690
73691 public static function mb_convert_case($s, $mode, $encoding = null)
73692 {
73693 $s = (string) $s;
73694 if ('' === $s) {
73695 return '';
73696 }
73697
73698 $encoding = self::getEncoding($encoding);
73699
73700 if ('UTF-8' === $encoding) {
73701 $encoding = null;
73702 if (!preg_match('//u', $s)) {
73703 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
73704 }
73705 } else {
73706 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
73707 }
73708
73709 if (MB_CASE_TITLE == $mode) {
73710 static $titleRegexp = null;
73711 if (null === $titleRegexp) {
73712 $titleRegexp = self::getData('titleCaseRegexp');
73713 }
73714 $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s);
73715 } else {
73716 if (MB_CASE_UPPER == $mode) {
73717 static $upper = null;
73718 if (null === $upper) {
73719 $upper = self::getData('upperCase');
73720 }
73721 $map = $upper;
73722 } else {
73723 if (self::MB_CASE_FOLD === $mode) {
73724 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
73725 }
73726
73727 static $lower = null;
73728 if (null === $lower) {
73729 $lower = self::getData('lowerCase');
73730 }
73731 $map = $lower;
73732 }
73733
73734 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
73735
73736 $i = 0;
73737 $len = \strlen($s);
73738
73739 while ($i < $len) {
73740 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
73741 $uchr = substr($s, $i, $ulen);
73742 $i += $ulen;
73743
73744 if (isset($map[$uchr])) {
73745 $uchr = $map[$uchr];
73746 $nlen = \strlen($uchr);
73747
73748 if ($nlen == $ulen) {
73749 $nlen = $i;
73750 do {
73751 $s[--$nlen] = $uchr[--$ulen];
73752 } while ($ulen);
73753 } else {
73754 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
73755 $len += $nlen - $ulen;
73756 $i += $nlen - $ulen;
73757 }
73758 }
73759 }
73760 }
73761
73762 if (null === $encoding) {
73763 return $s;
73764 }
73765
73766 return iconv('UTF-8', $encoding.'//IGNORE', $s);
73767 }
73768
73769 public static function mb_internal_encoding($encoding = null)
73770 {
73771 if (null === $encoding) {
73772 return self::$internalEncoding;
73773 }
73774
73775 $encoding = self::getEncoding($encoding);
73776
73777 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
73778 self::$internalEncoding = $encoding;
73779
73780 return true;
73781 }
73782
73783 return false;
73784 }
73785
73786 public static function mb_language($lang = null)
73787 {
73788 if (null === $lang) {
73789 return self::$language;
73790 }
73791
73792 switch ($lang = strtolower($lang)) {
73793 case 'uni':
73794 case 'neutral':
73795 self::$language = $lang;
73796
73797 return true;
73798 }
73799
73800 return false;
73801 }
73802
73803 public static function mb_list_encodings()
73804 {
73805 return array('UTF-8');
73806 }
73807
73808 public static function mb_encoding_aliases($encoding)
73809 {
73810 switch (strtoupper($encoding)) {
73811 case 'UTF8':
73812 case 'UTF-8':
73813 return array('utf8');
73814 }
73815
73816 return false;
73817 }
73818
73819 public static function mb_check_encoding($var = null, $encoding = null)
73820 {
73821 if (null === $encoding) {
73822 if (null === $var) {
73823 return false;
73824 }
73825 $encoding = self::$internalEncoding;
73826 }
73827
73828 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
73829 }
73830
73831 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
73832 {
73833 if (null === $encodingList) {
73834 $encodingList = self::$encodingList;
73835 } else {
73836 if (!\is_array($encodingList)) {
73837 $encodingList = array_map('trim', explode(',', $encodingList));
73838 }
73839 $encodingList = array_map('strtoupper', $encodingList);
73840 }
73841
73842 foreach ($encodingList as $enc) {
73843 switch ($enc) {
73844 case 'ASCII':
73845 if (!preg_match('/[\x80-\xFF]/', $str)) {
73846 return $enc;
73847 }
73848 break;
73849
73850 case 'UTF8':
73851 case 'UTF-8':
73852 if (preg_match('//u', $str)) {
73853 return 'UTF-8';
73854 }
73855 break;
73856
73857 default:
73858 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
73859 return $enc;
73860 }
73861 }
73862 }
73863
73864 return false;
73865 }
73866
73867 public static function mb_detect_order($encodingList = null)
73868 {
73869 if (null === $encodingList) {
73870 return self::$encodingList;
73871 }
73872
73873 if (!\is_array($encodingList)) {
73874 $encodingList = array_map('trim', explode(',', $encodingList));
73875 }
73876 $encodingList = array_map('strtoupper', $encodingList);
73877
73878 foreach ($encodingList as $enc) {
73879 switch ($enc) {
73880 default:
73881 if (strncmp($enc, 'ISO-8859-', 9)) {
73882 return false;
73883 }
73884
73885  case 'ASCII':
73886 case 'UTF8':
73887 case 'UTF-8':
73888 }
73889 }
73890
73891 self::$encodingList = $encodingList;
73892
73893 return true;
73894 }
73895
73896 public static function mb_strlen($s, $encoding = null)
73897 {
73898 $encoding = self::getEncoding($encoding);
73899 if ('CP850' === $encoding || 'ASCII' === $encoding) {
73900 return \strlen($s);
73901 }
73902
73903 return @iconv_strlen($s, $encoding);
73904 }
73905
73906 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
73907 {
73908 $encoding = self::getEncoding($encoding);
73909 if ('CP850' === $encoding || 'ASCII' === $encoding) {
73910 return strpos($haystack, $needle, $offset);
73911 }
73912
73913 $needle = (string) $needle;
73914 if ('' === $needle) {
73915 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
73916
73917 return false;
73918 }
73919
73920 return iconv_strpos($haystack, $needle, $offset, $encoding);
73921 }
73922
73923 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
73924 {
73925 $encoding = self::getEncoding($encoding);
73926 if ('CP850' === $encoding || 'ASCII' === $encoding) {
73927 return strrpos($haystack, $needle, $offset);
73928 }
73929
73930 if ($offset != (int) $offset) {
73931 $offset = 0;
73932 } elseif ($offset = (int) $offset) {
73933 if ($offset < 0) {
73934 if (0 > $offset += self::mb_strlen($needle)) {
73935 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
73936 }
73937 $offset = 0;
73938 } else {
73939 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
73940 }
73941 }
73942
73943 $pos = iconv_strrpos($haystack, $needle, $encoding);
73944
73945 return false !== $pos ? $offset + $pos : false;
73946 }
73947
73948 public static function mb_str_split($string, $split_length = 1, $encoding = null)
73949 {
73950 if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
73951 trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING);
73952
73953 return null;
73954 }
73955
73956 if (1 > $split_length = (int) $split_length) {
73957 trigger_error('The length of each segment must be greater than zero', E_USER_WARNING);
73958
73959 return false;
73960 }
73961
73962 if (null === $encoding) {
73963 $encoding = mb_internal_encoding();
73964 }
73965
73966 if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
73967 $rx = '/(';
73968 while (65535 < $split_length) {
73969 $rx .= '.{65535}';
73970 $split_length -= 65535;
73971 }
73972 $rx .= '.{'.$split_length.'})/us';
73973
73974 return preg_split($rx, $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
73975 }
73976
73977 $result = array();
73978 $length = mb_strlen($string, $encoding);
73979
73980 for ($i = 0; $i < $length; $i += $split_length) {
73981 $result[] = mb_substr($string, $i, $split_length, $encoding);
73982 }
73983
73984 return $result;
73985 }
73986
73987 public static function mb_strtolower($s, $encoding = null)
73988 {
73989 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
73990 }
73991
73992 public static function mb_strtoupper($s, $encoding = null)
73993 {
73994 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
73995 }
73996
73997 public static function mb_substitute_character($c = null)
73998 {
73999 if (0 === strcasecmp($c, 'none')) {
74000 return true;
74001 }
74002
74003 return null !== $c ? false : 'none';
74004 }
74005
74006 public static function mb_substr($s, $start, $length = null, $encoding = null)
74007 {
74008 $encoding = self::getEncoding($encoding);
74009 if ('CP850' === $encoding || 'ASCII' === $encoding) {
74010 return (string) substr($s, $start, null === $length ? 2147483647 : $length);
74011 }
74012
74013 if ($start < 0) {
74014 $start = iconv_strlen($s, $encoding) + $start;
74015 if ($start < 0) {
74016 $start = 0;
74017 }
74018 }
74019
74020 if (null === $length) {
74021 $length = 2147483647;
74022 } elseif ($length < 0) {
74023 $length = iconv_strlen($s, $encoding) + $length - $start;
74024 if ($length < 0) {
74025 return '';
74026 }
74027 }
74028
74029 return (string) iconv_substr($s, $start, $length, $encoding);
74030 }
74031
74032 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
74033 {
74034 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
74035 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
74036
74037 return self::mb_strpos($haystack, $needle, $offset, $encoding);
74038 }
74039
74040 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
74041 {
74042 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
74043
74044 return self::getSubpart($pos, $part, $haystack, $encoding);
74045 }
74046
74047 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
74048 {
74049 $encoding = self::getEncoding($encoding);
74050 if ('CP850' === $encoding || 'ASCII' === $encoding) {
74051 return strrchr($haystack, $needle, $part);
74052 }
74053 $needle = self::mb_substr($needle, 0, 1, $encoding);
74054 $pos = iconv_strrpos($haystack, $needle, $encoding);
74055
74056 return self::getSubpart($pos, $part, $haystack, $encoding);
74057 }
74058
74059 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
74060 {
74061 $needle = self::mb_substr($needle, 0, 1, $encoding);
74062 $pos = self::mb_strripos($haystack, $needle, $encoding);
74063
74064 return self::getSubpart($pos, $part, $haystack, $encoding);
74065 }
74066
74067 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
74068 {
74069 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
74070 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
74071
74072 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
74073 }
74074
74075 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
74076 {
74077 $pos = strpos($haystack, $needle);
74078 if (false === $pos) {
74079 return false;
74080 }
74081 if ($part) {
74082 return substr($haystack, 0, $pos);
74083 }
74084
74085 return substr($haystack, $pos);
74086 }
74087
74088 public static function mb_get_info($type = 'all')
74089 {
74090 $info = array(
74091 'internal_encoding' => self::$internalEncoding,
74092 'http_output' => 'pass',
74093 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
74094 'func_overload' => 0,
74095 'func_overload_list' => 'no overload',
74096 'mail_charset' => 'UTF-8',
74097 'mail_header_encoding' => 'BASE64',
74098 'mail_body_encoding' => 'BASE64',
74099 'illegal_chars' => 0,
74100 'encoding_translation' => 'Off',
74101 'language' => self::$language,
74102 'detect_order' => self::$encodingList,
74103 'substitute_character' => 'none',
74104 'strict_detection' => 'Off',
74105 );
74106
74107 if ('all' === $type) {
74108 return $info;
74109 }
74110 if (isset($info[$type])) {
74111 return $info[$type];
74112 }
74113
74114 return false;
74115 }
74116
74117 public static function mb_http_input($type = '')
74118 {
74119 return false;
74120 }
74121
74122 public static function mb_http_output($encoding = null)
74123 {
74124 return null !== $encoding ? 'pass' === $encoding : 'pass';
74125 }
74126
74127 public static function mb_strwidth($s, $encoding = null)
74128 {
74129 $encoding = self::getEncoding($encoding);
74130
74131 if ('UTF-8' !== $encoding) {
74132 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
74133 }
74134
74135 $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);
74136
74137 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
74138 }
74139
74140 public static function mb_substr_count($haystack, $needle, $encoding = null)
74141 {
74142 return substr_count($haystack, $needle);
74143 }
74144
74145 public static function mb_output_handler($contents, $status)
74146 {
74147 return $contents;
74148 }
74149
74150 public static function mb_chr($code, $encoding = null)
74151 {
74152 if (0x80 > $code %= 0x200000) {
74153 $s = \chr($code);
74154 } elseif (0x800 > $code) {
74155 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
74156 } elseif (0x10000 > $code) {
74157 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
74158 } else {
74159 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
74160 }
74161
74162 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
74163 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
74164 }
74165
74166 return $s;
74167 }
74168
74169 public static function mb_ord($s, $encoding = null)
74170 {
74171 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
74172 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
74173 }
74174
74175 if (1 === \strlen($s)) {
74176 return \ord($s);
74177 }
74178
74179 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
74180 if (0xF0 <= $code) {
74181 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
74182 }
74183 if (0xE0 <= $code) {
74184 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
74185 }
74186 if (0xC0 <= $code) {
74187 return (($code - 0xC0) << 6) + $s[2] - 0x80;
74188 }
74189
74190 return $code;
74191 }
74192
74193 private static function getSubpart($pos, $part, $haystack, $encoding)
74194 {
74195 if (false === $pos) {
74196 return false;
74197 }
74198 if ($part) {
74199 return self::mb_substr($haystack, 0, $pos, $encoding);
74200 }
74201
74202 return self::mb_substr($haystack, $pos, null, $encoding);
74203 }
74204
74205 private static function html_encoding_callback(array $m)
74206 {
74207 $i = 1;
74208 $entities = '';
74209 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
74210
74211 while (isset($m[$i])) {
74212 if (0x80 > $m[$i]) {
74213 $entities .= \chr($m[$i++]);
74214 continue;
74215 }
74216 if (0xF0 <= $m[$i]) {
74217 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
74218 } elseif (0xE0 <= $m[$i]) {
74219 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
74220 } else {
74221 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
74222 }
74223
74224 $entities .= '&#'.$c.';';
74225 }
74226
74227 return $entities;
74228 }
74229
74230 private static function title_case(array $s)
74231 {
74232 return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8');
74233 }
74234
74235 private static function getData($file)
74236 {
74237 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
74238 return require $file;
74239 }
74240
74241 return false;
74242 }
74243
74244 private static function getEncoding($encoding)
74245 {
74246 if (null === $encoding) {
74247 return self::$internalEncoding;
74248 }
74249
74250 if ('UTF-8' === $encoding) {
74251 return 'UTF-8';
74252 }
74253
74254 $encoding = strtoupper($encoding);
74255
74256 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
74257 return 'CP850';
74258 }
74259
74260 if ('UTF8' === $encoding) {
74261 return 'UTF-8';
74262 }
74263
74264 return $encoding;
74265 }
74266 }
74267 <?php
74268
74269 return array(
74270 'A' => 'a',
74271 'B' => 'b',
74272 'C' => 'c',
74273 'D' => 'd',
74274 'E' => 'e',
74275 'F' => 'f',
74276 'G' => 'g',
74277 'H' => 'h',
74278 'I' => 'i',
74279 'J' => 'j',
74280 'K' => 'k',
74281 'L' => 'l',
74282 'M' => 'm',
74283 'N' => 'n',
74284 'O' => 'o',
74285 'P' => 'p',
74286 'Q' => 'q',
74287 'R' => 'r',
74288 'S' => 's',
74289 'T' => 't',
74290 'U' => 'u',
74291 'V' => 'v',
74292 'W' => 'w',
74293 'X' => 'x',
74294 'Y' => 'y',
74295 'Z' => 'z',
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 'İ' => 'i',
74351 'IJ' => 'ij',
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 'DŽ' => 'dž',
74426 'Dž' => 'dž',
74427 'LJ' => 'lj',
74428 'Lj' => 'lj',
74429 'NJ' => 'nj',
74430 'Nj' => 'nj',
74431 'Ǎ' => 'ǎ',
74432 'Ǐ' => 'ǐ',
74433 'Ǒ' => 'ǒ',
74434 'Ǔ' => 'ǔ',
74435 'Ǖ' => 'ǖ',
74436 'Ǘ' => 'ǘ',
74437 'Ǚ' => 'ǚ',
74438 'Ǜ' => 'ǜ',
74439 'Ǟ' => 'ǟ',
74440 'Ǡ' => 'ǡ',
74441 'Ǣ' => 'ǣ',
74442 'Ǥ' => 'ǥ',
74443 'Ǧ' => 'ǧ',
74444 'Ǩ' => 'ǩ',
74445 'Ǫ' => 'ǫ',
74446 'Ǭ' => 'ǭ',
74447 'Ǯ' => 'ǯ',
74448 'DZ' => 'dz',
74449 'Dz' => 'dz',
74450 'Ǵ' => 'ǵ',
74451 'Ƕ' => 'ƕ',
74452 'Ƿ' => 'ƿ',
74453 'Ǹ' => 'ǹ',
74454 'Ǻ' => 'ǻ',
74455 'Ǽ' => 'ǽ',
74456 'Ǿ' => 'ǿ',
74457 'Ȁ' => 'ȁ',
74458 'Ȃ' => 'ȃ',
74459 'Ȅ' => 'ȅ',
74460 'Ȇ' => 'ȇ',
74461 'Ȉ' => 'ȉ',
74462 'Ȋ' => 'ȋ',
74463 'Ȍ' => 'ȍ',
74464 'Ȏ' => 'ȏ',
74465 'Ȑ' => 'ȑ',
74466 'Ȓ' => 'ȓ',
74467 'Ȕ' => 'ȕ',
74468 'Ȗ' => 'ȗ',
74469 'Ș' => 'ș',
74470 'Ț' => 'ț',
74471 'Ȝ' => 'ȝ',
74472 'Ȟ' => 'ȟ',
74473 'Ƞ' => 'ƞ',
74474 'Ȣ' => 'ȣ',
74475 'Ȥ' => 'ȥ',
74476 'Ȧ' => 'ȧ',
74477 'Ȩ' => 'ȩ',
74478 'Ȫ' => 'ȫ',
74479 'Ȭ' => 'ȭ',
74480 'Ȯ' => 'ȯ',
74481 'Ȱ' => 'ȱ',
74482 'Ȳ' => 'ȳ',
74483 'Ⱥ' => 'ⱥ',
74484 'Ȼ' => 'ȼ',
74485 'Ƚ' => 'ƚ',
74486 'Ⱦ' => 'ⱦ',
74487 'Ɂ' => 'ɂ',
74488 'Ƀ' => 'ƀ',
74489 'Ʉ' => 'ʉ',
74490 'Ʌ' => 'ʌ',
74491 'Ɇ' => 'ɇ',
74492 'Ɉ' => 'ɉ',
74493 'Ɋ' => 'ɋ',
74494 'Ɍ' => 'ɍ',
74495 'Ɏ' => 'ɏ',
74496 'Ͱ' => 'ͱ',
74497 'Ͳ' => 'ͳ',
74498 'Ͷ' => 'ͷ',
74499 'Ϳ' => 'ϳ',
74500 'Ά' => 'ά',
74501 'Έ' => 'έ',
74502 'Ή' => 'ή',
74503 'Ί' => 'ί',
74504 'Ό' => 'ό',
74505 'Ύ' => 'ύ',
74506 'Ώ' => 'ώ',
74507 'Α' => 'α',
74508 'Β' => 'β',
74509 'Γ' => 'γ',
74510 'Δ' => 'δ',
74511 'Ε' => 'ε',
74512 'Ζ' => 'ζ',
74513 'Η' => 'η',
74514 'Θ' => 'θ',
74515 'Ι' => 'ι',
74516 'Κ' => 'κ',
74517 'Λ' => 'λ',
74518 'Μ' => 'μ',
74519 'Ν' => 'ν',
74520 'Ξ' => 'ξ',
74521 'Ο' => 'ο',
74522 'Π' => 'π',
74523 'Ρ' => 'ρ',
74524 'Σ' => 'σ',
74525 'Τ' => 'τ',
74526 'Υ' => 'υ',
74527 'Φ' => 'φ',
74528 'Χ' => 'χ',
74529 'Ψ' => 'ψ',
74530 'Ω' => 'ω',
74531 'Ϊ' => 'ϊ',
74532 'Ϋ' => 'ϋ',
74533 'Ϗ' => 'ϗ',
74534 'Ϙ' => 'ϙ',
74535 'Ϛ' => 'ϛ',
74536 'Ϝ' => 'ϝ',
74537 'Ϟ' => 'ϟ',
74538 'Ϡ' => 'ϡ',
74539 'Ϣ' => 'ϣ',
74540 'Ϥ' => 'ϥ',
74541 'Ϧ' => 'ϧ',
74542 'Ϩ' => 'ϩ',
74543 'Ϫ' => 'ϫ',
74544 'Ϭ' => 'ϭ',
74545 'Ϯ' => 'ϯ',
74546 'ϴ' => 'θ',
74547 'Ϸ' => 'ϸ',
74548 'Ϲ' => 'ϲ',
74549 'Ϻ' => 'ϻ',
74550 'Ͻ' => 'ͻ',
74551 'Ͼ' => 'ͼ',
74552 'Ͽ' => 'ͽ',
74553 'Ѐ' => 'ѐ',
74554 'Ё' => 'ё',
74555 'Ђ' => 'ђ',
74556 'Ѓ' => 'ѓ',
74557 'Є' => 'є',
74558 'Ѕ' => 'ѕ',
74559 'І' => 'і',
74560 'Ї' => 'ї',
74561 'Ј' => 'ј',
74562 'Љ' => 'љ',
74563 'Њ' => 'њ',
74564 'Ћ' => 'ћ',
74565 'Ќ' => 'ќ',
74566 'Ѝ' => 'ѝ',
74567 'Ў' => 'ў',
74568 'Џ' => 'џ',
74569 'А' => 'а',
74570 'Б' => 'б',
74571 'В' => 'в',
74572 'Г' => 'г',
74573 'Д' => 'д',
74574 'Е' => 'е',
74575 'Ж' => 'ж',
74576 'З' => 'з',
74577 'И' => 'и',
74578 'Й' => 'й',
74579 'К' => 'к',
74580 'Л' => 'л',
74581 'М' => 'м',
74582 'Н' => 'н',
74583 'О' => 'о',
74584 'П' => 'п',
74585 'Р' => 'р',
74586 'С' => 'с',
74587 'Т' => 'т',
74588 'У' => 'у',
74589 'Ф' => 'ф',
74590 'Х' => 'х',
74591 'Ц' => 'ц',
74592 'Ч' => 'ч',
74593 'Ш' => 'ш',
74594 'Щ' => 'щ',
74595 'Ъ' => 'ъ',
74596 'Ы' => 'ы',
74597 'Ь' => 'ь',
74598 'Э' => 'э',
74599 'Ю' => 'ю',
74600 'Я' => 'я',
74601 'Ѡ' => 'ѡ',
74602 'Ѣ' => 'ѣ',
74603 'Ѥ' => 'ѥ',
74604 'Ѧ' => 'ѧ',
74605 'Ѩ' => 'ѩ',
74606 'Ѫ' => 'ѫ',
74607 'Ѭ' => 'ѭ',
74608 'Ѯ' => 'ѯ',
74609 'Ѱ' => 'ѱ',
74610 'Ѳ' => 'ѳ',
74611 'Ѵ' => 'ѵ',
74612 'Ѷ' => 'ѷ',
74613 'Ѹ' => 'ѹ',
74614 'Ѻ' => 'ѻ',
74615 'Ѽ' => 'ѽ',
74616 'Ѿ' => 'ѿ',
74617 'Ҁ' => 'ҁ',
74618 'Ҋ' => 'ҋ',
74619 'Ҍ' => 'ҍ',
74620 'Ҏ' => 'ҏ',
74621 'Ґ' => 'ґ',
74622 'Ғ' => 'ғ',
74623 'Ҕ' => 'ҕ',
74624 'Җ' => 'җ',
74625 'Ҙ' => 'ҙ',
74626 'Қ' => 'қ',
74627 'Ҝ' => 'ҝ',
74628 'Ҟ' => 'ҟ',
74629 'Ҡ' => 'ҡ',
74630 'Ң' => 'ң',
74631 'Ҥ' => 'ҥ',
74632 'Ҧ' => 'ҧ',
74633 'Ҩ' => 'ҩ',
74634 'Ҫ' => 'ҫ',
74635 'Ҭ' => 'ҭ',
74636 'Ү' => 'ү',
74637 'Ұ' => 'ұ',
74638 'Ҳ' => 'ҳ',
74639 'Ҵ' => 'ҵ',
74640 'Ҷ' => 'ҷ',
74641 'Ҹ' => 'ҹ',
74642 'Һ' => 'һ',
74643 'Ҽ' => 'ҽ',
74644 'Ҿ' => 'ҿ',
74645 'Ӏ' => 'ӏ',
74646 'Ӂ' => 'ӂ',
74647 'Ӄ' => 'ӄ',
74648 'Ӆ' => 'ӆ',
74649 'Ӈ' => 'ӈ',
74650 'Ӊ' => 'ӊ',
74651 'Ӌ' => 'ӌ',
74652 'Ӎ' => 'ӎ',
74653 'Ӑ' => 'ӑ',
74654 'Ӓ' => 'ӓ',
74655 'Ӕ' => 'ӕ',
74656 'Ӗ' => 'ӗ',
74657 'Ә' => 'ә',
74658 'Ӛ' => 'ӛ',
74659 'Ӝ' => 'ӝ',
74660 'Ӟ' => 'ӟ',
74661 'Ӡ' => 'ӡ',
74662 'Ӣ' => 'ӣ',
74663 'Ӥ' => 'ӥ',
74664 'Ӧ' => 'ӧ',
74665 'Ө' => 'ө',
74666 'Ӫ' => 'ӫ',
74667 'Ӭ' => 'ӭ',
74668 'Ӯ' => 'ӯ',
74669 'Ӱ' => 'ӱ',
74670 'Ӳ' => 'ӳ',
74671 'Ӵ' => 'ӵ',
74672 'Ӷ' => 'ӷ',
74673 'Ӹ' => 'ӹ',
74674 'Ӻ' => 'ӻ',
74675 'Ӽ' => 'ӽ',
74676 'Ӿ' => 'ӿ',
74677 'Ԁ' => 'ԁ',
74678 'Ԃ' => 'ԃ',
74679 'Ԅ' => 'ԅ',
74680 'Ԇ' => 'ԇ',
74681 'Ԉ' => 'ԉ',
74682 'Ԋ' => 'ԋ',
74683 'Ԍ' => 'ԍ',
74684 'Ԏ' => 'ԏ',
74685 'Ԑ' => 'ԑ',
74686 'Ԓ' => 'ԓ',
74687 'Ԕ' => 'ԕ',
74688 'Ԗ' => 'ԗ',
74689 'Ԙ' => 'ԙ',
74690 'Ԛ' => 'ԛ',
74691 'Ԝ' => 'ԝ',
74692 'Ԟ' => 'ԟ',
74693 'Ԡ' => 'ԡ',
74694 'Ԣ' => 'ԣ',
74695 'Ԥ' => 'ԥ',
74696 'Ԧ' => 'ԧ',
74697 'Ԩ' => 'ԩ',
74698 'Ԫ' => 'ԫ',
74699 'Ԭ' => 'ԭ',
74700 'Ԯ' => 'ԯ',
74701 'Ա' => 'ա',
74702 'Բ' => 'բ',
74703 'Գ' => 'գ',
74704 'Դ' => 'դ',
74705 'Ե' => 'ե',
74706 'Զ' => 'զ',
74707 'Է' => 'է',
74708 'Ը' => 'ը',
74709 'Թ' => 'թ',
74710 'Ժ' => 'ժ',
74711 'Ի' => 'ի',
74712 'Լ' => 'լ',
74713 'Խ' => 'խ',
74714 'Ծ' => 'ծ',
74715 'Կ' => 'կ',
74716 'Հ' => 'հ',
74717 'Ձ' => 'ձ',
74718 'Ղ' => 'ղ',
74719 'Ճ' => 'ճ',
74720 'Մ' => 'մ',
74721 'Յ' => 'յ',
74722 'Ն' => 'ն',
74723 'Շ' => 'շ',
74724 'Ո' => 'ո',
74725 'Չ' => 'չ',
74726 'Պ' => 'պ',
74727 'Ջ' => 'ջ',
74728 'Ռ' => 'ռ',
74729 'Ս' => 'ս',
74730 'Վ' => 'վ',
74731 'Տ' => 'տ',
74732 'Ր' => 'ր',
74733 'Ց' => 'ց',
74734 'Ւ' => 'ւ',
74735 'Փ' => 'փ',
74736 'Ք' => 'ք',
74737 'Օ' => 'օ',
74738 'Ֆ' => 'ֆ',
74739 'Ⴀ' => 'ⴀ',
74740 'Ⴁ' => 'ⴁ',
74741 'Ⴂ' => 'ⴂ',
74742 'Ⴃ' => 'ⴃ',
74743 'Ⴄ' => 'ⴄ',
74744 'Ⴅ' => 'ⴅ',
74745 'Ⴆ' => 'ⴆ',
74746 'Ⴇ' => 'ⴇ',
74747 'Ⴈ' => 'ⴈ',
74748 'Ⴉ' => 'ⴉ',
74749 'Ⴊ' => 'ⴊ',
74750 'Ⴋ' => 'ⴋ',
74751 'Ⴌ' => 'ⴌ',
74752 'Ⴍ' => 'ⴍ',
74753 'Ⴎ' => 'ⴎ',
74754 'Ⴏ' => 'ⴏ',
74755 'Ⴐ' => 'ⴐ',
74756 'Ⴑ' => 'ⴑ',
74757 'Ⴒ' => 'ⴒ',
74758 'Ⴓ' => 'ⴓ',
74759 'Ⴔ' => 'ⴔ',
74760 'Ⴕ' => 'ⴕ',
74761 'Ⴖ' => 'ⴖ',
74762 'Ⴗ' => 'ⴗ',
74763 'Ⴘ' => 'ⴘ',
74764 'Ⴙ' => 'ⴙ',
74765 'Ⴚ' => 'ⴚ',
74766 'Ⴛ' => 'ⴛ',
74767 'Ⴜ' => 'ⴜ',
74768 'Ⴝ' => 'ⴝ',
74769 'Ⴞ' => 'ⴞ',
74770 'Ⴟ' => 'ⴟ',
74771 'Ⴠ' => 'ⴠ',
74772 'Ⴡ' => 'ⴡ',
74773 'Ⴢ' => 'ⴢ',
74774 'Ⴣ' => 'ⴣ',
74775 'Ⴤ' => 'ⴤ',
74776 'Ⴥ' => 'ⴥ',
74777 'Ⴧ' => 'ⴧ',
74778 'Ⴭ' => 'ⴭ',
74779 'Ḁ' => 'ḁ',
74780 'Ḃ' => 'ḃ',
74781 'Ḅ' => 'ḅ',
74782 'Ḇ' => 'ḇ',
74783 'Ḉ' => 'ḉ',
74784 'Ḋ' => 'ḋ',
74785 'Ḍ' => 'ḍ',
74786 'Ḏ' => 'ḏ',
74787 'Ḑ' => 'ḑ',
74788 'Ḓ' => 'ḓ',
74789 'Ḕ' => 'ḕ',
74790 'Ḗ' => 'ḗ',
74791 'Ḙ' => 'ḙ',
74792 'Ḛ' => 'ḛ',
74793 'Ḝ' => 'ḝ',
74794 'Ḟ' => 'ḟ',
74795 'Ḡ' => 'ḡ',
74796 'Ḣ' => 'ḣ',
74797 'Ḥ' => 'ḥ',
74798 'Ḧ' => 'ḧ',
74799 'Ḩ' => 'ḩ',
74800 'Ḫ' => 'ḫ',
74801 'Ḭ' => 'ḭ',
74802 'Ḯ' => 'ḯ',
74803 'Ḱ' => 'ḱ',
74804 'Ḳ' => 'ḳ',
74805 'Ḵ' => 'ḵ',
74806 'Ḷ' => 'ḷ',
74807 'Ḹ' => 'ḹ',
74808 'Ḻ' => 'ḻ',
74809 'Ḽ' => 'ḽ',
74810 'Ḿ' => 'ḿ',
74811 'Ṁ' => 'ṁ',
74812 'Ṃ' => 'ṃ',
74813 'Ṅ' => 'ṅ',
74814 'Ṇ' => 'ṇ',
74815 'Ṉ' => 'ṉ',
74816 'Ṋ' => 'ṋ',
74817 'Ṍ' => 'ṍ',
74818 'Ṏ' => 'ṏ',
74819 'Ṑ' => 'ṑ',
74820 'Ṓ' => 'ṓ',
74821 'Ṕ' => 'ṕ',
74822 'Ṗ' => 'ṗ',
74823 'Ṙ' => 'ṙ',
74824 'Ṛ' => 'ṛ',
74825 'Ṝ' => 'ṝ',
74826 'Ṟ' => 'ṟ',
74827 'Ṡ' => 'ṡ',
74828 'Ṣ' => 'ṣ',
74829 'Ṥ' => 'ṥ',
74830 'Ṧ' => 'ṧ',
74831 'Ṩ' => 'ṩ',
74832 'Ṫ' => 'ṫ',
74833 'Ṭ' => 'ṭ',
74834 'Ṯ' => 'ṯ',
74835 'Ṱ' => 'ṱ',
74836 'Ṳ' => 'ṳ',
74837 'Ṵ' => 'ṵ',
74838 'Ṷ' => 'ṷ',
74839 'Ṹ' => 'ṹ',
74840 'Ṻ' => 'ṻ',
74841 'Ṽ' => 'ṽ',
74842 'Ṿ' => 'ṿ',
74843 'Ẁ' => 'ẁ',
74844 'Ẃ' => 'ẃ',
74845 'Ẅ' => 'ẅ',
74846 'Ẇ' => 'ẇ',
74847 'Ẉ' => 'ẉ',
74848 'Ẋ' => 'ẋ',
74849 'Ẍ' => 'ẍ',
74850 'Ẏ' => 'ẏ',
74851 'Ẑ' => 'ẑ',
74852 'Ẓ' => 'ẓ',
74853 'Ẕ' => 'ẕ',
74854 'ẞ' => 'ß',
74855 'Ạ' => 'ạ',
74856 'Ả' => 'ả',
74857 'Ấ' => 'ấ',
74858 'Ầ' => 'ầ',
74859 'Ẩ' => 'ẩ',
74860 'Ẫ' => 'ẫ',
74861 'Ậ' => 'ậ',
74862 'Ắ' => 'ắ',
74863 'Ằ' => 'ằ',
74864 'Ẳ' => 'ẳ',
74865 'Ẵ' => 'ẵ',
74866 'Ặ' => 'ặ',
74867 'Ẹ' => 'ẹ',
74868 'Ẻ' => 'ẻ',
74869 'Ẽ' => 'ẽ',
74870 'Ế' => 'ế',
74871 'Ề' => 'ề',
74872 'Ể' => 'ể',
74873 'Ễ' => 'ễ',
74874 'Ệ' => 'ệ',
74875 'Ỉ' => 'ỉ',
74876 'Ị' => 'ị',
74877 'Ọ' => 'ọ',
74878 'Ỏ' => 'ỏ',
74879 'Ố' => 'ố',
74880 'Ồ' => 'ồ',
74881 'Ổ' => 'ổ',
74882 'Ỗ' => 'ỗ',
74883 'Ộ' => 'ộ',
74884 'Ớ' => 'ớ',
74885 'Ờ' => 'ờ',
74886 'Ở' => 'ở',
74887 'Ỡ' => 'ỡ',
74888 'Ợ' => 'ợ',
74889 'Ụ' => 'ụ',
74890 'Ủ' => 'ủ',
74891 'Ứ' => 'ứ',
74892 'Ừ' => 'ừ',
74893 'Ử' => 'ử',
74894 'Ữ' => 'ữ',
74895 'Ự' => 'ự',
74896 'Ỳ' => 'ỳ',
74897 'Ỵ' => 'ỵ',
74898 'Ỷ' => 'ỷ',
74899 'Ỹ' => 'ỹ',
74900 'Ỻ' => 'ỻ',
74901 'Ỽ' => 'ỽ',
74902 'Ỿ' => 'ỿ',
74903 'Ἀ' => 'ἀ',
74904 'Ἁ' => 'ἁ',
74905 'Ἂ' => 'ἂ',
74906 'Ἃ' => 'ἃ',
74907 'Ἄ' => 'ἄ',
74908 'Ἅ' => 'ἅ',
74909 'Ἆ' => 'ἆ',
74910 'Ἇ' => 'ἇ',
74911 'Ἐ' => 'ἐ',
74912 'Ἑ' => 'ἑ',
74913 'Ἒ' => 'ἒ',
74914 'Ἓ' => 'ἓ',
74915 'Ἔ' => 'ἔ',
74916 'Ἕ' => 'ἕ',
74917 'Ἠ' => 'ἠ',
74918 'Ἡ' => 'ἡ',
74919 'Ἢ' => 'ἢ',
74920 'Ἣ' => 'ἣ',
74921 'Ἤ' => 'ἤ',
74922 'Ἥ' => 'ἥ',
74923 'Ἦ' => 'ἦ',
74924 'Ἧ' => 'ἧ',
74925 'Ἰ' => 'ἰ',
74926 'Ἱ' => 'ἱ',
74927 'Ἲ' => 'ἲ',
74928 'Ἳ' => 'ἳ',
74929 'Ἴ' => 'ἴ',
74930 'Ἵ' => 'ἵ',
74931 'Ἶ' => 'ἶ',
74932 'Ἷ' => 'ἷ',
74933 'Ὀ' => 'ὀ',
74934 'Ὁ' => 'ὁ',
74935 'Ὂ' => 'ὂ',
74936 'Ὃ' => 'ὃ',
74937 'Ὄ' => 'ὄ',
74938 'Ὅ' => 'ὅ',
74939 'Ὑ' => 'ὑ',
74940 'Ὓ' => 'ὓ',
74941 'Ὕ' => 'ὕ',
74942 'Ὗ' => 'ὗ',
74943 'Ὠ' => 'ὠ',
74944 'Ὡ' => 'ὡ',
74945 'Ὢ' => 'ὢ',
74946 'Ὣ' => 'ὣ',
74947 'Ὤ' => 'ὤ',
74948 'Ὥ' => 'ὥ',
74949 'Ὦ' => 'ὦ',
74950 'Ὧ' => 'ὧ',
74951 'ᾈ' => 'ᾀ',
74952 'ᾉ' => 'ᾁ',
74953 'ᾊ' => 'ᾂ',
74954 'ᾋ' => 'ᾃ',
74955 'ᾌ' => 'ᾄ',
74956 'ᾍ' => 'ᾅ',
74957 'ᾎ' => 'ᾆ',
74958 'ᾏ' => 'ᾇ',
74959 'ᾘ' => 'ᾐ',
74960 'ᾙ' => 'ᾑ',
74961 'ᾚ' => 'ᾒ',
74962 'ᾛ' => 'ᾓ',
74963 'ᾜ' => 'ᾔ',
74964 'ᾝ' => 'ᾕ',
74965 'ᾞ' => 'ᾖ',
74966 'ᾟ' => 'ᾗ',
74967 'ᾨ' => 'ᾠ',
74968 'ᾩ' => 'ᾡ',
74969 'ᾪ' => 'ᾢ',
74970 'ᾫ' => 'ᾣ',
74971 'ᾬ' => 'ᾤ',
74972 'ᾭ' => 'ᾥ',
74973 'ᾮ' => 'ᾦ',
74974 'ᾯ' => 'ᾧ',
74975 'Ᾰ' => 'ᾰ',
74976 'Ᾱ' => 'ᾱ',
74977 'Ὰ' => 'ὰ',
74978 'Ά' => 'ά',
74979 'ᾼ' => 'ᾳ',
74980 'Ὲ' => 'ὲ',
74981 'Έ' => 'έ',
74982 'Ὴ' => 'ὴ',
74983 'Ή' => 'ή',
74984 'ῌ' => 'ῃ',
74985 'Ῐ' => 'ῐ',
74986 'Ῑ' => 'ῑ',
74987 'Ὶ' => 'ὶ',
74988 'Ί' => 'ί',
74989 'Ῠ' => 'ῠ',
74990 'Ῡ' => 'ῡ',
74991 'Ὺ' => 'ὺ',
74992 'Ύ' => 'ύ',
74993 'Ῥ' => 'ῥ',
74994 'Ὸ' => 'ὸ',
74995 'Ό' => 'ό',
74996 'Ὼ' => 'ὼ',
74997 'Ώ' => 'ώ',
74998 'ῼ' => 'ῳ',
74999 'Ω' => 'ω',
75000 'K' => 'k',
75001 'Å' => 'å',
75002 'Ⅎ' => 'ⅎ',
75003 'Ⅰ' => 'ⅰ',
75004 'Ⅱ' => 'ⅱ',
75005 'Ⅲ' => 'ⅲ',
75006 'Ⅳ' => 'ⅳ',
75007 'Ⅴ' => 'ⅴ',
75008 'Ⅵ' => 'ⅵ',
75009 'Ⅶ' => 'ⅶ',
75010 'Ⅷ' => 'ⅷ',
75011 'Ⅸ' => 'ⅸ',
75012 'Ⅹ' => 'ⅹ',
75013 'Ⅺ' => 'ⅺ',
75014 'Ⅻ' => 'ⅻ',
75015 'Ⅼ' => 'ⅼ',
75016 'Ⅽ' => 'ⅽ',
75017 'Ⅾ' => 'ⅾ',
75018 'Ⅿ' => 'ⅿ',
75019 'Ↄ' => 'ↄ',
75020 'Ⓐ' => 'ⓐ',
75021 'Ⓑ' => 'ⓑ',
75022 'Ⓒ' => 'ⓒ',
75023 'Ⓓ' => 'ⓓ',
75024 'Ⓔ' => 'ⓔ',
75025 'Ⓕ' => 'ⓕ',
75026 'Ⓖ' => 'ⓖ',
75027 'Ⓗ' => 'ⓗ',
75028 'Ⓘ' => 'ⓘ',
75029 'Ⓙ' => 'ⓙ',
75030 'Ⓚ' => 'ⓚ',
75031 'Ⓛ' => 'ⓛ',
75032 'Ⓜ' => 'ⓜ',
75033 'Ⓝ' => 'ⓝ',
75034 'Ⓞ' => 'ⓞ',
75035 'Ⓟ' => 'ⓟ',
75036 'Ⓠ' => 'ⓠ',
75037 'Ⓡ' => 'ⓡ',
75038 'Ⓢ' => 'ⓢ',
75039 'Ⓣ' => 'ⓣ',
75040 'Ⓤ' => 'ⓤ',
75041 'Ⓥ' => 'ⓥ',
75042 'Ⓦ' => 'ⓦ',
75043 'Ⓧ' => 'ⓧ',
75044 'Ⓨ' => 'ⓨ',
75045 'Ⓩ' => 'ⓩ',
75046 'Ⰰ' => 'ⰰ',
75047 'Ⰱ' => 'ⰱ',
75048 'Ⰲ' => 'ⰲ',
75049 'Ⰳ' => 'ⰳ',
75050 'Ⰴ' => 'ⰴ',
75051 'Ⰵ' => 'ⰵ',
75052 'Ⰶ' => 'ⰶ',
75053 'Ⰷ' => 'ⰷ',
75054 'Ⰸ' => 'ⰸ',
75055 'Ⰹ' => 'ⰹ',
75056 'Ⰺ' => 'ⰺ',
75057 'Ⰻ' => 'ⰻ',
75058 'Ⰼ' => 'ⰼ',
75059 'Ⰽ' => 'ⰽ',
75060 'Ⰾ' => 'ⰾ',
75061 'Ⰿ' => 'ⰿ',
75062 'Ⱀ' => 'ⱀ',
75063 'Ⱁ' => 'ⱁ',
75064 'Ⱂ' => 'ⱂ',
75065 'Ⱃ' => 'ⱃ',
75066 'Ⱄ' => 'ⱄ',
75067 'Ⱅ' => 'ⱅ',
75068 'Ⱆ' => 'ⱆ',
75069 'Ⱇ' => 'ⱇ',
75070 'Ⱈ' => 'ⱈ',
75071 'Ⱉ' => 'ⱉ',
75072 'Ⱊ' => 'ⱊ',
75073 'Ⱋ' => 'ⱋ',
75074 'Ⱌ' => 'ⱌ',
75075 'Ⱍ' => 'ⱍ',
75076 'Ⱎ' => 'ⱎ',
75077 'Ⱏ' => 'ⱏ',
75078 'Ⱐ' => 'ⱐ',
75079 'Ⱑ' => 'ⱑ',
75080 'Ⱒ' => 'ⱒ',
75081 'Ⱓ' => 'ⱓ',
75082 'Ⱔ' => 'ⱔ',
75083 'Ⱕ' => 'ⱕ',
75084 'Ⱖ' => 'ⱖ',
75085 'Ⱗ' => 'ⱗ',
75086 'Ⱘ' => 'ⱘ',
75087 'Ⱙ' => 'ⱙ',
75088 'Ⱚ' => 'ⱚ',
75089 'Ⱛ' => 'ⱛ',
75090 'Ⱜ' => 'ⱜ',
75091 'Ⱝ' => 'ⱝ',
75092 'Ⱞ' => 'ⱞ',
75093 'Ⱡ' => 'ⱡ',
75094 'Ɫ' => 'ɫ',
75095 'Ᵽ' => 'ᵽ',
75096 'Ɽ' => 'ɽ',
75097 'Ⱨ' => 'ⱨ',
75098 'Ⱪ' => 'ⱪ',
75099 'Ⱬ' => 'ⱬ',
75100 'Ɑ' => 'ɑ',
75101 'Ɱ' => 'ɱ',
75102 'Ɐ' => 'ɐ',
75103 'Ɒ' => 'ɒ',
75104 'Ⱳ' => 'ⱳ',
75105 'Ⱶ' => 'ⱶ',
75106 'Ȿ' => 'ȿ',
75107 'Ɀ' => 'ɀ',
75108 'Ⲁ' => 'ⲁ',
75109 'Ⲃ' => 'ⲃ',
75110 'Ⲅ' => 'ⲅ',
75111 'Ⲇ' => 'ⲇ',
75112 'Ⲉ' => 'ⲉ',
75113 'Ⲋ' => 'ⲋ',
75114 'Ⲍ' => 'ⲍ',
75115 'Ⲏ' => 'ⲏ',
75116 'Ⲑ' => 'ⲑ',
75117 'Ⲓ' => 'ⲓ',
75118 'Ⲕ' => 'ⲕ',
75119 'Ⲗ' => 'ⲗ',
75120 'Ⲙ' => 'ⲙ',
75121 'Ⲛ' => 'ⲛ',
75122 'Ⲝ' => 'ⲝ',
75123 'Ⲟ' => 'ⲟ',
75124 'Ⲡ' => 'ⲡ',
75125 'Ⲣ' => 'ⲣ',
75126 'Ⲥ' => 'ⲥ',
75127 'Ⲧ' => 'ⲧ',
75128 'Ⲩ' => 'ⲩ',
75129 'Ⲫ' => 'ⲫ',
75130 'Ⲭ' => 'ⲭ',
75131 'Ⲯ' => 'ⲯ',
75132 'Ⲱ' => 'ⲱ',
75133 'Ⲳ' => 'ⲳ',
75134 'Ⲵ' => 'ⲵ',
75135 'Ⲷ' => 'ⲷ',
75136 'Ⲹ' => 'ⲹ',
75137 'Ⲻ' => 'ⲻ',
75138 'Ⲽ' => 'ⲽ',
75139 'Ⲿ' => 'ⲿ',
75140 'Ⳁ' => 'ⳁ',
75141 'Ⳃ' => 'ⳃ',
75142 'Ⳅ' => 'ⳅ',
75143 'Ⳇ' => 'ⳇ',
75144 'Ⳉ' => 'ⳉ',
75145 'Ⳋ' => 'ⳋ',
75146 'Ⳍ' => 'ⳍ',
75147 'Ⳏ' => 'ⳏ',
75148 'Ⳑ' => 'ⳑ',
75149 'Ⳓ' => 'ⳓ',
75150 'Ⳕ' => 'ⳕ',
75151 'Ⳗ' => 'ⳗ',
75152 'Ⳙ' => 'ⳙ',
75153 'Ⳛ' => 'ⳛ',
75154 'Ⳝ' => 'ⳝ',
75155 'Ⳟ' => 'ⳟ',
75156 'Ⳡ' => 'ⳡ',
75157 'Ⳣ' => 'ⳣ',
75158 'Ⳬ' => 'ⳬ',
75159 'Ⳮ' => 'ⳮ',
75160 'Ⳳ' => 'ⳳ',
75161 'Ꙁ' => 'ꙁ',
75162 'Ꙃ' => 'ꙃ',
75163 'Ꙅ' => 'ꙅ',
75164 'Ꙇ' => 'ꙇ',
75165 'Ꙉ' => 'ꙉ',
75166 'Ꙋ' => 'ꙋ',
75167 'Ꙍ' => 'ꙍ',
75168 'Ꙏ' => 'ꙏ',
75169 'Ꙑ' => 'ꙑ',
75170 'Ꙓ' => 'ꙓ',
75171 'Ꙕ' => 'ꙕ',
75172 'Ꙗ' => 'ꙗ',
75173 'Ꙙ' => 'ꙙ',
75174 'Ꙛ' => 'ꙛ',
75175 'Ꙝ' => 'ꙝ',
75176 'Ꙟ' => 'ꙟ',
75177 'Ꙡ' => 'ꙡ',
75178 'Ꙣ' => 'ꙣ',
75179 'Ꙥ' => 'ꙥ',
75180 'Ꙧ' => 'ꙧ',
75181 'Ꙩ' => 'ꙩ',
75182 'Ꙫ' => 'ꙫ',
75183 'Ꙭ' => 'ꙭ',
75184 'Ꚁ' => 'ꚁ',
75185 'Ꚃ' => 'ꚃ',
75186 'Ꚅ' => 'ꚅ',
75187 'Ꚇ' => 'ꚇ',
75188 'Ꚉ' => 'ꚉ',
75189 'Ꚋ' => 'ꚋ',
75190 'Ꚍ' => 'ꚍ',
75191 'Ꚏ' => 'ꚏ',
75192 'Ꚑ' => 'ꚑ',
75193 'Ꚓ' => 'ꚓ',
75194 'Ꚕ' => 'ꚕ',
75195 'Ꚗ' => 'ꚗ',
75196 'Ꚙ' => 'ꚙ',
75197 'Ꚛ' => 'ꚛ',
75198 'Ꜣ' => 'ꜣ',
75199 'Ꜥ' => 'ꜥ',
75200 'Ꜧ' => 'ꜧ',
75201 'Ꜩ' => 'ꜩ',
75202 'Ꜫ' => 'ꜫ',
75203 'Ꜭ' => 'ꜭ',
75204 'Ꜯ' => 'ꜯ',
75205 'Ꜳ' => 'ꜳ',
75206 'Ꜵ' => 'ꜵ',
75207 'Ꜷ' => 'ꜷ',
75208 'Ꜹ' => 'ꜹ',
75209 'Ꜻ' => 'ꜻ',
75210 'Ꜽ' => 'ꜽ',
75211 'Ꜿ' => 'ꜿ',
75212 'Ꝁ' => 'ꝁ',
75213 'Ꝃ' => 'ꝃ',
75214 'Ꝅ' => 'ꝅ',
75215 'Ꝇ' => 'ꝇ',
75216 'Ꝉ' => 'ꝉ',
75217 'Ꝋ' => 'ꝋ',
75218 'Ꝍ' => 'ꝍ',
75219 'Ꝏ' => 'ꝏ',
75220 'Ꝑ' => 'ꝑ',
75221 'Ꝓ' => 'ꝓ',
75222 'Ꝕ' => 'ꝕ',
75223 'Ꝗ' => 'ꝗ',
75224 'Ꝙ' => 'ꝙ',
75225 'Ꝛ' => 'ꝛ',
75226 'Ꝝ' => 'ꝝ',
75227 'Ꝟ' => 'ꝟ',
75228 'Ꝡ' => 'ꝡ',
75229 'Ꝣ' => 'ꝣ',
75230 'Ꝥ' => 'ꝥ',
75231 'Ꝧ' => 'ꝧ',
75232 'Ꝩ' => 'ꝩ',
75233 'Ꝫ' => 'ꝫ',
75234 'Ꝭ' => 'ꝭ',
75235 'Ꝯ' => 'ꝯ',
75236 'Ꝺ' => 'ꝺ',
75237 'Ꝼ' => 'ꝼ',
75238 'Ᵹ' => 'ᵹ',
75239 'Ꝿ' => 'ꝿ',
75240 'Ꞁ' => 'ꞁ',
75241 'Ꞃ' => 'ꞃ',
75242 'Ꞅ' => 'ꞅ',
75243 'Ꞇ' => 'ꞇ',
75244 'Ꞌ' => 'ꞌ',
75245 'Ɥ' => 'ɥ',
75246 'Ꞑ' => 'ꞑ',
75247 'Ꞓ' => 'ꞓ',
75248 'Ꞗ' => 'ꞗ',
75249 'Ꞙ' => 'ꞙ',
75250 'Ꞛ' => 'ꞛ',
75251 'Ꞝ' => 'ꞝ',
75252 'Ꞟ' => 'ꞟ',
75253 'Ꞡ' => 'ꞡ',
75254 'Ꞣ' => 'ꞣ',
75255 'Ꞥ' => 'ꞥ',
75256 'Ꞧ' => 'ꞧ',
75257 'Ꞩ' => 'ꞩ',
75258 'Ɦ' => 'ɦ',
75259 'Ɜ' => 'ɜ',
75260 'Ɡ' => 'ɡ',
75261 'Ɬ' => 'ɬ',
75262 'Ʞ' => 'ʞ',
75263 'Ʇ' => 'ʇ',
75264 'A' => 'a',
75265 'B' => 'b',
75266 'C' => 'c',
75267 'D' => 'd',
75268 'E' => 'e',
75269 'F' => 'f',
75270 'G' => 'g',
75271 'H' => 'h',
75272 'I' => 'i',
75273 'J' => 'j',
75274 'K' => 'k',
75275 'L' => 'l',
75276 'M' => 'm',
75277 'N' => 'n',
75278 'O' => 'o',
75279 'P' => 'p',
75280 'Q' => 'q',
75281 'R' => 'r',
75282 'S' => 's',
75283 'T' => 't',
75284 'U' => 'u',
75285 'V' => 'v',
75286 'W' => 'w',
75287 'X' => 'x',
75288 'Y' => 'y',
75289 'Z' => 'z',
75290 '𐐀' => '𐐨',
75291 '𐐁' => '𐐩',
75292 '𐐂' => '𐐪',
75293 '𐐃' => '𐐫',
75294 '𐐄' => '𐐬',
75295 '𐐅' => '𐐭',
75296 '𐐆' => '𐐮',
75297 '𐐇' => '𐐯',
75298 '𐐈' => '𐐰',
75299 '𐐉' => '𐐱',
75300 '𐐊' => '𐐲',
75301 '𐐋' => '𐐳',
75302 '𐐌' => '𐐴',
75303 '𐐍' => '𐐵',
75304 '𐐎' => '𐐶',
75305 '𐐏' => '𐐷',
75306 '𐐐' => '𐐸',
75307 '𐐑' => '𐐹',
75308 '𐐒' => '𐐺',
75309 '𐐓' => '𐐻',
75310 '𐐔' => '𐐼',
75311 '𐐕' => '𐐽',
75312 '𐐖' => '𐐾',
75313 '𐐗' => '𐐿',
75314 '𐐘' => '𐑀',
75315 '𐐙' => '𐑁',
75316 '𐐚' => '𐑂',
75317 '𐐛' => '𐑃',
75318 '𐐜' => '𐑄',
75319 '𐐝' => '𐑅',
75320 '𐐞' => '𐑆',
75321 '𐐟' => '𐑇',
75322 '𐐠' => '𐑈',
75323 '𐐡' => '𐑉',
75324 '𐐢' => '𐑊',
75325 '𐐣' => '𐑋',
75326 '𐐤' => '𐑌',
75327 '𐐥' => '𐑍',
75328 '𐐦' => '𐑎',
75329 '𐐧' => '𐑏',
75330 '𑢠' => '𑣀',
75331 '𑢡' => '𑣁',
75332 '𑢢' => '𑣂',
75333 '𑢣' => '𑣃',
75334 '𑢤' => '𑣄',
75335 '𑢥' => '𑣅',
75336 '𑢦' => '𑣆',
75337 '𑢧' => '𑣇',
75338 '𑢨' => '𑣈',
75339 '𑢩' => '𑣉',
75340 '𑢪' => '𑣊',
75341 '𑢫' => '𑣋',
75342 '𑢬' => '𑣌',
75343 '𑢭' => '𑣍',
75344 '𑢮' => '𑣎',
75345 '𑢯' => '𑣏',
75346 '𑢰' => '𑣐',
75347 '𑢱' => '𑣑',
75348 '𑢲' => '𑣒',
75349 '𑢳' => '𑣓',
75350 '𑢴' => '𑣔',
75351 '𑢵' => '𑣕',
75352 '𑢶' => '𑣖',
75353 '𑢷' => '𑣗',
75354 '𑢸' => '𑣘',
75355 '𑢹' => '𑣙',
75356 '𑢺' => '𑣚',
75357 '𑢻' => '𑣛',
75358 '𑢼' => '𑣜',
75359 '𑢽' => '𑣝',
75360 '𑢾' => '𑣞',
75361 '𑢿' => '𑣟',
75362 );
75363 <?php
75364
75365
75366
75367 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';
75368 <?php
75369
75370 return array(
75371 'a' => 'A',
75372 'b' => 'B',
75373 'c' => 'C',
75374 'd' => 'D',
75375 'e' => 'E',
75376 'f' => 'F',
75377 'g' => 'G',
75378 'h' => 'H',
75379 'i' => 'I',
75380 'j' => 'J',
75381 'k' => 'K',
75382 'l' => 'L',
75383 'm' => 'M',
75384 'n' => 'N',
75385 'o' => 'O',
75386 'p' => 'P',
75387 'q' => 'Q',
75388 'r' => 'R',
75389 's' => 'S',
75390 't' => 'T',
75391 'u' => 'U',
75392 'v' => 'V',
75393 'w' => 'W',
75394 'x' => 'X',
75395 'y' => 'Y',
75396 'z' => 'Z',
75397 'µ' => 'Μ',
75398 'à' => 'À',
75399 'á' => 'Á',
75400 'â' => 'Â',
75401 'ã' => 'Ã',
75402 'ä' => 'Ä',
75403 'å' => 'Å',
75404 'æ' => 'Æ',
75405 'ç' => 'Ç',
75406 'è' => 'È',
75407 'é' => 'É',
75408 'ê' => 'Ê',
75409 'ë' => 'Ë',
75410 'ì' => 'Ì',
75411 'í' => 'Í',
75412 'î' => 'Î',
75413 'ï' => 'Ï',
75414 'ð' => 'Ð',
75415 'ñ' => 'Ñ',
75416 'ò' => 'Ò',
75417 'ó' => 'Ó',
75418 'ô' => 'Ô',
75419 'õ' => 'Õ',
75420 'ö' => 'Ö',
75421 'ø' => 'Ø',
75422 'ù' => 'Ù',
75423 'ú' => 'Ú',
75424 'û' => 'Û',
75425 'ü' => 'Ü',
75426 'ý' => 'Ý',
75427 'þ' => 'Þ',
75428 'ÿ' => 'Ÿ',
75429 'ā' => 'Ā',
75430 'ă' => 'Ă',
75431 'ą' => 'Ą',
75432 'ć' => 'Ć',
75433 'ĉ' => 'Ĉ',
75434 'ċ' => 'Ċ',
75435 'č' => 'Č',
75436 'ď' => 'Ď',
75437 'đ' => 'Đ',
75438 'ē' => 'Ē',
75439 'ĕ' => 'Ĕ',
75440 'ė' => 'Ė',
75441 'ę' => 'Ę',
75442 'ě' => 'Ě',
75443 'ĝ' => 'Ĝ',
75444 'ğ' => 'Ğ',
75445 'ġ' => 'Ġ',
75446 'ģ' => 'Ģ',
75447 'ĥ' => 'Ĥ',
75448 'ħ' => 'Ħ',
75449 'ĩ' => 'Ĩ',
75450 'ī' => 'Ī',
75451 'ĭ' => 'Ĭ',
75452 'į' => 'Į',
75453 'ı' => 'I',
75454 'ij' => 'IJ',
75455 'ĵ' => 'Ĵ',
75456 'ķ' => 'Ķ',
75457 'ĺ' => 'Ĺ',
75458 'ļ' => 'Ļ',
75459 'ľ' => 'Ľ',
75460 'ŀ' => 'Ŀ',
75461 'ł' => 'Ł',
75462 'ń' => 'Ń',
75463 'ņ' => 'Ņ',
75464 'ň' => 'Ň',
75465 'ŋ' => 'Ŋ',
75466 'ō' => 'Ō',
75467 'ŏ' => 'Ŏ',
75468 'ő' => 'Ő',
75469 'œ' => 'Œ',
75470 'ŕ' => 'Ŕ',
75471 'ŗ' => 'Ŗ',
75472 'ř' => 'Ř',
75473 'ś' => 'Ś',
75474 'ŝ' => 'Ŝ',
75475 'ş' => 'Ş',
75476 'š' => 'Š',
75477 'ţ' => 'Ţ',
75478 'ť' => 'Ť',
75479 'ŧ' => 'Ŧ',
75480 'ũ' => 'Ũ',
75481 'ū' => 'Ū',
75482 'ŭ' => 'Ŭ',
75483 'ů' => 'Ů',
75484 'ű' => 'Ű',
75485 'ų' => 'Ų',
75486 'ŵ' => 'Ŵ',
75487 'ŷ' => 'Ŷ',
75488 'ź' => 'Ź',
75489 'ż' => 'Ż',
75490 'ž' => 'Ž',
75491 'ſ' => 'S',
75492 'ƀ' => 'Ƀ',
75493 'ƃ' => 'Ƃ',
75494 'ƅ' => 'Ƅ',
75495 'ƈ' => 'Ƈ',
75496 'ƌ' => 'Ƌ',
75497 'ƒ' => 'Ƒ',
75498 'ƕ' => 'Ƕ',
75499 'ƙ' => 'Ƙ',
75500 'ƚ' => 'Ƚ',
75501 'ƞ' => 'Ƞ',
75502 'ơ' => 'Ơ',
75503 'ƣ' => 'Ƣ',
75504 'ƥ' => 'Ƥ',
75505 'ƨ' => 'Ƨ',
75506 'ƭ' => 'Ƭ',
75507 'ư' => 'Ư',
75508 'ƴ' => 'Ƴ',
75509 'ƶ' => 'Ƶ',
75510 'ƹ' => 'Ƹ',
75511 'ƽ' => 'Ƽ',
75512 'ƿ' => 'Ƿ',
75513 'Dž' => 'DŽ',
75514 'dž' => 'DŽ',
75515 'Lj' => 'LJ',
75516 'lj' => 'LJ',
75517 'Nj' => 'NJ',
75518 'nj' => 'NJ',
75519 'ǎ' => 'Ǎ',
75520 'ǐ' => 'Ǐ',
75521 'ǒ' => 'Ǒ',
75522 'ǔ' => 'Ǔ',
75523 'ǖ' => 'Ǖ',
75524 'ǘ' => 'Ǘ',
75525 'ǚ' => 'Ǚ',
75526 'ǜ' => 'Ǜ',
75527 'ǝ' => 'Ǝ',
75528 'ǟ' => 'Ǟ',
75529 'ǡ' => 'Ǡ',
75530 'ǣ' => 'Ǣ',
75531 'ǥ' => 'Ǥ',
75532 'ǧ' => 'Ǧ',
75533 'ǩ' => 'Ǩ',
75534 'ǫ' => 'Ǫ',
75535 'ǭ' => 'Ǭ',
75536 'ǯ' => 'Ǯ',
75537 'Dz' => 'DZ',
75538 'dz' => 'DZ',
75539 'ǵ' => 'Ǵ',
75540 'ǹ' => 'Ǹ',
75541 'ǻ' => 'Ǻ',
75542 'ǽ' => 'Ǽ',
75543 'ǿ' => 'Ǿ',
75544 'ȁ' => 'Ȁ',
75545 'ȃ' => 'Ȃ',
75546 'ȅ' => 'Ȅ',
75547 'ȇ' => 'Ȇ',
75548 'ȉ' => 'Ȉ',
75549 'ȋ' => 'Ȋ',
75550 'ȍ' => 'Ȍ',
75551 'ȏ' => 'Ȏ',
75552 'ȑ' => 'Ȑ',
75553 'ȓ' => 'Ȓ',
75554 'ȕ' => 'Ȕ',
75555 'ȗ' => 'Ȗ',
75556 'ș' => 'Ș',
75557 'ț' => 'Ț',
75558 'ȝ' => 'Ȝ',
75559 'ȟ' => 'Ȟ',
75560 'ȣ' => 'Ȣ',
75561 'ȥ' => 'Ȥ',
75562 'ȧ' => 'Ȧ',
75563 'ȩ' => 'Ȩ',
75564 'ȫ' => 'Ȫ',
75565 'ȭ' => 'Ȭ',
75566 'ȯ' => 'Ȯ',
75567 'ȱ' => 'Ȱ',
75568 'ȳ' => 'Ȳ',
75569 'ȼ' => 'Ȼ',
75570 'ȿ' => 'Ȿ',
75571 'ɀ' => 'Ɀ',
75572 'ɂ' => 'Ɂ',
75573 'ɇ' => 'Ɇ',
75574 'ɉ' => 'Ɉ',
75575 'ɋ' => 'Ɋ',
75576 'ɍ' => 'Ɍ',
75577 'ɏ' => 'Ɏ',
75578 'ɐ' => 'Ɐ',
75579 'ɑ' => 'Ɑ',
75580 'ɒ' => 'Ɒ',
75581 'ɓ' => 'Ɓ',
75582 'ɔ' => 'Ɔ',
75583 'ɖ' => 'Ɖ',
75584 'ɗ' => 'Ɗ',
75585 'ə' => 'Ə',
75586 'ɛ' => 'Ɛ',
75587 'ɜ' => 'Ɜ',
75588 'ɠ' => 'Ɠ',
75589 'ɡ' => 'Ɡ',
75590 'ɣ' => 'Ɣ',
75591 'ɥ' => 'Ɥ',
75592 'ɦ' => 'Ɦ',
75593 'ɨ' => 'Ɨ',
75594 'ɩ' => 'Ɩ',
75595 'ɫ' => 'Ɫ',
75596 'ɬ' => 'Ɬ',
75597 'ɯ' => 'Ɯ',
75598 'ɱ' => 'Ɱ',
75599 'ɲ' => 'Ɲ',
75600 'ɵ' => 'Ɵ',
75601 'ɽ' => 'Ɽ',
75602 'ʀ' => 'Ʀ',
75603 'ʃ' => 'Ʃ',
75604 'ʇ' => 'Ʇ',
75605 'ʈ' => 'Ʈ',
75606 'ʉ' => 'Ʉ',
75607 'ʊ' => 'Ʊ',
75608 'ʋ' => 'Ʋ',
75609 'ʌ' => 'Ʌ',
75610 'ʒ' => 'Ʒ',
75611 'ʞ' => 'Ʞ',
75612 'ͅ' => 'Ι',
75613 'ͱ' => 'Ͱ',
75614 'ͳ' => 'Ͳ',
75615 'ͷ' => 'Ͷ',
75616 'ͻ' => 'Ͻ',
75617 'ͼ' => 'Ͼ',
75618 'ͽ' => 'Ͽ',
75619 'ά' => 'Ά',
75620 'έ' => 'Έ',
75621 'ή' => 'Ή',
75622 'ί' => 'Ί',
75623 'α' => 'Α',
75624 'β' => 'Β',
75625 'γ' => 'Γ',
75626 'δ' => 'Δ',
75627 'ε' => 'Ε',
75628 'ζ' => 'Ζ',
75629 'η' => 'Η',
75630 'θ' => 'Θ',
75631 'ι' => 'Ι',
75632 'κ' => 'Κ',
75633 'λ' => 'Λ',
75634 'μ' => 'Μ',
75635 'ν' => 'Ν',
75636 'ξ' => 'Ξ',
75637 'ο' => 'Ο',
75638 'π' => 'Π',
75639 'ρ' => 'Ρ',
75640 'ς' => 'Σ',
75641 'σ' => 'Σ',
75642 'τ' => 'Τ',
75643 'υ' => 'Υ',
75644 'φ' => 'Φ',
75645 'χ' => 'Χ',
75646 'ψ' => 'Ψ',
75647 'ω' => 'Ω',
75648 'ϊ' => 'Ϊ',
75649 'ϋ' => 'Ϋ',
75650 'ό' => 'Ό',
75651 'ύ' => 'Ύ',
75652 'ώ' => 'Ώ',
75653 'ϐ' => 'Β',
75654 'ϑ' => 'Θ',
75655 'ϕ' => 'Φ',
75656 'ϖ' => 'Π',
75657 'ϗ' => 'Ϗ',
75658 'ϙ' => 'Ϙ',
75659 'ϛ' => 'Ϛ',
75660 'ϝ' => 'Ϝ',
75661 'ϟ' => 'Ϟ',
75662 'ϡ' => 'Ϡ',
75663 'ϣ' => 'Ϣ',
75664 'ϥ' => 'Ϥ',
75665 'ϧ' => 'Ϧ',
75666 'ϩ' => 'Ϩ',
75667 'ϫ' => 'Ϫ',
75668 'ϭ' => 'Ϭ',
75669 'ϯ' => 'Ϯ',
75670 'ϰ' => 'Κ',
75671 'ϱ' => 'Ρ',
75672 'ϲ' => 'Ϲ',
75673 'ϳ' => 'Ϳ',
75674 'ϵ' => 'Ε',
75675 'ϸ' => 'Ϸ',
75676 'ϻ' => 'Ϻ',
75677 'а' => 'А',
75678 'б' => 'Б',
75679 'в' => 'В',
75680 'г' => 'Г',
75681 'д' => 'Д',
75682 'е' => 'Е',
75683 'ж' => 'Ж',
75684 'з' => 'З',
75685 'и' => 'И',
75686 'й' => 'Й',
75687 'к' => 'К',
75688 'л' => 'Л',
75689 'м' => 'М',
75690 'н' => 'Н',
75691 'о' => 'О',
75692 'п' => 'П',
75693 'р' => 'Р',
75694 'с' => 'С',
75695 'т' => 'Т',
75696 'у' => 'У',
75697 'ф' => 'Ф',
75698 'х' => 'Х',
75699 'ц' => 'Ц',
75700 'ч' => 'Ч',
75701 'ш' => 'Ш',
75702 'щ' => 'Щ',
75703 'ъ' => 'Ъ',
75704 'ы' => 'Ы',
75705 'ь' => 'Ь',
75706 'э' => 'Э',
75707 'ю' => 'Ю',
75708 'я' => 'Я',
75709 'ѐ' => 'Ѐ',
75710 'ё' => 'Ё',
75711 'ђ' => 'Ђ',
75712 'ѓ' => 'Ѓ',
75713 'є' => 'Є',
75714 'ѕ' => 'Ѕ',
75715 'і' => 'І',
75716 'ї' => 'Ї',
75717 'ј' => 'Ј',
75718 'љ' => 'Љ',
75719 'њ' => 'Њ',
75720 'ћ' => 'Ћ',
75721 'ќ' => 'Ќ',
75722 'ѝ' => 'Ѝ',
75723 'ў' => 'Ў',
75724 'џ' => 'Џ',
75725 'ѡ' => 'Ѡ',
75726 'ѣ' => 'Ѣ',
75727 'ѥ' => 'Ѥ',
75728 'ѧ' => 'Ѧ',
75729 'ѩ' => 'Ѩ',
75730 'ѫ' => 'Ѫ',
75731 'ѭ' => 'Ѭ',
75732 'ѯ' => 'Ѯ',
75733 'ѱ' => 'Ѱ',
75734 'ѳ' => 'Ѳ',
75735 'ѵ' => 'Ѵ',
75736 'ѷ' => 'Ѷ',
75737 'ѹ' => 'Ѹ',
75738 'ѻ' => 'Ѻ',
75739 'ѽ' => 'Ѽ',
75740 'ѿ' => 'Ѿ',
75741 'ҁ' => 'Ҁ',
75742 'ҋ' => 'Ҋ',
75743 'ҍ' => 'Ҍ',
75744 'ҏ' => 'Ҏ',
75745 'ґ' => 'Ґ',
75746 'ғ' => 'Ғ',
75747 'ҕ' => 'Ҕ',
75748 'җ' => 'Җ',
75749 'ҙ' => 'Ҙ',
75750 'қ' => 'Қ',
75751 'ҝ' => 'Ҝ',
75752 'ҟ' => 'Ҟ',
75753 'ҡ' => 'Ҡ',
75754 'ң' => 'Ң',
75755 'ҥ' => 'Ҥ',
75756 'ҧ' => 'Ҧ',
75757 'ҩ' => 'Ҩ',
75758 'ҫ' => 'Ҫ',
75759 'ҭ' => 'Ҭ',
75760 'ү' => 'Ү',
75761 'ұ' => 'Ұ',
75762 'ҳ' => 'Ҳ',
75763 'ҵ' => 'Ҵ',
75764 'ҷ' => 'Ҷ',
75765 'ҹ' => 'Ҹ',
75766 'һ' => 'Һ',
75767 'ҽ' => 'Ҽ',
75768 'ҿ' => 'Ҿ',
75769 'ӂ' => 'Ӂ',
75770 'ӄ' => 'Ӄ',
75771 'ӆ' => 'Ӆ',
75772 'ӈ' => 'Ӈ',
75773 'ӊ' => 'Ӊ',
75774 'ӌ' => 'Ӌ',
75775 'ӎ' => 'Ӎ',
75776 'ӏ' => 'Ӏ',
75777 'ӑ' => 'Ӑ',
75778 'ӓ' => 'Ӓ',
75779 'ӕ' => 'Ӕ',
75780 'ӗ' => 'Ӗ',
75781 'ә' => 'Ә',
75782 'ӛ' => 'Ӛ',
75783 'ӝ' => 'Ӝ',
75784 'ӟ' => 'Ӟ',
75785 'ӡ' => 'Ӡ',
75786 'ӣ' => 'Ӣ',
75787 'ӥ' => 'Ӥ',
75788 'ӧ' => 'Ӧ',
75789 'ө' => 'Ө',
75790 'ӫ' => 'Ӫ',
75791 'ӭ' => 'Ӭ',
75792 'ӯ' => 'Ӯ',
75793 'ӱ' => 'Ӱ',
75794 'ӳ' => 'Ӳ',
75795 'ӵ' => 'Ӵ',
75796 'ӷ' => 'Ӷ',
75797 'ӹ' => 'Ӹ',
75798 'ӻ' => 'Ӻ',
75799 'ӽ' => 'Ӽ',
75800 'ӿ' => 'Ӿ',
75801 'ԁ' => 'Ԁ',
75802 'ԃ' => 'Ԃ',
75803 'ԅ' => 'Ԅ',
75804 'ԇ' => 'Ԇ',
75805 'ԉ' => 'Ԉ',
75806 'ԋ' => 'Ԋ',
75807 'ԍ' => 'Ԍ',
75808 'ԏ' => 'Ԏ',
75809 'ԑ' => 'Ԑ',
75810 'ԓ' => 'Ԓ',
75811 'ԕ' => 'Ԕ',
75812 'ԗ' => 'Ԗ',
75813 'ԙ' => 'Ԙ',
75814 'ԛ' => 'Ԛ',
75815 'ԝ' => 'Ԝ',
75816 'ԟ' => 'Ԟ',
75817 'ԡ' => 'Ԡ',
75818 'ԣ' => 'Ԣ',
75819 'ԥ' => 'Ԥ',
75820 'ԧ' => 'Ԧ',
75821 'ԩ' => 'Ԩ',
75822 'ԫ' => 'Ԫ',
75823 'ԭ' => 'Ԭ',
75824 'ԯ' => 'Ԯ',
75825 'ա' => 'Ա',
75826 'բ' => 'Բ',
75827 'գ' => 'Գ',
75828 'դ' => 'Դ',
75829 'ե' => 'Ե',
75830 'զ' => 'Զ',
75831 'է' => 'Է',
75832 'ը' => 'Ը',
75833 'թ' => 'Թ',
75834 'ժ' => 'Ժ',
75835 'ի' => 'Ի',
75836 'լ' => 'Լ',
75837 'խ' => 'Խ',
75838 'ծ' => 'Ծ',
75839 'կ' => 'Կ',
75840 'հ' => 'Հ',
75841 'ձ' => 'Ձ',
75842 'ղ' => 'Ղ',
75843 'ճ' => 'Ճ',
75844 'մ' => 'Մ',
75845 'յ' => 'Յ',
75846 'ն' => 'Ն',
75847 'շ' => 'Շ',
75848 'ո' => 'Ո',
75849 'չ' => 'Չ',
75850 'պ' => 'Պ',
75851 'ջ' => 'Ջ',
75852 'ռ' => 'Ռ',
75853 'ս' => 'Ս',
75854 'վ' => 'Վ',
75855 'տ' => 'Տ',
75856 'ր' => 'Ր',
75857 'ց' => 'Ց',
75858 'ւ' => 'Ւ',
75859 'փ' => 'Փ',
75860 'ք' => 'Ք',
75861 'օ' => 'Օ',
75862 'ֆ' => 'Ֆ',
75863 'ᵹ' => 'Ᵹ',
75864 'ᵽ' => 'Ᵽ',
75865 'ḁ' => 'Ḁ',
75866 'ḃ' => 'Ḃ',
75867 'ḅ' => 'Ḅ',
75868 'ḇ' => 'Ḇ',
75869 'ḉ' => 'Ḉ',
75870 'ḋ' => 'Ḋ',
75871 'ḍ' => 'Ḍ',
75872 'ḏ' => 'Ḏ',
75873 'ḑ' => 'Ḑ',
75874 'ḓ' => 'Ḓ',
75875 'ḕ' => 'Ḕ',
75876 'ḗ' => 'Ḗ',
75877 'ḙ' => 'Ḙ',
75878 'ḛ' => 'Ḛ',
75879 'ḝ' => 'Ḝ',
75880 'ḟ' => 'Ḟ',
75881 'ḡ' => 'Ḡ',
75882 'ḣ' => 'Ḣ',
75883 'ḥ' => 'Ḥ',
75884 'ḧ' => 'Ḧ',
75885 'ḩ' => 'Ḩ',
75886 'ḫ' => 'Ḫ',
75887 'ḭ' => 'Ḭ',
75888 'ḯ' => 'Ḯ',
75889 'ḱ' => 'Ḱ',
75890 'ḳ' => 'Ḳ',
75891 'ḵ' => 'Ḵ',
75892 'ḷ' => 'Ḷ',
75893 'ḹ' => 'Ḹ',
75894 'ḻ' => 'Ḻ',
75895 'ḽ' => 'Ḽ',
75896 'ḿ' => 'Ḿ',
75897 'ṁ' => 'Ṁ',
75898 'ṃ' => 'Ṃ',
75899 'ṅ' => 'Ṅ',
75900 'ṇ' => 'Ṇ',
75901 'ṉ' => 'Ṉ',
75902 'ṋ' => 'Ṋ',
75903 'ṍ' => 'Ṍ',
75904 'ṏ' => 'Ṏ',
75905 'ṑ' => 'Ṑ',
75906 'ṓ' => 'Ṓ',
75907 'ṕ' => 'Ṕ',
75908 'ṗ' => 'Ṗ',
75909 'ṙ' => 'Ṙ',
75910 'ṛ' => 'Ṛ',
75911 'ṝ' => 'Ṝ',
75912 'ṟ' => 'Ṟ',
75913 'ṡ' => 'Ṡ',
75914 'ṣ' => 'Ṣ',
75915 'ṥ' => 'Ṥ',
75916 'ṧ' => 'Ṧ',
75917 'ṩ' => 'Ṩ',
75918 'ṫ' => 'Ṫ',
75919 'ṭ' => 'Ṭ',
75920 'ṯ' => 'Ṯ',
75921 'ṱ' => 'Ṱ',
75922 'ṳ' => 'Ṳ',
75923 'ṵ' => 'Ṵ',
75924 'ṷ' => 'Ṷ',
75925 'ṹ' => 'Ṹ',
75926 'ṻ' => 'Ṻ',
75927 'ṽ' => 'Ṽ',
75928 'ṿ' => 'Ṿ',
75929 'ẁ' => 'Ẁ',
75930 'ẃ' => 'Ẃ',
75931 'ẅ' => 'Ẅ',
75932 'ẇ' => 'Ẇ',
75933 'ẉ' => 'Ẉ',
75934 'ẋ' => 'Ẋ',
75935 'ẍ' => 'Ẍ',
75936 'ẏ' => 'Ẏ',
75937 'ẑ' => 'Ẑ',
75938 'ẓ' => 'Ẓ',
75939 'ẕ' => 'Ẕ',
75940 'ẛ' => 'Ṡ',
75941 'ạ' => 'Ạ',
75942 'ả' => 'Ả',
75943 'ấ' => 'Ấ',
75944 'ầ' => 'Ầ',
75945 'ẩ' => 'Ẩ',
75946 'ẫ' => 'Ẫ',
75947 'ậ' => 'Ậ',
75948 'ắ' => 'Ắ',
75949 'ằ' => 'Ằ',
75950 'ẳ' => 'Ẳ',
75951 'ẵ' => 'Ẵ',
75952 'ặ' => 'Ặ',
75953 'ẹ' => 'Ẹ',
75954 'ẻ' => 'Ẻ',
75955 'ẽ' => 'Ẽ',
75956 'ế' => 'Ế',
75957 'ề' => 'Ề',
75958 'ể' => 'Ể',
75959 'ễ' => 'Ễ',
75960 'ệ' => 'Ệ',
75961 'ỉ' => 'Ỉ',
75962 'ị' => 'Ị',
75963 'ọ' => 'Ọ',
75964 'ỏ' => 'Ỏ',
75965 'ố' => 'Ố',
75966 'ồ' => 'Ồ',
75967 'ổ' => 'Ổ',
75968 'ỗ' => 'Ỗ',
75969 'ộ' => 'Ộ',
75970 'ớ' => 'Ớ',
75971 'ờ' => 'Ờ',
75972 'ở' => 'Ở',
75973 'ỡ' => 'Ỡ',
75974 'ợ' => 'Ợ',
75975 'ụ' => 'Ụ',
75976 'ủ' => 'Ủ',
75977 'ứ' => 'Ứ',
75978 'ừ' => 'Ừ',
75979 'ử' => 'Ử',
75980 'ữ' => 'Ữ',
75981 'ự' => 'Ự',
75982 'ỳ' => 'Ỳ',
75983 'ỵ' => 'Ỵ',
75984 'ỷ' => 'Ỷ',
75985 'ỹ' => 'Ỹ',
75986 'ỻ' => 'Ỻ',
75987 'ỽ' => 'Ỽ',
75988 'ỿ' => 'Ỿ',
75989 'ἀ' => 'Ἀ',
75990 'ἁ' => 'Ἁ',
75991 'ἂ' => 'Ἂ',
75992 'ἃ' => 'Ἃ',
75993 'ἄ' => 'Ἄ',
75994 'ἅ' => 'Ἅ',
75995 'ἆ' => 'Ἆ',
75996 'ἇ' => 'Ἇ',
75997 'ἐ' => 'Ἐ',
75998 'ἑ' => 'Ἑ',
75999 'ἒ' => 'Ἒ',
76000 'ἓ' => 'Ἓ',
76001 'ἔ' => 'Ἔ',
76002 'ἕ' => 'Ἕ',
76003 'ἠ' => 'Ἠ',
76004 'ἡ' => 'Ἡ',
76005 'ἢ' => 'Ἢ',
76006 'ἣ' => 'Ἣ',
76007 'ἤ' => 'Ἤ',
76008 'ἥ' => 'Ἥ',
76009 'ἦ' => 'Ἦ',
76010 'ἧ' => 'Ἧ',
76011 'ἰ' => 'Ἰ',
76012 'ἱ' => 'Ἱ',
76013 'ἲ' => 'Ἲ',
76014 'ἳ' => 'Ἳ',
76015 'ἴ' => 'Ἴ',
76016 'ἵ' => 'Ἵ',
76017 'ἶ' => 'Ἶ',
76018 'ἷ' => 'Ἷ',
76019 'ὀ' => 'Ὀ',
76020 'ὁ' => 'Ὁ',
76021 'ὂ' => 'Ὂ',
76022 'ὃ' => 'Ὃ',
76023 'ὄ' => 'Ὄ',
76024 'ὅ' => 'Ὅ',
76025 'ὑ' => 'Ὑ',
76026 'ὓ' => 'Ὓ',
76027 'ὕ' => 'Ὕ',
76028 'ὗ' => 'Ὗ',
76029 'ὠ' => 'Ὠ',
76030 'ὡ' => 'Ὡ',
76031 'ὢ' => 'Ὢ',
76032 'ὣ' => 'Ὣ',
76033 'ὤ' => 'Ὤ',
76034 'ὥ' => 'Ὥ',
76035 'ὦ' => 'Ὦ',
76036 'ὧ' => 'Ὧ',
76037 'ὰ' => 'Ὰ',
76038 'ά' => 'Ά',
76039 'ὲ' => 'Ὲ',
76040 'έ' => 'Έ',
76041 'ὴ' => 'Ὴ',
76042 'ή' => 'Ή',
76043 'ὶ' => 'Ὶ',
76044 'ί' => 'Ί',
76045 'ὸ' => 'Ὸ',
76046 'ό' => 'Ό',
76047 'ὺ' => 'Ὺ',
76048 'ύ' => 'Ύ',
76049 'ὼ' => 'Ὼ',
76050 'ώ' => 'Ώ',
76051 'ᾀ' => 'ᾈ',
76052 'ᾁ' => 'ᾉ',
76053 'ᾂ' => 'ᾊ',
76054 'ᾃ' => 'ᾋ',
76055 'ᾄ' => 'ᾌ',
76056 'ᾅ' => 'ᾍ',
76057 'ᾆ' => 'ᾎ',
76058 'ᾇ' => 'ᾏ',
76059 'ᾐ' => 'ᾘ',
76060 'ᾑ' => 'ᾙ',
76061 'ᾒ' => 'ᾚ',
76062 'ᾓ' => 'ᾛ',
76063 'ᾔ' => 'ᾜ',
76064 'ᾕ' => 'ᾝ',
76065 'ᾖ' => 'ᾞ',
76066 'ᾗ' => 'ᾟ',
76067 'ᾠ' => 'ᾨ',
76068 'ᾡ' => 'ᾩ',
76069 'ᾢ' => 'ᾪ',
76070 'ᾣ' => 'ᾫ',
76071 'ᾤ' => 'ᾬ',
76072 'ᾥ' => 'ᾭ',
76073 'ᾦ' => 'ᾮ',
76074 'ᾧ' => 'ᾯ',
76075 'ᾰ' => 'Ᾰ',
76076 'ᾱ' => 'Ᾱ',
76077 'ᾳ' => 'ᾼ',
76078 'ι' => 'Ι',
76079 'ῃ' => 'ῌ',
76080 'ῐ' => 'Ῐ',
76081 'ῑ' => 'Ῑ',
76082 'ῠ' => 'Ῠ',
76083 'ῡ' => 'Ῡ',
76084 'ῥ' => 'Ῥ',
76085 'ῳ' => 'ῼ',
76086 'ⅎ' => 'Ⅎ',
76087 'ⅰ' => 'Ⅰ',
76088 'ⅱ' => 'Ⅱ',
76089 'ⅲ' => 'Ⅲ',
76090 'ⅳ' => 'Ⅳ',
76091 'ⅴ' => 'Ⅴ',
76092 'ⅵ' => 'Ⅵ',
76093 'ⅶ' => 'Ⅶ',
76094 'ⅷ' => 'Ⅷ',
76095 'ⅸ' => 'Ⅸ',
76096 'ⅹ' => 'Ⅹ',
76097 'ⅺ' => 'Ⅺ',
76098 'ⅻ' => 'Ⅻ',
76099 'ⅼ' => 'Ⅼ',
76100 'ⅽ' => 'Ⅽ',
76101 'ⅾ' => 'Ⅾ',
76102 'ⅿ' => 'Ⅿ',
76103 'ↄ' => 'Ↄ',
76104 'ⓐ' => 'Ⓐ',
76105 'ⓑ' => 'Ⓑ',
76106 'ⓒ' => 'Ⓒ',
76107 'ⓓ' => 'Ⓓ',
76108 'ⓔ' => 'Ⓔ',
76109 'ⓕ' => 'Ⓕ',
76110 'ⓖ' => 'Ⓖ',
76111 'ⓗ' => 'Ⓗ',
76112 'ⓘ' => 'Ⓘ',
76113 'ⓙ' => 'Ⓙ',
76114 'ⓚ' => 'Ⓚ',
76115 'ⓛ' => 'Ⓛ',
76116 'ⓜ' => 'Ⓜ',
76117 'ⓝ' => 'Ⓝ',
76118 'ⓞ' => 'Ⓞ',
76119 'ⓟ' => 'Ⓟ',
76120 'ⓠ' => 'Ⓠ',
76121 'ⓡ' => 'Ⓡ',
76122 'ⓢ' => 'Ⓢ',
76123 'ⓣ' => 'Ⓣ',
76124 'ⓤ' => 'Ⓤ',
76125 'ⓥ' => 'Ⓥ',
76126 'ⓦ' => 'Ⓦ',
76127 'ⓧ' => 'Ⓧ',
76128 'ⓨ' => 'Ⓨ',
76129 'ⓩ' => 'Ⓩ',
76130 'ⰰ' => 'Ⰰ',
76131 'ⰱ' => 'Ⰱ',
76132 'ⰲ' => 'Ⰲ',
76133 'ⰳ' => 'Ⰳ',
76134 'ⰴ' => 'Ⰴ',
76135 'ⰵ' => 'Ⰵ',
76136 'ⰶ' => 'Ⰶ',
76137 'ⰷ' => 'Ⰷ',
76138 'ⰸ' => 'Ⰸ',
76139 'ⰹ' => 'Ⰹ',
76140 'ⰺ' => 'Ⰺ',
76141 'ⰻ' => 'Ⰻ',
76142 'ⰼ' => 'Ⰼ',
76143 'ⰽ' => 'Ⰽ',
76144 'ⰾ' => 'Ⰾ',
76145 'ⰿ' => 'Ⰿ',
76146 'ⱀ' => 'Ⱀ',
76147 'ⱁ' => 'Ⱁ',
76148 'ⱂ' => 'Ⱂ',
76149 'ⱃ' => 'Ⱃ',
76150 'ⱄ' => 'Ⱄ',
76151 'ⱅ' => 'Ⱅ',
76152 'ⱆ' => 'Ⱆ',
76153 'ⱇ' => 'Ⱇ',
76154 'ⱈ' => 'Ⱈ',
76155 'ⱉ' => 'Ⱉ',
76156 'ⱊ' => 'Ⱊ',
76157 'ⱋ' => 'Ⱋ',
76158 'ⱌ' => 'Ⱌ',
76159 'ⱍ' => 'Ⱍ',
76160 'ⱎ' => 'Ⱎ',
76161 'ⱏ' => 'Ⱏ',
76162 'ⱐ' => 'Ⱐ',
76163 'ⱑ' => 'Ⱑ',
76164 'ⱒ' => 'Ⱒ',
76165 'ⱓ' => 'Ⱓ',
76166 'ⱔ' => 'Ⱔ',
76167 'ⱕ' => 'Ⱕ',
76168 'ⱖ' => 'Ⱖ',
76169 'ⱗ' => 'Ⱗ',
76170 'ⱘ' => 'Ⱘ',
76171 'ⱙ' => 'Ⱙ',
76172 'ⱚ' => 'Ⱚ',
76173 'ⱛ' => 'Ⱛ',
76174 'ⱜ' => 'Ⱜ',
76175 'ⱝ' => 'Ⱝ',
76176 'ⱞ' => 'Ⱞ',
76177 'ⱡ' => 'Ⱡ',
76178 'ⱥ' => 'Ⱥ',
76179 'ⱦ' => 'Ⱦ',
76180 'ⱨ' => 'Ⱨ',
76181 'ⱪ' => 'Ⱪ',
76182 'ⱬ' => 'Ⱬ',
76183 'ⱳ' => 'Ⱳ',
76184 'ⱶ' => 'Ⱶ',
76185 'ⲁ' => 'Ⲁ',
76186 'ⲃ' => 'Ⲃ',
76187 'ⲅ' => 'Ⲅ',
76188 'ⲇ' => 'Ⲇ',
76189 'ⲉ' => 'Ⲉ',
76190 'ⲋ' => 'Ⲋ',
76191 'ⲍ' => 'Ⲍ',
76192 'ⲏ' => 'Ⲏ',
76193 'ⲑ' => 'Ⲑ',
76194 'ⲓ' => 'Ⲓ',
76195 'ⲕ' => 'Ⲕ',
76196 'ⲗ' => 'Ⲗ',
76197 'ⲙ' => 'Ⲙ',
76198 'ⲛ' => 'Ⲛ',
76199 'ⲝ' => 'Ⲝ',
76200 'ⲟ' => 'Ⲟ',
76201 'ⲡ' => 'Ⲡ',
76202 'ⲣ' => 'Ⲣ',
76203 'ⲥ' => 'Ⲥ',
76204 'ⲧ' => 'Ⲧ',
76205 'ⲩ' => 'Ⲩ',
76206 'ⲫ' => 'Ⲫ',
76207 'ⲭ' => 'Ⲭ',
76208 'ⲯ' => 'Ⲯ',
76209 'ⲱ' => 'Ⲱ',
76210 'ⲳ' => 'Ⲳ',
76211 'ⲵ' => 'Ⲵ',
76212 'ⲷ' => 'Ⲷ',
76213 'ⲹ' => 'Ⲹ',
76214 'ⲻ' => 'Ⲻ',
76215 'ⲽ' => 'Ⲽ',
76216 'ⲿ' => 'Ⲿ',
76217 'ⳁ' => 'Ⳁ',
76218 'ⳃ' => 'Ⳃ',
76219 'ⳅ' => 'Ⳅ',
76220 'ⳇ' => 'Ⳇ',
76221 'ⳉ' => 'Ⳉ',
76222 'ⳋ' => 'Ⳋ',
76223 'ⳍ' => 'Ⳍ',
76224 'ⳏ' => 'Ⳏ',
76225 'ⳑ' => 'Ⳑ',
76226 'ⳓ' => 'Ⳓ',
76227 'ⳕ' => 'Ⳕ',
76228 'ⳗ' => 'Ⳗ',
76229 'ⳙ' => 'Ⳙ',
76230 'ⳛ' => 'Ⳛ',
76231 'ⳝ' => 'Ⳝ',
76232 'ⳟ' => 'Ⳟ',
76233 'ⳡ' => 'Ⳡ',
76234 'ⳣ' => 'Ⳣ',
76235 'ⳬ' => 'Ⳬ',
76236 'ⳮ' => 'Ⳮ',
76237 'ⳳ' => 'Ⳳ',
76238 'ⴀ' => 'Ⴀ',
76239 'ⴁ' => 'Ⴁ',
76240 'ⴂ' => 'Ⴂ',
76241 'ⴃ' => 'Ⴃ',
76242 'ⴄ' => 'Ⴄ',
76243 'ⴅ' => 'Ⴅ',
76244 'ⴆ' => 'Ⴆ',
76245 'ⴇ' => 'Ⴇ',
76246 'ⴈ' => 'Ⴈ',
76247 'ⴉ' => 'Ⴉ',
76248 'ⴊ' => 'Ⴊ',
76249 'ⴋ' => 'Ⴋ',
76250 'ⴌ' => 'Ⴌ',
76251 'ⴍ' => 'Ⴍ',
76252 'ⴎ' => 'Ⴎ',
76253 'ⴏ' => 'Ⴏ',
76254 'ⴐ' => 'Ⴐ',
76255 'ⴑ' => 'Ⴑ',
76256 'ⴒ' => 'Ⴒ',
76257 'ⴓ' => 'Ⴓ',
76258 'ⴔ' => 'Ⴔ',
76259 'ⴕ' => 'Ⴕ',
76260 'ⴖ' => 'Ⴖ',
76261 'ⴗ' => 'Ⴗ',
76262 'ⴘ' => 'Ⴘ',
76263 'ⴙ' => 'Ⴙ',
76264 'ⴚ' => 'Ⴚ',
76265 'ⴛ' => 'Ⴛ',
76266 'ⴜ' => 'Ⴜ',
76267 'ⴝ' => 'Ⴝ',
76268 'ⴞ' => 'Ⴞ',
76269 'ⴟ' => 'Ⴟ',
76270 'ⴠ' => 'Ⴠ',
76271 'ⴡ' => 'Ⴡ',
76272 'ⴢ' => 'Ⴢ',
76273 'ⴣ' => 'Ⴣ',
76274 'ⴤ' => 'Ⴤ',
76275 'ⴥ' => 'Ⴥ',
76276 'ⴧ' => 'Ⴧ',
76277 'ⴭ' => 'Ⴭ',
76278 'ꙁ' => 'Ꙁ',
76279 'ꙃ' => 'Ꙃ',
76280 'ꙅ' => 'Ꙅ',
76281 'ꙇ' => 'Ꙇ',
76282 'ꙉ' => 'Ꙉ',
76283 'ꙋ' => 'Ꙋ',
76284 'ꙍ' => 'Ꙍ',
76285 'ꙏ' => 'Ꙏ',
76286 'ꙑ' => 'Ꙑ',
76287 'ꙓ' => 'Ꙓ',
76288 'ꙕ' => 'Ꙕ',
76289 'ꙗ' => 'Ꙗ',
76290 'ꙙ' => 'Ꙙ',
76291 'ꙛ' => 'Ꙛ',
76292 'ꙝ' => 'Ꙝ',
76293 'ꙟ' => 'Ꙟ',
76294 'ꙡ' => 'Ꙡ',
76295 'ꙣ' => 'Ꙣ',
76296 'ꙥ' => 'Ꙥ',
76297 'ꙧ' => 'Ꙧ',
76298 'ꙩ' => 'Ꙩ',
76299 'ꙫ' => 'Ꙫ',
76300 'ꙭ' => 'Ꙭ',
76301 'ꚁ' => 'Ꚁ',
76302 'ꚃ' => 'Ꚃ',
76303 'ꚅ' => 'Ꚅ',
76304 'ꚇ' => 'Ꚇ',
76305 'ꚉ' => 'Ꚉ',
76306 'ꚋ' => 'Ꚋ',
76307 'ꚍ' => 'Ꚍ',
76308 'ꚏ' => 'Ꚏ',
76309 'ꚑ' => 'Ꚑ',
76310 'ꚓ' => 'Ꚓ',
76311 'ꚕ' => 'Ꚕ',
76312 'ꚗ' => 'Ꚗ',
76313 'ꚙ' => 'Ꚙ',
76314 'ꚛ' => 'Ꚛ',
76315 'ꜣ' => 'Ꜣ',
76316 'ꜥ' => 'Ꜥ',
76317 'ꜧ' => 'Ꜧ',
76318 'ꜩ' => 'Ꜩ',
76319 'ꜫ' => 'Ꜫ',
76320 'ꜭ' => 'Ꜭ',
76321 'ꜯ' => 'Ꜯ',
76322 'ꜳ' => 'Ꜳ',
76323 'ꜵ' => 'Ꜵ',
76324 'ꜷ' => 'Ꜷ',
76325 'ꜹ' => 'Ꜹ',
76326 'ꜻ' => 'Ꜻ',
76327 'ꜽ' => 'Ꜽ',
76328 'ꜿ' => 'Ꜿ',
76329 'ꝁ' => 'Ꝁ',
76330 'ꝃ' => 'Ꝃ',
76331 'ꝅ' => 'Ꝅ',
76332 'ꝇ' => 'Ꝇ',
76333 'ꝉ' => 'Ꝉ',
76334 'ꝋ' => 'Ꝋ',
76335 'ꝍ' => 'Ꝍ',
76336 'ꝏ' => 'Ꝏ',
76337 'ꝑ' => 'Ꝑ',
76338 'ꝓ' => 'Ꝓ',
76339 'ꝕ' => 'Ꝕ',
76340 'ꝗ' => 'Ꝗ',
76341 'ꝙ' => 'Ꝙ',
76342 'ꝛ' => 'Ꝛ',
76343 'ꝝ' => 'Ꝝ',
76344 'ꝟ' => 'Ꝟ',
76345 'ꝡ' => 'Ꝡ',
76346 'ꝣ' => 'Ꝣ',
76347 'ꝥ' => 'Ꝥ',
76348 'ꝧ' => 'Ꝧ',
76349 'ꝩ' => 'Ꝩ',
76350 'ꝫ' => 'Ꝫ',
76351 'ꝭ' => 'Ꝭ',
76352 'ꝯ' => 'Ꝯ',
76353 'ꝺ' => 'Ꝺ',
76354 'ꝼ' => 'Ꝼ',
76355 'ꝿ' => 'Ꝿ',
76356 'ꞁ' => 'Ꞁ',
76357 'ꞃ' => 'Ꞃ',
76358 'ꞅ' => 'Ꞅ',
76359 'ꞇ' => 'Ꞇ',
76360 'ꞌ' => 'Ꞌ',
76361 'ꞑ' => 'Ꞑ',
76362 'ꞓ' => 'Ꞓ',
76363 'ꞗ' => 'Ꞗ',
76364 'ꞙ' => 'Ꞙ',
76365 'ꞛ' => 'Ꞛ',
76366 'ꞝ' => 'Ꞝ',
76367 'ꞟ' => 'Ꞟ',
76368 'ꞡ' => 'Ꞡ',
76369 'ꞣ' => 'Ꞣ',
76370 'ꞥ' => 'Ꞥ',
76371 'ꞧ' => 'Ꞧ',
76372 'ꞩ' => 'Ꞩ',
76373 'a' => 'A',
76374 'b' => 'B',
76375 'c' => 'C',
76376 'd' => 'D',
76377 'e' => 'E',
76378 'f' => 'F',
76379 'g' => 'G',
76380 'h' => 'H',
76381 'i' => 'I',
76382 'j' => 'J',
76383 'k' => 'K',
76384 'l' => 'L',
76385 'm' => 'M',
76386 'n' => 'N',
76387 'o' => 'O',
76388 'p' => 'P',
76389 'q' => 'Q',
76390 'r' => 'R',
76391 's' => 'S',
76392 't' => 'T',
76393 'u' => 'U',
76394 'v' => 'V',
76395 'w' => 'W',
76396 'x' => 'X',
76397 'y' => 'Y',
76398 'z' => 'Z',
76399 '𐐨' => '𐐀',
76400 '𐐩' => '𐐁',
76401 '𐐪' => '𐐂',
76402 '𐐫' => '𐐃',
76403 '𐐬' => '𐐄',
76404 '𐐭' => '𐐅',
76405 '𐐮' => '𐐆',
76406 '𐐯' => '𐐇',
76407 '𐐰' => '𐐈',
76408 '𐐱' => '𐐉',
76409 '𐐲' => '𐐊',
76410 '𐐳' => '𐐋',
76411 '𐐴' => '𐐌',
76412 '𐐵' => '𐐍',
76413 '𐐶' => '𐐎',
76414 '𐐷' => '𐐏',
76415 '𐐸' => '𐐐',
76416 '𐐹' => '𐐑',
76417 '𐐺' => '𐐒',
76418 '𐐻' => '𐐓',
76419 '𐐼' => '𐐔',
76420 '𐐽' => '𐐕',
76421 '𐐾' => '𐐖',
76422 '𐐿' => '𐐗',
76423 '𐑀' => '𐐘',
76424 '𐑁' => '𐐙',
76425 '𐑂' => '𐐚',
76426 '𐑃' => '𐐛',
76427 '𐑄' => '𐐜',
76428 '𐑅' => '𐐝',
76429 '𐑆' => '𐐞',
76430 '𐑇' => '𐐟',
76431 '𐑈' => '𐐠',
76432 '𐑉' => '𐐡',
76433 '𐑊' => '𐐢',
76434 '𐑋' => '𐐣',
76435 '𐑌' => '𐐤',
76436 '𐑍' => '𐐥',
76437 '𐑎' => '𐐦',
76438 '𐑏' => '𐐧',
76439 '𑣀' => '𑢠',
76440 '𑣁' => '𑢡',
76441 '𑣂' => '𑢢',
76442 '𑣃' => '𑢣',
76443 '𑣄' => '𑢤',
76444 '𑣅' => '𑢥',
76445 '𑣆' => '𑢦',
76446 '𑣇' => '𑢧',
76447 '𑣈' => '𑢨',
76448 '𑣉' => '𑢩',
76449 '𑣊' => '𑢪',
76450 '𑣋' => '𑢫',
76451 '𑣌' => '𑢬',
76452 '𑣍' => '𑢭',
76453 '𑣎' => '𑢮',
76454 '𑣏' => '𑢯',
76455 '𑣐' => '𑢰',
76456 '𑣑' => '𑢱',
76457 '𑣒' => '𑢲',
76458 '𑣓' => '𑢳',
76459 '𑣔' => '𑢴',
76460 '𑣕' => '𑢵',
76461 '𑣖' => '𑢶',
76462 '𑣗' => '𑢷',
76463 '𑣘' => '𑢸',
76464 '𑣙' => '𑢹',
76465 '𑣚' => '𑢺',
76466 '𑣛' => '𑢻',
76467 '𑣜' => '𑢼',
76468 '𑣝' => '𑢽',
76469 '𑣞' => '𑢾',
76470 '𑣟' => '𑢿',
76471 );
76472 <?php
76473
76474
76475
76476
76477
76478
76479
76480
76481
76482
76483 use Symfony\Polyfill\Mbstring as p;
76484
76485 if (!function_exists('mb_convert_encoding')) {
76486 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
76487 }
76488 if (!function_exists('mb_decode_mimeheader')) {
76489 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
76490 }
76491 if (!function_exists('mb_encode_mimeheader')) {
76492 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
76493 }
76494 if (!function_exists('mb_decode_numericentity')) {
76495 function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
76496 }
76497 if (!function_exists('mb_encode_numericentity')) {
76498 function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
76499 }
76500 if (!function_exists('mb_convert_case')) {
76501 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
76502 }
76503 if (!function_exists('mb_internal_encoding')) {
76504 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
76505 }
76506 if (!function_exists('mb_language')) {
76507 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
76508 }
76509 if (!function_exists('mb_list_encodings')) {
76510 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
76511 }
76512 if (!function_exists('mb_encoding_aliases')) {
76513 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
76514 }
76515 if (!function_exists('mb_check_encoding')) {
76516 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
76517 }
76518 if (!function_exists('mb_detect_encoding')) {
76519 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
76520 }
76521 if (!function_exists('mb_detect_order')) {
76522 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
76523 }
76524 if (!function_exists('mb_parse_str')) {
76525 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
76526 }
76527 if (!function_exists('mb_strlen')) {
76528 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
76529 }
76530 if (!function_exists('mb_strpos')) {
76531 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
76532 }
76533 if (!function_exists('mb_strtolower')) {
76534 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
76535 }
76536 if (!function_exists('mb_strtoupper')) {
76537 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
76538 }
76539 if (!function_exists('mb_substitute_character')) {
76540 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
76541 }
76542 if (!function_exists('mb_substr')) {
76543 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
76544 }
76545 if (!function_exists('mb_stripos')) {
76546 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
76547 }
76548 if (!function_exists('mb_stristr')) {
76549 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
76550 }
76551 if (!function_exists('mb_strrchr')) {
76552 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
76553 }
76554 if (!function_exists('mb_strrichr')) {
76555 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
76556 }
76557 if (!function_exists('mb_strripos')) {
76558 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
76559 }
76560 if (!function_exists('mb_strrpos')) {
76561 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
76562 }
76563 if (!function_exists('mb_strstr')) {
76564 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
76565 }
76566 if (!function_exists('mb_get_info')) {
76567 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
76568 }
76569 if (!function_exists('mb_http_output')) {
76570 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
76571 }
76572 if (!function_exists('mb_strwidth')) {
76573 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
76574 }
76575 if (!function_exists('mb_substr_count')) {
76576 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
76577 }
76578 if (!function_exists('mb_output_handler')) {
76579 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
76580 }
76581 if (!function_exists('mb_http_input')) {
76582 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
76583 }
76584 if (!function_exists('mb_convert_variables')) {
76585 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); }
76586 }
76587 if (!function_exists('mb_ord')) {
76588 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
76589 }
76590 if (!function_exists('mb_chr')) {
76591 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
76592 }
76593 if (!function_exists('mb_scrub')) {
76594 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
76595 }
76596 if (!function_exists('mb_str_split')) {
76597 function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
76598 }
76599
76600 if (extension_loaded('mbstring')) {
76601 return;
76602 }
76603
76604 if (!defined('MB_CASE_UPPER')) {
76605 define('MB_CASE_UPPER', 0);
76606 }
76607 if (!defined('MB_CASE_LOWER')) {
76608 define('MB_CASE_LOWER', 1);
76609 }
76610 if (!defined('MB_CASE_TITLE')) {
76611 define('MB_CASE_TITLE', 2);
76612 }
76613 <?php
76614
76615
76616
76617
76618
76619
76620
76621
76622
76623
76624 namespace Symfony\Component\Process\Exception;
76625
76626
76627
76628
76629
76630
76631 interface ExceptionInterface
76632 {
76633 }
76634 <?php
76635
76636
76637
76638
76639
76640
76641
76642
76643
76644
76645 namespace Symfony\Component\Process\Exception;
76646
76647
76648
76649
76650
76651
76652 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
76653 {
76654 }
76655 <?php
76656
76657
76658
76659
76660
76661
76662
76663
76664
76665
76666 namespace Symfony\Component\Process\Exception;
76667
76668
76669
76670
76671
76672
76673 class LogicException extends \LogicException implements ExceptionInterface
76674 {
76675 }
76676 <?php
76677
76678
76679
76680
76681
76682
76683
76684
76685
76686
76687 namespace Symfony\Component\Process\Exception;
76688
76689 use Symfony\Component\Process\Process;
76690
76691
76692
76693
76694
76695
76696 class ProcessFailedException extends RuntimeException
76697 {
76698 private $process;
76699
76700 public function __construct(Process $process)
76701 {
76702 if ($process->isSuccessful()) {
76703 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
76704 }
76705
76706 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
76707 $process->getCommandLine(),
76708 $process->getExitCode(),
76709 $process->getExitCodeText(),
76710 $process->getWorkingDirectory()
76711 );
76712
76713 if (!$process->isOutputDisabled()) {
76714 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
76715 $process->getOutput(),
76716 $process->getErrorOutput()
76717 );
76718 }
76719
76720 parent::__construct($error);
76721
76722 $this->process = $process;
76723 }
76724
76725 public function getProcess()
76726 {
76727 return $this->process;
76728 }
76729 }
76730 <?php
76731
76732
76733
76734
76735
76736
76737
76738
76739
76740
76741 namespace Symfony\Component\Process\Exception;
76742
76743 use Symfony\Component\Process\Process;
76744
76745
76746
76747
76748
76749
76750 class ProcessTimedOutException extends RuntimeException
76751 {
76752 const TYPE_GENERAL = 1;
76753 const TYPE_IDLE = 2;
76754
76755 private $process;
76756 private $timeoutType;
76757
76758 public function __construct(Process $process, $timeoutType)
76759 {
76760 $this->process = $process;
76761 $this->timeoutType = $timeoutType;
76762
76763 parent::__construct(sprintf(
76764 'The process "%s" exceeded the timeout of %s seconds.',
76765 $process->getCommandLine(),
76766 $this->getExceededTimeout()
76767 ));
76768 }
76769
76770 public function getProcess()
76771 {
76772 return $this->process;
76773 }
76774
76775 public function isGeneralTimeout()
76776 {
76777 return self::TYPE_GENERAL === $this->timeoutType;
76778 }
76779
76780 public function isIdleTimeout()
76781 {
76782 return self::TYPE_IDLE === $this->timeoutType;
76783 }
76784
76785 public function getExceededTimeout()
76786 {
76787 switch ($this->timeoutType) {
76788 case self::TYPE_GENERAL:
76789 return $this->process->getTimeout();
76790
76791 case self::TYPE_IDLE:
76792 return $this->process->getIdleTimeout();
76793
76794 default:
76795 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
76796 }
76797 }
76798 }
76799 <?php
76800
76801
76802
76803
76804
76805
76806
76807
76808
76809
76810 namespace Symfony\Component\Process\Exception;
76811
76812
76813
76814
76815
76816
76817 class RuntimeException extends \RuntimeException implements ExceptionInterface
76818 {
76819 }
76820 <?php
76821
76822
76823
76824
76825
76826
76827
76828
76829
76830
76831 namespace Symfony\Component\Process;
76832
76833
76834
76835
76836
76837
76838
76839 class ExecutableFinder
76840 {
76841 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
76842
76843
76844
76845
76846 public function setSuffixes(array $suffixes)
76847 {
76848 $this->suffixes = $suffixes;
76849 }
76850
76851
76852
76853
76854
76855
76856 public function addSuffix($suffix)
76857 {
76858 $this->suffixes[] = $suffix;
76859 }
76860
76861
76862
76863
76864
76865
76866
76867
76868
76869
76870 public function find($name, $default = null, array $extraDirs = array())
76871 {
76872 if (ini_get('open_basedir')) {
76873 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
76874 $dirs = array();
76875 foreach ($searchPath as $path) {
76876
76877  if (@is_dir($path)) {
76878 $dirs[] = $path;
76879 } else {
76880 if (basename($path) == $name && @is_executable($path)) {
76881 return $path;
76882 }
76883 }
76884 }
76885 } else {
76886 $dirs = array_merge(
76887 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
76888 $extraDirs
76889 );
76890 }
76891
76892 $suffixes = array('');
76893 if ('\\' === \DIRECTORY_SEPARATOR) {
76894 $pathExt = getenv('PATHEXT');
76895 $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
76896 }
76897 foreach ($suffixes as $suffix) {
76898 foreach ($dirs as $dir) {
76899 if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
76900 return $file;
76901 }
76902 }
76903 }
76904
76905 return $default;
76906 }
76907 }
76908 Copyright (c) 2004-2018 Fabien Potencier
76909
76910 Permission is hereby granted, free of charge, to any person obtaining a copy
76911 of this software and associated documentation files (the "Software"), to deal
76912 in the Software without restriction, including without limitation the rights
76913 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
76914 copies of the Software, and to permit persons to whom the Software is furnished
76915 to do so, subject to the following conditions:
76916
76917 The above copyright notice and this permission notice shall be included in all
76918 copies or substantial portions of the Software.
76919
76920 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76921 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76922 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
76923 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76924 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76925 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
76926 THE SOFTWARE.
76927 <?php
76928
76929
76930
76931
76932
76933
76934
76935
76936
76937
76938 namespace Symfony\Component\Process;
76939
76940
76941
76942
76943
76944
76945
76946 class PhpExecutableFinder
76947 {
76948 private $executableFinder;
76949
76950 public function __construct()
76951 {
76952 $this->executableFinder = new ExecutableFinder();
76953 }
76954
76955
76956
76957
76958
76959
76960
76961
76962 public function find($includeArgs = true)
76963 {
76964 $args = $this->findArguments();
76965 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
76966
76967
76968  if (\defined('HHVM_VERSION')) {
76969 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
76970 }
76971
76972
76973  if (\defined('PHP_BINARY') && PHP_BINARY && \in_array(\PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) {
76974 return PHP_BINARY.$args;
76975 }
76976
76977 if ($php = getenv('PHP_PATH')) {
76978 if (!@is_executable($php)) {
76979 return false;
76980 }
76981
76982 return $php;
76983 }
76984
76985 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
76986 if (@is_executable($php)) {
76987 return $php;
76988 }
76989 }
76990
76991 if (@is_executable($php = PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
76992 return $php;
76993 }
76994
76995 $dirs = array(PHP_BINDIR);
76996 if ('\\' === \DIRECTORY_SEPARATOR) {
76997 $dirs[] = 'C:\xampp\php\\';
76998 }
76999
77000 return $this->executableFinder->find('php', false, $dirs);
77001 }
77002
77003
77004
77005
77006
77007
77008 public function findArguments()
77009 {
77010 $arguments = array();
77011
77012 if (\defined('HHVM_VERSION')) {
77013 $arguments[] = '--php';
77014 } elseif ('phpdbg' === \PHP_SAPI) {
77015 $arguments[] = '-qrr';
77016 }
77017
77018 return $arguments;
77019 }
77020 }
77021 <?php
77022
77023
77024
77025
77026
77027
77028
77029
77030
77031
77032 namespace Symfony\Component\Process;
77033
77034 use Symfony\Component\Process\Exception\RuntimeException;
77035
77036
77037
77038
77039
77040
77041
77042
77043
77044
77045 class PhpProcess extends Process
77046 {
77047
77048
77049
77050
77051
77052
77053
77054 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
77055 {
77056 $executableFinder = new PhpExecutableFinder();
77057 if (false === $php = $executableFinder->find()) {
77058 $php = null;
77059 }
77060 if ('phpdbg' === \PHP_SAPI) {
77061 $file = tempnam(sys_get_temp_dir(), 'dbg');
77062 file_put_contents($file, $script);
77063 register_shutdown_function('unlink', $file);
77064 $php .= ' '.ProcessUtils::escapeArgument($file);
77065 $script = null;
77066 }
77067 if ('\\' !== \DIRECTORY_SEPARATOR && null !== $php) {
77068
77069  
77070  
77071  $php = 'exec '.$php;
77072 }
77073
77074 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
77075 }
77076
77077
77078
77079
77080 public function setPhpBinary($php)
77081 {
77082 $this->setCommandLine($php);
77083 }
77084
77085
77086
77087
77088 public function start($callback = null)
77089 {
77090 if (null === $this->getCommandLine()) {
77091 throw new RuntimeException('Unable to find the PHP executable.');
77092 }
77093
77094 parent::start($callback);
77095 }
77096 }
77097 <?php
77098
77099
77100
77101
77102
77103
77104
77105
77106
77107
77108 namespace Symfony\Component\Process\Pipes;
77109
77110
77111
77112
77113
77114
77115 abstract class AbstractPipes implements PipesInterface
77116 {
77117 public $pipes = array();
77118
77119 private $inputBuffer = '';
77120 private $input;
77121 private $blocked = true;
77122 private $lastError;
77123
77124
77125
77126
77127 public function __construct($input)
77128 {
77129 if (\is_resource($input)) {
77130 $this->input = $input;
77131 } elseif (\is_string($input)) {
77132 $this->inputBuffer = $input;
77133 } else {
77134 $this->inputBuffer = (string) $input;
77135 }
77136 }
77137
77138
77139
77140
77141 public function close()
77142 {
77143 foreach ($this->pipes as $pipe) {
77144 fclose($pipe);
77145 }
77146 $this->pipes = array();
77147 }
77148
77149
77150
77151
77152
77153
77154 protected function hasSystemCallBeenInterrupted()
77155 {
77156 $lastError = $this->lastError;
77157 $this->lastError = null;
77158
77159
77160  return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
77161 }
77162
77163
77164
77165
77166 protected function unblock()
77167 {
77168 if (!$this->blocked) {
77169 return;
77170 }
77171
77172 foreach ($this->pipes as $pipe) {
77173 stream_set_blocking($pipe, 0);
77174 }
77175 if (null !== $this->input) {
77176 stream_set_blocking($this->input, 0);
77177 }
77178
77179 $this->blocked = false;
77180 }
77181
77182
77183
77184
77185 protected function write()
77186 {
77187 if (!isset($this->pipes[0])) {
77188 return;
77189 }
77190 $input = $this->input;
77191 $r = $e = array();
77192 $w = array($this->pipes[0]);
77193
77194
77195  if (false === @stream_select($r, $w, $e, 0, 0)) {
77196 return;
77197 }
77198
77199 foreach ($w as $stdin) {
77200 if (isset($this->inputBuffer[0])) {
77201 $written = fwrite($stdin, $this->inputBuffer);
77202 $this->inputBuffer = substr($this->inputBuffer, $written);
77203 if (isset($this->inputBuffer[0])) {
77204 return array($this->pipes[0]);
77205 }
77206 }
77207
77208 if ($input) {
77209 for (;;) {
77210 $data = fread($input, self::CHUNK_SIZE);
77211 if (!isset($data[0])) {
77212 break;
77213 }
77214 $written = fwrite($stdin, $data);
77215 $data = substr($data, $written);
77216 if (isset($data[0])) {
77217 $this->inputBuffer = $data;
77218
77219 return array($this->pipes[0]);
77220 }
77221 }
77222 if (feof($input)) {
77223
77224  
77225  $this->input = null;
77226 }
77227 }
77228 }
77229
77230
77231  if (null === $this->input && !isset($this->inputBuffer[0])) {
77232 fclose($this->pipes[0]);
77233 unset($this->pipes[0]);
77234 } elseif (!$w) {
77235 return array($this->pipes[0]);
77236 }
77237 }
77238
77239
77240
77241
77242 public function handleError($type, $msg)
77243 {
77244 $this->lastError = $msg;
77245 }
77246 }
77247 <?php
77248
77249
77250
77251
77252
77253
77254
77255
77256
77257
77258 namespace Symfony\Component\Process\Pipes;
77259
77260
77261
77262
77263
77264
77265
77266
77267 interface PipesInterface
77268 {
77269 const CHUNK_SIZE = 16384;
77270
77271
77272
77273
77274
77275
77276 public function getDescriptors();
77277
77278
77279
77280
77281
77282
77283 public function getFiles();
77284
77285
77286
77287
77288
77289
77290
77291
77292
77293 public function readAndWrite($blocking, $close = false);
77294
77295
77296
77297
77298
77299
77300 public function areOpen();
77301
77302
77303
77304
77305 public function close();
77306 }
77307 <?php
77308
77309
77310
77311
77312
77313
77314
77315
77316
77317
77318 namespace Symfony\Component\Process\Pipes;
77319
77320 use Symfony\Component\Process\Process;
77321
77322
77323
77324
77325
77326
77327
77328
77329 class UnixPipes extends AbstractPipes
77330 {
77331 private $ttyMode;
77332 private $ptyMode;
77333 private $disableOutput;
77334
77335 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
77336 {
77337 $this->ttyMode = (bool) $ttyMode;
77338 $this->ptyMode = (bool) $ptyMode;
77339 $this->disableOutput = (bool) $disableOutput;
77340
77341 parent::__construct($input);
77342 }
77343
77344 public function __destruct()
77345 {
77346 $this->close();
77347 }
77348
77349
77350
77351
77352 public function getDescriptors()
77353 {
77354 if ($this->disableOutput) {
77355 $nullstream = fopen('/dev/null', 'c');
77356
77357 return array(
77358 array('pipe', 'r'),
77359 $nullstream,
77360 $nullstream,
77361 );
77362 }
77363
77364 if ($this->ttyMode) {
77365 return array(
77366 array('file', '/dev/tty', 'r'),
77367 array('file', '/dev/tty', 'w'),
77368 array('file', '/dev/tty', 'w'),
77369 );
77370 }
77371
77372 if ($this->ptyMode && Process::isPtySupported()) {
77373 return array(
77374 array('pty'),
77375 array('pty'),
77376 array('pty'),
77377 );
77378 }
77379
77380 return array(
77381 array('pipe', 'r'),
77382 array('pipe', 'w'), 
77383  array('pipe', 'w'), 
77384  );
77385 }
77386
77387
77388
77389
77390 public function getFiles()
77391 {
77392 return array();
77393 }
77394
77395
77396
77397
77398 public function readAndWrite($blocking, $close = false)
77399 {
77400 $this->unblock();
77401 $w = $this->write();
77402
77403 $read = $e = array();
77404 $r = $this->pipes;
77405 unset($r[0]);
77406
77407
77408  set_error_handler(array($this, 'handleError'));
77409 if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
77410 restore_error_handler();
77411
77412  
77413  if (!$this->hasSystemCallBeenInterrupted()) {
77414 $this->pipes = array();
77415 }
77416
77417 return $read;
77418 }
77419 restore_error_handler();
77420
77421 foreach ($r as $pipe) {
77422
77423  
77424  $read[$type = array_search($pipe, $this->pipes, true)] = '';
77425
77426 do {
77427 $data = fread($pipe, self::CHUNK_SIZE);
77428 $read[$type] .= $data;
77429 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
77430
77431 if (!isset($read[$type][0])) {
77432 unset($read[$type]);
77433 }
77434
77435 if ($close && feof($pipe)) {
77436 fclose($pipe);
77437 unset($this->pipes[$type]);
77438 }
77439 }
77440
77441 return $read;
77442 }
77443
77444
77445
77446
77447 public function areOpen()
77448 {
77449 return (bool) $this->pipes;
77450 }
77451
77452
77453
77454
77455
77456
77457
77458
77459
77460 public static function create(Process $process, $input)
77461 {
77462 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
77463 }
77464 }
77465 <?php
77466
77467
77468
77469
77470
77471
77472
77473
77474
77475
77476 namespace Symfony\Component\Process\Pipes;
77477
77478 use Symfony\Component\Process\Exception\RuntimeException;
77479 use Symfony\Component\Process\Process;
77480
77481
77482
77483
77484
77485
77486
77487
77488
77489
77490
77491 class WindowsPipes extends AbstractPipes
77492 {
77493 private $files = array();
77494 private $fileHandles = array();
77495 private $lockHandles = array();
77496 private $readBytes = array(
77497 Process::STDOUT => 0,
77498 Process::STDERR => 0,
77499 );
77500 private $disableOutput;
77501
77502 public function __construct($disableOutput, $input)
77503 {
77504 $this->disableOutput = (bool) $disableOutput;
77505
77506 if (!$this->disableOutput) {
77507
77508  
77509  
77510  
77511  $pipes = array(
77512 Process::STDOUT => Process::OUT,
77513 Process::STDERR => Process::ERR,
77514 );
77515 $tmpDir = sys_get_temp_dir();
77516 $lastError = 'unknown reason';
77517 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
77518 for ($i = 0;; ++$i) {
77519 foreach ($pipes as $pipe => $name) {
77520 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
77521
77522 if (!$h = fopen($file.'.lock', 'w')) {
77523 restore_error_handler();
77524 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $lastError));
77525 }
77526 if (!flock($h, LOCK_EX | LOCK_NB)) {
77527 continue 2;
77528 }
77529 if (isset($this->lockHandles[$pipe])) {
77530 flock($this->lockHandles[$pipe], LOCK_UN);
77531 fclose($this->lockHandles[$pipe]);
77532 }
77533 $this->lockHandles[$pipe] = $h;
77534
77535 if (!fclose(fopen($file, 'w')) || !$h = fopen($file, 'r')) {
77536 flock($this->lockHandles[$pipe], LOCK_UN);
77537 fclose($this->lockHandles[$pipe]);
77538 unset($this->lockHandles[$pipe]);
77539 continue 2;
77540 }
77541 $this->fileHandles[$pipe] = $h;
77542 $this->files[$pipe] = $file;
77543 }
77544 break;
77545 }
77546 restore_error_handler();
77547 }
77548
77549 parent::__construct($input);
77550 }
77551
77552 public function __destruct()
77553 {
77554 $this->close();
77555 }
77556
77557
77558
77559
77560 public function getDescriptors()
77561 {
77562 if ($this->disableOutput) {
77563 $nullstream = fopen('NUL', 'c');
77564
77565 return array(
77566 array('pipe', 'r'),
77567 $nullstream,
77568 $nullstream,
77569 );
77570 }
77571
77572
77573  
77574  
77575  return array(
77576 array('pipe', 'r'),
77577 array('file', 'NUL', 'w'),
77578 array('file', 'NUL', 'w'),
77579 );
77580 }
77581
77582
77583
77584
77585 public function getFiles()
77586 {
77587 return $this->files;
77588 }
77589
77590
77591
77592
77593 public function readAndWrite($blocking, $close = false)
77594 {
77595 $this->unblock();
77596 $w = $this->write();
77597 $read = $r = $e = array();
77598
77599 if ($blocking) {
77600 if ($w) {
77601 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
77602 } elseif ($this->fileHandles) {
77603 usleep(Process::TIMEOUT_PRECISION * 1E6);
77604 }
77605 }
77606 foreach ($this->fileHandles as $type => $fileHandle) {
77607 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
77608
77609 if (isset($data[0])) {
77610 $this->readBytes[$type] += \strlen($data);
77611 $read[$type] = $data;
77612 }
77613 if ($close) {
77614 ftruncate($fileHandle, 0);
77615 fclose($fileHandle);
77616 flock($this->lockHandles[$type], LOCK_UN);
77617 fclose($this->lockHandles[$type]);
77618 unset($this->fileHandles[$type], $this->lockHandles[$type]);
77619 }
77620 }
77621
77622 return $read;
77623 }
77624
77625
77626
77627
77628 public function areOpen()
77629 {
77630 return $this->pipes && $this->fileHandles;
77631 }
77632
77633
77634
77635
77636 public function close()
77637 {
77638 parent::close();
77639 foreach ($this->fileHandles as $type => $handle) {
77640 ftruncate($handle, 0);
77641 fclose($handle);
77642 flock($this->lockHandles[$type], LOCK_UN);
77643 fclose($this->lockHandles[$type]);
77644 }
77645 $this->fileHandles = $this->lockHandles = array();
77646 }
77647
77648
77649
77650
77651
77652
77653
77654
77655
77656 public static function create(Process $process, $input)
77657 {
77658 return new static($process->isOutputDisabled(), $input);
77659 }
77660 }
77661 <?php
77662
77663
77664
77665
77666
77667
77668
77669
77670
77671
77672 namespace Symfony\Component\Process;
77673
77674 use Symfony\Component\Process\Exception\InvalidArgumentException;
77675 use Symfony\Component\Process\Exception\LogicException;
77676 use Symfony\Component\Process\Exception\ProcessFailedException;
77677 use Symfony\Component\Process\Exception\ProcessTimedOutException;
77678 use Symfony\Component\Process\Exception\RuntimeException;
77679 use Symfony\Component\Process\Pipes\PipesInterface;
77680 use Symfony\Component\Process\Pipes\UnixPipes;
77681 use Symfony\Component\Process\Pipes\WindowsPipes;
77682
77683
77684
77685
77686
77687
77688
77689
77690 class Process
77691 {
77692 const ERR = 'err';
77693 const OUT = 'out';
77694
77695 const STATUS_READY = 'ready';
77696 const STATUS_STARTED = 'started';
77697 const STATUS_TERMINATED = 'terminated';
77698
77699 const STDIN = 0;
77700 const STDOUT = 1;
77701 const STDERR = 2;
77702
77703
77704  const TIMEOUT_PRECISION = 0.2;
77705
77706 private $callback;
77707 private $commandline;
77708 private $cwd;
77709 private $env;
77710 private $input;
77711 private $starttime;
77712 private $lastOutputTime;
77713 private $timeout;
77714 private $idleTimeout;
77715 private $options;
77716 private $exitcode;
77717 private $fallbackStatus = array();
77718 private $processInformation;
77719 private $outputDisabled = false;
77720 private $stdout;
77721 private $stderr;
77722 private $enhanceWindowsCompatibility = true;
77723 private $enhanceSigchildCompatibility;
77724 private $process;
77725 private $status = self::STATUS_READY;
77726 private $incrementalOutputOffset = 0;
77727 private $incrementalErrorOutputOffset = 0;
77728 private $tty;
77729 private $pty;
77730
77731 private $useFileHandles = false;
77732
77733 private $processPipes;
77734
77735 private $latestSignal;
77736
77737 private static $sigchild;
77738
77739
77740
77741
77742
77743
77744 public static $exitCodes = array(
77745 0 => 'OK',
77746 1 => 'General error',
77747 2 => 'Misuse of shell builtins',
77748
77749 126 => 'Invoked command cannot execute',
77750 127 => 'Command not found',
77751 128 => 'Invalid exit argument',
77752
77753
77754  129 => 'Hangup',
77755 130 => 'Interrupt',
77756 131 => 'Quit and dump core',
77757 132 => 'Illegal instruction',
77758 133 => 'Trace/breakpoint trap',
77759 134 => 'Process aborted',
77760 135 => 'Bus error: "access to undefined portion of memory object"',
77761 136 => 'Floating point exception: "erroneous arithmetic operation"',
77762 137 => 'Kill (terminate immediately)',
77763 138 => 'User-defined 1',
77764 139 => 'Segmentation violation',
77765 140 => 'User-defined 2',
77766 141 => 'Write to pipe with no one reading',
77767 142 => 'Signal raised by alarm',
77768 143 => 'Termination (request to terminate)',
77769
77770  145 => 'Child process terminated, stopped (or continued*)',
77771 146 => 'Continue if stopped',
77772 147 => 'Stop executing temporarily',
77773 148 => 'Terminal stop signal',
77774 149 => 'Background process attempting to read from tty ("in")',
77775 150 => 'Background process attempting to write to tty ("out")',
77776 151 => 'Urgent data available on socket',
77777 152 => 'CPU time limit exceeded',
77778 153 => 'File size limit exceeded',
77779 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
77780 155 => 'Profiling timer expired',
77781
77782  157 => 'Pollable event',
77783
77784  159 => 'Bad syscall',
77785 );
77786
77787
77788
77789
77790
77791
77792
77793
77794
77795
77796
77797 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
77798 {
77799 if (!\function_exists('proc_open')) {
77800 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
77801 }
77802
77803 $this->commandline = $commandline;
77804 $this->cwd = $cwd;
77805
77806
77807  
77808  
77809  
77810  if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
77811 $this->cwd = getcwd();
77812 }
77813 if (null !== $env) {
77814 $this->setEnv($env);
77815 }
77816
77817 $this->setInput($input);
77818 $this->setTimeout($timeout);
77819 $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR;
77820 $this->pty = false;
77821 $this->enhanceSigchildCompatibility = '\\' !== \DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
77822 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
77823 }
77824
77825 public function __destruct()
77826 {
77827 $this->stop(0);
77828 }
77829
77830 public function __clone()
77831 {
77832 $this->resetProcessData();
77833 }
77834
77835
77836
77837
77838
77839
77840
77841
77842
77843
77844
77845
77846
77847
77848
77849
77850
77851
77852
77853
77854 public function run($callback = null)
77855 {
77856 $this->start($callback);
77857
77858 return $this->wait();
77859 }
77860
77861
77862
77863
77864
77865
77866
77867
77868
77869
77870
77871
77872
77873
77874 public function mustRun($callback = null)
77875 {
77876 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
77877 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
77878 }
77879
77880 if (0 !== $this->run($callback)) {
77881 throw new ProcessFailedException($this);
77882 }
77883
77884 return $this;
77885 }
77886
77887
77888
77889
77890
77891
77892
77893
77894
77895
77896
77897
77898
77899
77900
77901
77902
77903
77904
77905
77906 public function start($callback = null)
77907 {
77908 if ($this->isRunning()) {
77909 throw new RuntimeException('Process is already running');
77910 }
77911 if ($this->outputDisabled && null !== $callback) {
77912 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
77913 }
77914
77915 $this->resetProcessData();
77916 $this->starttime = $this->lastOutputTime = microtime(true);
77917 $this->callback = $this->buildCallback($callback);
77918 $descriptors = $this->getDescriptors();
77919
77920 $commandline = $this->commandline;
77921
77922 if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
77923 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
77924 foreach ($this->processPipes->getFiles() as $offset => $filename) {
77925 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
77926 }
77927 $commandline .= '"';
77928
77929 if (!isset($this->options['bypass_shell'])) {
77930 $this->options['bypass_shell'] = true;
77931 }
77932 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
77933
77934  $descriptors[3] = array('pipe', 'w');
77935
77936
77937  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
77938 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
77939
77940
77941  
77942  $ptsWorkaround = fopen(__FILE__, 'r');
77943 }
77944
77945 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
77946
77947 if (!\is_resource($this->process)) {
77948 throw new RuntimeException('Unable to launch a new process.');
77949 }
77950 $this->status = self::STATUS_STARTED;
77951
77952 if (isset($descriptors[3])) {
77953 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
77954 }
77955
77956 if ($this->tty) {
77957 return;
77958 }
77959
77960 $this->updateStatus(false);
77961 $this->checkTimeout();
77962 }
77963
77964
77965
77966
77967
77968
77969
77970
77971
77972
77973
77974
77975
77976
77977
77978
77979 public function restart($callback = null)
77980 {
77981 if ($this->isRunning()) {
77982 throw new RuntimeException('Process is already running');
77983 }
77984
77985 $process = clone $this;
77986 $process->start($callback);
77987
77988 return $process;
77989 }
77990
77991
77992
77993
77994
77995
77996
77997
77998
77999
78000
78001
78002
78003
78004
78005
78006 public function wait($callback = null)
78007 {
78008 $this->requireProcessIsStarted(__FUNCTION__);
78009
78010 $this->updateStatus(false);
78011 if (null !== $callback) {
78012 $this->callback = $this->buildCallback($callback);
78013 }
78014
78015 do {
78016 $this->checkTimeout();
78017 $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
78018 $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
78019 } while ($running);
78020
78021 while ($this->isRunning()) {
78022 usleep(1000);
78023 }
78024
78025 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
78026 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
78027 }
78028
78029 return $this->exitcode;
78030 }
78031
78032
78033
78034
78035
78036
78037 public function getPid()
78038 {
78039 return $this->isRunning() ? $this->processInformation['pid'] : null;
78040 }
78041
78042
78043
78044
78045
78046
78047
78048
78049
78050
78051
78052
78053 public function signal($signal)
78054 {
78055 $this->doSignal($signal, true);
78056
78057 return $this;
78058 }
78059
78060
78061
78062
78063
78064
78065
78066
78067
78068 public function disableOutput()
78069 {
78070 if ($this->isRunning()) {
78071 throw new RuntimeException('Disabling output while the process is running is not possible.');
78072 }
78073 if (null !== $this->idleTimeout) {
78074 throw new LogicException('Output can not be disabled while an idle timeout is set.');
78075 }
78076
78077 $this->outputDisabled = true;
78078
78079 return $this;
78080 }
78081
78082
78083
78084
78085
78086
78087
78088
78089 public function enableOutput()
78090 {
78091 if ($this->isRunning()) {
78092 throw new RuntimeException('Enabling output while the process is running is not possible.');
78093 }
78094
78095 $this->outputDisabled = false;
78096
78097 return $this;
78098 }
78099
78100
78101
78102
78103
78104
78105 public function isOutputDisabled()
78106 {
78107 return $this->outputDisabled;
78108 }
78109
78110
78111
78112
78113
78114
78115
78116
78117
78118 public function getOutput()
78119 {
78120 $this->readPipesForOutput(__FUNCTION__);
78121
78122 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
78123 return '';
78124 }
78125
78126 return $ret;
78127 }
78128
78129
78130
78131
78132
78133
78134
78135
78136
78137
78138
78139
78140 public function getIncrementalOutput()
78141 {
78142 $this->readPipesForOutput(__FUNCTION__);
78143
78144 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
78145 $this->incrementalOutputOffset = ftell($this->stdout);
78146
78147 if (false === $latest) {
78148 return '';
78149 }
78150
78151 return $latest;
78152 }
78153
78154
78155
78156
78157
78158
78159 public function clearOutput()
78160 {
78161 ftruncate($this->stdout, 0);
78162 fseek($this->stdout, 0);
78163 $this->incrementalOutputOffset = 0;
78164
78165 return $this;
78166 }
78167
78168
78169
78170
78171
78172
78173
78174
78175
78176 public function getErrorOutput()
78177 {
78178 $this->readPipesForOutput(__FUNCTION__);
78179
78180 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
78181 return '';
78182 }
78183
78184 return $ret;
78185 }
78186
78187
78188
78189
78190
78191
78192
78193
78194
78195
78196
78197
78198
78199 public function getIncrementalErrorOutput()
78200 {
78201 $this->readPipesForOutput(__FUNCTION__);
78202
78203 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
78204 $this->incrementalErrorOutputOffset = ftell($this->stderr);
78205
78206 if (false === $latest) {
78207 return '';
78208 }
78209
78210 return $latest;
78211 }
78212
78213
78214
78215
78216
78217
78218 public function clearErrorOutput()
78219 {
78220 ftruncate($this->stderr, 0);
78221 fseek($this->stderr, 0);
78222 $this->incrementalErrorOutputOffset = 0;
78223
78224 return $this;
78225 }
78226
78227
78228
78229
78230
78231
78232
78233
78234 public function getExitCode()
78235 {
78236 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
78237 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
78238 }
78239
78240 $this->updateStatus(false);
78241
78242 return $this->exitcode;
78243 }
78244
78245
78246
78247
78248
78249
78250
78251
78252
78253
78254
78255
78256 public function getExitCodeText()
78257 {
78258 if (null === $exitcode = $this->getExitCode()) {
78259 return;
78260 }
78261
78262 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
78263 }
78264
78265
78266
78267
78268
78269
78270 public function isSuccessful()
78271 {
78272 return 0 === $this->getExitCode();
78273 }
78274
78275
78276
78277
78278
78279
78280
78281
78282
78283
78284
78285 public function hasBeenSignaled()
78286 {
78287 $this->requireProcessIsTerminated(__FUNCTION__);
78288
78289 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
78290 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
78291 }
78292
78293 return $this->processInformation['signaled'];
78294 }
78295
78296
78297
78298
78299
78300
78301
78302
78303
78304
78305
78306 public function getTermSignal()
78307 {
78308 $this->requireProcessIsTerminated(__FUNCTION__);
78309
78310 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
78311 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
78312 }
78313
78314 return $this->processInformation['termsig'];
78315 }
78316
78317
78318
78319
78320
78321
78322
78323
78324
78325
78326 public function hasBeenStopped()
78327 {
78328 $this->requireProcessIsTerminated(__FUNCTION__);
78329
78330 return $this->processInformation['stopped'];
78331 }
78332
78333
78334
78335
78336
78337
78338
78339
78340
78341
78342 public function getStopSignal()
78343 {
78344 $this->requireProcessIsTerminated(__FUNCTION__);
78345
78346 return $this->processInformation['stopsig'];
78347 }
78348
78349
78350
78351
78352
78353
78354 public function isRunning()
78355 {
78356 if (self::STATUS_STARTED !== $this->status) {
78357 return false;
78358 }
78359
78360 $this->updateStatus(false);
78361
78362 return $this->processInformation['running'];
78363 }
78364
78365
78366
78367
78368
78369
78370 public function isStarted()
78371 {
78372 return self::STATUS_READY != $this->status;
78373 }
78374
78375
78376
78377
78378
78379
78380 public function isTerminated()
78381 {
78382 $this->updateStatus(false);
78383
78384 return self::STATUS_TERMINATED == $this->status;
78385 }
78386
78387
78388
78389
78390
78391
78392
78393
78394 public function getStatus()
78395 {
78396 $this->updateStatus(false);
78397
78398 return $this->status;
78399 }
78400
78401
78402
78403
78404
78405
78406
78407
78408
78409 public function stop($timeout = 10, $signal = null)
78410 {
78411 $timeoutMicro = microtime(true) + $timeout;
78412 if ($this->isRunning()) {
78413
78414  $this->doSignal(15, false);
78415 do {
78416 usleep(1000);
78417 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
78418
78419 if ($this->isRunning()) {
78420
78421  
78422  $this->doSignal($signal ?: 9, false);
78423 }
78424 }
78425
78426 if ($this->isRunning()) {
78427 if (isset($this->fallbackStatus['pid'])) {
78428 unset($this->fallbackStatus['pid']);
78429
78430 return $this->stop(0, $signal);
78431 }
78432 $this->close();
78433 }
78434
78435 return $this->exitcode;
78436 }
78437
78438
78439
78440
78441
78442
78443
78444
78445 public function addOutput($line)
78446 {
78447 $this->lastOutputTime = microtime(true);
78448
78449 fseek($this->stdout, 0, SEEK_END);
78450 fwrite($this->stdout, $line);
78451 fseek($this->stdout, $this->incrementalOutputOffset);
78452 }
78453
78454
78455
78456
78457
78458
78459
78460
78461 public function addErrorOutput($line)
78462 {
78463 $this->lastOutputTime = microtime(true);
78464
78465 fseek($this->stderr, 0, SEEK_END);
78466 fwrite($this->stderr, $line);
78467 fseek($this->stderr, $this->incrementalErrorOutputOffset);
78468 }
78469
78470
78471
78472
78473
78474
78475 public function getCommandLine()
78476 {
78477 return $this->commandline;
78478 }
78479
78480
78481
78482
78483
78484
78485
78486
78487 public function setCommandLine($commandline)
78488 {
78489 $this->commandline = $commandline;
78490
78491 return $this;
78492 }
78493
78494
78495
78496
78497
78498
78499 public function getTimeout()
78500 {
78501 return $this->timeout;
78502 }
78503
78504
78505
78506
78507
78508
78509 public function getIdleTimeout()
78510 {
78511 return $this->idleTimeout;
78512 }
78513
78514
78515
78516
78517
78518
78519
78520
78521
78522
78523
78524
78525 public function setTimeout($timeout)
78526 {
78527 $this->timeout = $this->validateTimeout($timeout);
78528
78529 return $this;
78530 }
78531
78532
78533
78534
78535
78536
78537
78538
78539
78540
78541
78542
78543
78544 public function setIdleTimeout($timeout)
78545 {
78546 if (null !== $timeout && $this->outputDisabled) {
78547 throw new LogicException('Idle timeout can not be set while the output is disabled.');
78548 }
78549
78550 $this->idleTimeout = $this->validateTimeout($timeout);
78551
78552 return $this;
78553 }
78554
78555
78556
78557
78558
78559
78560
78561
78562
78563
78564 public function setTty($tty)
78565 {
78566 if ('\\' === \DIRECTORY_SEPARATOR && $tty) {
78567 throw new RuntimeException('TTY mode is not supported on Windows platform.');
78568 }
78569 if ($tty) {
78570 static $isTtySupported;
78571
78572 if (null === $isTtySupported) {
78573 $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);
78574 }
78575
78576 if (!$isTtySupported) {
78577 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
78578 }
78579 }
78580
78581 $this->tty = (bool) $tty;
78582
78583 return $this;
78584 }
78585
78586
78587
78588
78589
78590
78591 public function isTty()
78592 {
78593 return $this->tty;
78594 }
78595
78596
78597
78598
78599
78600
78601
78602
78603 public function setPty($bool)
78604 {
78605 $this->pty = (bool) $bool;
78606
78607 return $this;
78608 }
78609
78610
78611
78612
78613
78614
78615 public function isPty()
78616 {
78617 return $this->pty;
78618 }
78619
78620
78621
78622
78623
78624
78625 public function getWorkingDirectory()
78626 {
78627 if (null === $this->cwd) {
78628
78629  
78630  return getcwd() ?: null;
78631 }
78632
78633 return $this->cwd;
78634 }
78635
78636
78637
78638
78639
78640
78641
78642
78643 public function setWorkingDirectory($cwd)
78644 {
78645 $this->cwd = $cwd;
78646
78647 return $this;
78648 }
78649
78650
78651
78652
78653
78654
78655 public function getEnv()
78656 {
78657 return $this->env;
78658 }
78659
78660
78661
78662
78663
78664
78665
78666
78667
78668
78669
78670
78671
78672
78673 public function setEnv(array $env)
78674 {
78675
78676  $env = array_filter($env, function ($value) {
78677 return !\is_array($value);
78678 });
78679
78680 $this->env = array();
78681 foreach ($env as $key => $value) {
78682 $this->env[$key] = (string) $value;
78683 }
78684
78685 return $this;
78686 }
78687
78688
78689
78690
78691
78692
78693
78694
78695
78696
78697 public function getStdin()
78698 {
78699 @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);
78700
78701 return $this->getInput();
78702 }
78703
78704
78705
78706
78707
78708
78709 public function getInput()
78710 {
78711 return $this->input;
78712 }
78713
78714
78715
78716
78717
78718
78719
78720
78721
78722
78723
78724
78725
78726
78727 public function setStdin($stdin)
78728 {
78729 @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);
78730
78731 return $this->setInput($stdin);
78732 }
78733
78734
78735
78736
78737
78738
78739
78740
78741
78742
78743
78744
78745
78746
78747 public function setInput($input)
78748 {
78749 if ($this->isRunning()) {
78750 throw new LogicException('Input can not be set while the process is running.');
78751 }
78752
78753 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
78754
78755 return $this;
78756 }
78757
78758
78759
78760
78761
78762
78763 public function getOptions()
78764 {
78765 return $this->options;
78766 }
78767
78768
78769
78770
78771
78772
78773
78774
78775 public function setOptions(array $options)
78776 {
78777 $this->options = $options;
78778
78779 return $this;
78780 }
78781
78782
78783
78784
78785
78786
78787
78788
78789 public function getEnhanceWindowsCompatibility()
78790 {
78791 return $this->enhanceWindowsCompatibility;
78792 }
78793
78794
78795
78796
78797
78798
78799
78800
78801 public function setEnhanceWindowsCompatibility($enhance)
78802 {
78803 $this->enhanceWindowsCompatibility = (bool) $enhance;
78804
78805 return $this;
78806 }
78807
78808
78809
78810
78811
78812
78813 public function getEnhanceSigchildCompatibility()
78814 {
78815 return $this->enhanceSigchildCompatibility;
78816 }
78817
78818
78819
78820
78821
78822
78823
78824
78825
78826
78827
78828
78829 public function setEnhanceSigchildCompatibility($enhance)
78830 {
78831 $this->enhanceSigchildCompatibility = (bool) $enhance;
78832
78833 return $this;
78834 }
78835
78836
78837
78838
78839
78840
78841
78842
78843
78844 public function checkTimeout()
78845 {
78846 if (self::STATUS_STARTED !== $this->status) {
78847 return;
78848 }
78849
78850 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
78851 $this->stop(0);
78852
78853 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
78854 }
78855
78856 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
78857 $this->stop(0);
78858
78859 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
78860 }
78861 }
78862
78863
78864
78865
78866
78867
78868 public static function isPtySupported()
78869 {
78870 static $result;
78871
78872 if (null !== $result) {
78873 return $result;
78874 }
78875
78876 if ('\\' === \DIRECTORY_SEPARATOR) {
78877 return $result = false;
78878 }
78879
78880 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
78881 }
78882
78883
78884
78885
78886
78887
78888 private function getDescriptors()
78889 {
78890 if ('\\' === \DIRECTORY_SEPARATOR) {
78891 $this->processPipes = WindowsPipes::create($this, $this->input);
78892 } else {
78893 $this->processPipes = UnixPipes::create($this, $this->input);
78894 }
78895
78896 return $this->processPipes->getDescriptors();
78897 }
78898
78899
78900
78901
78902
78903
78904
78905
78906
78907
78908
78909 protected function buildCallback($callback)
78910 {
78911 $that = $this;
78912 $out = self::OUT;
78913 $callback = function ($type, $data) use ($that, $callback, $out) {
78914 if ($out == $type) {
78915 $that->addOutput($data);
78916 } else {
78917 $that->addErrorOutput($data);
78918 }
78919
78920 if (null !== $callback) {
78921 \call_user_func($callback, $type, $data);
78922 }
78923 };
78924
78925 return $callback;
78926 }
78927
78928
78929
78930
78931
78932
78933 protected function updateStatus($blocking)
78934 {
78935 if (self::STATUS_STARTED !== $this->status) {
78936 return;
78937 }
78938
78939 $this->processInformation = proc_get_status($this->process);
78940 $running = $this->processInformation['running'];
78941
78942 $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);
78943
78944 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
78945 $this->processInformation = $this->fallbackStatus + $this->processInformation;
78946 }
78947
78948 if (!$running) {
78949 $this->close();
78950 }
78951 }
78952
78953
78954
78955
78956
78957
78958 protected function isSigchildEnabled()
78959 {
78960 if (null !== self::$sigchild) {
78961 return self::$sigchild;
78962 }
78963
78964 if (!\function_exists('phpinfo') || \defined('HHVM_VERSION')) {
78965 return self::$sigchild = false;
78966 }
78967
78968 ob_start();
78969 phpinfo(INFO_GENERAL);
78970
78971 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
78972 }
78973
78974
78975
78976
78977
78978
78979
78980
78981 private function readPipesForOutput($caller)
78982 {
78983 if ($this->outputDisabled) {
78984 throw new LogicException('Output has been disabled.');
78985 }
78986
78987 $this->requireProcessIsStarted($caller);
78988
78989 $this->updateStatus(false);
78990 }
78991
78992
78993
78994
78995
78996
78997
78998
78999
79000
79001 private function validateTimeout($timeout)
79002 {
79003 $timeout = (float) $timeout;
79004
79005 if (0.0 === $timeout) {
79006 $timeout = null;
79007 } elseif ($timeout < 0) {
79008 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
79009 }
79010
79011 return $timeout;
79012 }
79013
79014
79015
79016
79017
79018
79019
79020 private function readPipes($blocking, $close)
79021 {
79022 $result = $this->processPipes->readAndWrite($blocking, $close);
79023
79024 $callback = $this->callback;
79025 foreach ($result as $type => $data) {
79026 if (3 !== $type) {
79027 $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
79028 } elseif (!isset($this->fallbackStatus['signaled'])) {
79029 $this->fallbackStatus['exitcode'] = (int) $data;
79030 }
79031 }
79032 }
79033
79034
79035
79036
79037
79038
79039 private function close()
79040 {
79041 $this->processPipes->close();
79042 if (\is_resource($this->process)) {
79043 proc_close($this->process);
79044 }
79045 $this->exitcode = $this->processInformation['exitcode'];
79046 $this->status = self::STATUS_TERMINATED;
79047
79048 if (-1 === $this->exitcode) {
79049 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
79050
79051  $this->exitcode = 128 + $this->processInformation['termsig'];
79052 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
79053 $this->processInformation['signaled'] = true;
79054 $this->processInformation['termsig'] = -1;
79055 }
79056 }
79057
79058
79059  
79060  
79061  $this->callback = null;
79062
79063 return $this->exitcode;
79064 }
79065
79066
79067
79068
79069 private function resetProcessData()
79070 {
79071 $this->starttime = null;
79072 $this->callback = null;
79073 $this->exitcode = null;
79074 $this->fallbackStatus = array();
79075 $this->processInformation = null;
79076 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
79077 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
79078 $this->process = null;
79079 $this->latestSignal = null;
79080 $this->status = self::STATUS_READY;
79081 $this->incrementalOutputOffset = 0;
79082 $this->incrementalErrorOutputOffset = 0;
79083 }
79084
79085
79086
79087
79088
79089
79090
79091
79092
79093
79094
79095
79096
79097 private function doSignal($signal, $throwException)
79098 {
79099 if (null === $pid = $this->getPid()) {
79100 if ($throwException) {
79101 throw new LogicException('Can not send signal on a non running process.');
79102 }
79103
79104 return false;
79105 }
79106
79107 if ('\\' === \DIRECTORY_SEPARATOR) {
79108 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
79109 if ($exitCode && $this->isRunning()) {
79110 if ($throwException) {
79111 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
79112 }
79113
79114 return false;
79115 }
79116 } else {
79117 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
79118 $ok = @proc_terminate($this->process, $signal);
79119 } elseif (\function_exists('posix_kill')) {
79120 $ok = @posix_kill($pid, $signal);
79121 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
79122 $ok = false === fgets($pipes[2]);
79123 }
79124 if (!$ok) {
79125 if ($throwException) {
79126 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
79127 }
79128
79129 return false;
79130 }
79131 }
79132
79133 $this->latestSignal = (int) $signal;
79134 $this->fallbackStatus['signaled'] = true;
79135 $this->fallbackStatus['exitcode'] = -1;
79136 $this->fallbackStatus['termsig'] = $this->latestSignal;
79137
79138 return true;
79139 }
79140
79141
79142
79143
79144
79145
79146
79147
79148 private function requireProcessIsStarted($functionName)
79149 {
79150 if (!$this->isStarted()) {
79151 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
79152 }
79153 }
79154
79155
79156
79157
79158
79159
79160
79161
79162 private function requireProcessIsTerminated($functionName)
79163 {
79164 if (!$this->isTerminated()) {
79165 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
79166 }
79167 }
79168 }
79169 <?php
79170
79171
79172
79173
79174
79175
79176
79177
79178
79179
79180 namespace Symfony\Component\Process;
79181
79182 use Symfony\Component\Process\Exception\InvalidArgumentException;
79183 use Symfony\Component\Process\Exception\LogicException;
79184
79185
79186
79187
79188 class ProcessBuilder
79189 {
79190 private $arguments;
79191 private $cwd;
79192 private $env = array();
79193 private $input;
79194 private $timeout = 60;
79195 private $options = array();
79196 private $inheritEnv = true;
79197 private $prefix = array();
79198 private $outputDisabled = false;
79199
79200
79201
79202
79203 public function __construct(array $arguments = array())
79204 {
79205 $this->arguments = $arguments;
79206 }
79207
79208
79209
79210
79211
79212
79213
79214
79215 public static function create(array $arguments = array())
79216 {
79217 return new static($arguments);
79218 }
79219
79220
79221
79222
79223
79224
79225
79226
79227 public function add($argument)
79228 {
79229 $this->arguments[] = $argument;
79230
79231 return $this;
79232 }
79233
79234
79235
79236
79237
79238
79239
79240
79241
79242
79243 public function setPrefix($prefix)
79244 {
79245 $this->prefix = \is_array($prefix) ? $prefix : array($prefix);
79246
79247 return $this;
79248 }
79249
79250
79251
79252
79253
79254
79255
79256
79257
79258
79259
79260 public function setArguments(array $arguments)
79261 {
79262 $this->arguments = $arguments;
79263
79264 return $this;
79265 }
79266
79267
79268
79269
79270
79271
79272
79273
79274 public function setWorkingDirectory($cwd)
79275 {
79276 $this->cwd = $cwd;
79277
79278 return $this;
79279 }
79280
79281
79282
79283
79284
79285
79286
79287
79288 public function inheritEnvironmentVariables($inheritEnv = true)
79289 {
79290 $this->inheritEnv = $inheritEnv;
79291
79292 return $this;
79293 }
79294
79295
79296
79297
79298
79299
79300
79301
79302
79303
79304
79305
79306 public function setEnv($name, $value)
79307 {
79308 $this->env[$name] = $value;
79309
79310 return $this;
79311 }
79312
79313
79314
79315
79316
79317
79318
79319
79320
79321
79322
79323
79324 public function addEnvironmentVariables(array $variables)
79325 {
79326 $this->env = array_replace($this->env, $variables);
79327
79328 return $this;
79329 }
79330
79331
79332
79333
79334
79335
79336
79337
79338
79339
79340
79341
79342 public function setInput($input)
79343 {
79344 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
79345
79346 return $this;
79347 }
79348
79349
79350
79351
79352
79353
79354
79355
79356
79357
79358
79359
79360 public function setTimeout($timeout)
79361 {
79362 if (null === $timeout) {
79363 $this->timeout = null;
79364
79365 return $this;
79366 }
79367
79368 $timeout = (float) $timeout;
79369
79370 if ($timeout < 0) {
79371 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
79372 }
79373
79374 $this->timeout = $timeout;
79375
79376 return $this;
79377 }
79378
79379
79380
79381
79382
79383
79384
79385
79386
79387 public function setOption($name, $value)
79388 {
79389 $this->options[$name] = $value;
79390
79391 return $this;
79392 }
79393
79394
79395
79396
79397
79398
79399 public function disableOutput()
79400 {
79401 $this->outputDisabled = true;
79402
79403 return $this;
79404 }
79405
79406
79407
79408
79409
79410
79411 public function enableOutput()
79412 {
79413 $this->outputDisabled = false;
79414
79415 return $this;
79416 }
79417
79418
79419
79420
79421
79422
79423
79424
79425 public function getProcess()
79426 {
79427 if (0 === \count($this->prefix) && 0 === \count($this->arguments)) {
79428 throw new LogicException('You must add() command arguments before calling getProcess().');
79429 }
79430
79431 $options = $this->options;
79432
79433 $arguments = array_merge($this->prefix, $this->arguments);
79434 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
79435
79436 if ($this->inheritEnv) {
79437
79438  $env = array_replace($_ENV, $_SERVER, $this->env);
79439 } else {
79440 $env = $this->env;
79441 }
79442
79443 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
79444
79445 if ($this->outputDisabled) {
79446 $process->disableOutput();
79447 }
79448
79449 return $process;
79450 }
79451 }
79452 <?php
79453
79454
79455
79456
79457
79458
79459
79460
79461
79462
79463 namespace Symfony\Component\Process;
79464
79465 use Symfony\Component\Process\Exception\InvalidArgumentException;
79466
79467
79468
79469
79470
79471
79472
79473
79474 class ProcessUtils
79475 {
79476
79477
79478
79479 private function __construct()
79480 {
79481 }
79482
79483
79484
79485
79486
79487
79488
79489
79490 public static function escapeArgument($argument)
79491 {
79492
79493  
79494  
79495  
79496  if ('\\' === \DIRECTORY_SEPARATOR) {
79497 if ('' === $argument) {
79498 return escapeshellarg($argument);
79499 }
79500
79501 $escapedArgument = '';
79502 $quote = false;
79503 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
79504 if ('"' === $part) {
79505 $escapedArgument .= '\\"';
79506 } elseif (self::isSurroundedBy($part, '%')) {
79507
79508  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
79509 } else {
79510
79511  if ('\\' === substr($part, -1)) {
79512 $part .= '\\';
79513 }
79514 $quote = true;
79515 $escapedArgument .= $part;
79516 }
79517 }
79518 if ($quote) {
79519 $escapedArgument = '"'.$escapedArgument.'"';
79520 }
79521
79522 return $escapedArgument;
79523 }
79524
79525 return "'".str_replace("'", "'\\''", $argument)."'";
79526 }
79527
79528
79529
79530
79531
79532
79533
79534
79535
79536
79537
79538
79539
79540 public static function validateInput($caller, $input)
79541 {
79542 if (null !== $input) {
79543 if (\is_resource($input)) {
79544 return $input;
79545 }
79546 if (\is_string($input)) {
79547 return $input;
79548 }
79549 if (is_scalar($input)) {
79550 return (string) $input;
79551 }
79552
79553  if (\is_object($input) && method_exists($input, '__toString')) {
79554 @trigger_error('Passing an object as an input is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
79555
79556 return (string) $input;
79557 }
79558
79559 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
79560 }
79561
79562 return $input;
79563 }
79564
79565 private static function isSurroundedBy($arg, $char)
79566 {
79567 return 2 < \strlen($arg) && $char === $arg[0] && $char === $arg[\strlen($arg) - 1];
79568 }
79569 }
79570 Copyright (c) 2011 Jordi Boggiano
79571
79572 Permission is hereby granted, free of charge, to any person obtaining a copy
79573 of this software and associated documentation files (the "Software"), to deal
79574 in the Software without restriction, including without limitation the rights
79575 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79576 copies of the Software, and to permit persons to whom the Software is furnished
79577 to do so, subject to the following conditions:
79578
79579 The above copyright notice and this permission notice shall be included in all
79580 copies or substantial portions of the Software.
79581
79582 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79583 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79584 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79585 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79586 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79587 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
79588 THE SOFTWARE.
79589 <?php
79590
79591
79592
79593
79594
79595
79596
79597
79598
79599
79600 namespace Seld\JsonLint;
79601
79602 class DuplicateKeyException extends ParsingException
79603 {
79604 public function __construct($message, $key, array $details = array())
79605 {
79606 $details['key'] = $key;
79607 parent::__construct($message, $details);
79608 }
79609
79610 public function getKey()
79611 {
79612 return $this->details['key'];
79613 }
79614 }
79615 <?php
79616
79617
79618
79619
79620
79621
79622
79623
79624
79625
79626 namespace Seld\JsonLint;
79627 use stdClass;
79628
79629
79630
79631
79632
79633
79634
79635
79636
79637
79638
79639
79640
79641
79642 class JsonParser
79643 {
79644 const DETECT_KEY_CONFLICTS = 1;
79645 const ALLOW_DUPLICATE_KEYS = 2;
79646 const PARSE_TO_ASSOC = 4;
79647
79648 private $lexer;
79649
79650 private $flags;
79651 private $stack;
79652 private $vstack; 
79653  private $lstack; 
79654
79655 private $symbols = array(
79656 'error' => 2,
79657 'JSONString' => 3,
79658 'STRING' => 4,
79659 'JSONNumber' => 5,
79660 'NUMBER' => 6,
79661 'JSONNullLiteral' => 7,
79662 'NULL' => 8,
79663 'JSONBooleanLiteral' => 9,
79664 'TRUE' => 10,
79665 'FALSE' => 11,
79666 'JSONText' => 12,
79667 'JSONValue' => 13,
79668 'EOF' => 14,
79669 'JSONObject' => 15,
79670 'JSONArray' => 16,
79671 '{' => 17,
79672 '}' => 18,
79673 'JSONMemberList' => 19,
79674 'JSONMember' => 20,
79675 ':' => 21,
79676 ',' => 22,
79677 '[' => 23,
79678 ']' => 24,
79679 'JSONElementList' => 25,
79680 '$accept' => 0,
79681 '$end' => 1,
79682 );
79683
79684 private $terminals_ = array(
79685 2 => "error",
79686 4 => "STRING",
79687 6 => "NUMBER",
79688 8 => "NULL",
79689 10 => "TRUE",
79690 11 => "FALSE",
79691 14 => "EOF",
79692 17 => "{",
79693 18 => "}",
79694 21 => ":",
79695 22 => ",",
79696 23 => "[",
79697 24 => "]",
79698 );
79699
79700 private $productions_ = array(
79701 0,
79702 array(3, 1),
79703 array(5, 1),
79704 array(7, 1),
79705 array(9, 1),
79706 array(9, 1),
79707 array(12, 2),
79708 array(13, 1),
79709 array(13, 1),
79710 array(13, 1),
79711 array(13, 1),
79712 array(13, 1),
79713 array(13, 1),
79714 array(15, 2),
79715 array(15, 3),
79716 array(20, 3),
79717 array(19, 1),
79718 array(19, 3),
79719 array(16, 2),
79720 array(16, 3),
79721 array(25, 1),
79722 array(25, 3)
79723 );
79724
79725 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)),
79726 );
79727
79728 private $defaultActions = array(
79729 16 => array(2, 6)
79730 );
79731
79732
79733
79734
79735
79736
79737 public function lint($input, $flags = 0)
79738 {
79739 try {
79740 $this->parse($input, $flags);
79741 } catch (ParsingException $e) {
79742 return $e;
79743 }
79744 }
79745
79746
79747
79748
79749
79750
79751
79752 public function parse($input, $flags = 0)
79753 {
79754 $this->failOnBOM($input);
79755
79756 $this->flags = $flags;
79757
79758 $this->stack = array(0);
79759 $this->vstack = array(null);
79760 $this->lstack = array();
79761
79762 $yytext = '';
79763 $yylineno = 0;
79764 $yyleng = 0;
79765 $recovering = 0;
79766 $TERROR = 2;
79767 $EOF = 1;
79768
79769 $this->lexer = new Lexer();
79770 $this->lexer->setInput($input);
79771
79772 $yyloc = $this->lexer->yylloc;
79773 $this->lstack[] = $yyloc;
79774
79775 $symbol = null;
79776 $preErrorSymbol = null;
79777 $state = null;
79778 $action = null;
79779 $a = null;
79780 $r = null;
79781 $yyval = new stdClass;
79782 $p = null;
79783 $len = null;
79784 $newState = null;
79785 $expected = null;
79786 $errStr = null;
79787
79788 while (true) {
79789
79790  $state = $this->stack[\count($this->stack)-1];
79791
79792
79793  if (isset($this->defaultActions[$state])) {
79794 $action = $this->defaultActions[$state];
79795 } else {
79796 if ($symbol == null) {
79797 $symbol = $this->lex();
79798 }
79799
79800  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
79801 }
79802
79803
79804  if (!$action || !$action[0]) {
79805 if (!$recovering) {
79806
79807  $expected = array();
79808 foreach ($this->table[$state] as $p => $ignore) {
79809 if (isset($this->terminals_[$p]) && $p > 2) {
79810 $expected[] = "'" . $this->terminals_[$p] . "'";
79811 }
79812 }
79813
79814 $message = null;
79815 if (\in_array("'STRING'", $expected) && \in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
79816 $message = "Invalid string";
79817 if ("'" === substr($this->lexer->match, 0, 1)) {
79818 $message .= ", it appears you used single quotes instead of double quotes";
79819 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u](...)?)}', $this->lexer->getFullUpcomingInput(), $match)) {
79820 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
79821 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getFullUpcomingInput())) {
79822 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
79823 }
79824 }
79825
79826 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
79827 $errStr .= $this->lexer->showPosition() . "\n";
79828 if ($message) {
79829 $errStr .= $message;
79830 } else {
79831 $errStr .= (\count($expected) > 1) ? "Expected one of: " : "Expected: ";
79832 $errStr .= implode(', ', $expected);
79833 }
79834
79835 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
79836 $errStr .= " - It appears you have an extra trailing comma";
79837 }
79838
79839 $this->parseError($errStr, array(
79840 'text' => $this->lexer->match,
79841 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
79842 'line' => $this->lexer->yylineno,
79843 'loc' => $yyloc,
79844 'expected' => $expected,
79845 ));
79846 }
79847
79848
79849  if ($recovering == 3) {
79850 if ($symbol == $EOF) {
79851 throw new ParsingException($errStr ?: 'Parsing halted.');
79852 }
79853
79854
79855  $yyleng = $this->lexer->yyleng;
79856 $yytext = $this->lexer->yytext;
79857 $yylineno = $this->lexer->yylineno;
79858 $yyloc = $this->lexer->yylloc;
79859 $symbol = $this->lex();
79860 }
79861
79862
79863  while (true) {
79864
79865  if (\array_key_exists($TERROR, $this->table[$state])) {
79866 break;
79867 }
79868 if ($state == 0) {
79869 throw new ParsingException($errStr ?: 'Parsing halted.');
79870 }
79871 $this->popStack(1);
79872 $state = $this->stack[\count($this->stack)-1];
79873 }
79874
79875 $preErrorSymbol = $symbol; 
79876  $symbol = $TERROR; 
79877  $state = $this->stack[\count($this->stack)-1];
79878 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
79879 $recovering = 3; 
79880  }
79881
79882
79883  if (\is_array($action[0]) && \count($action) > 1) {
79884 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
79885 }
79886
79887 switch ($action[0]) {
79888 case 1: 
79889  $this->stack[] = $symbol;
79890 $this->vstack[] = $this->lexer->yytext;
79891 $this->lstack[] = $this->lexer->yylloc;
79892 $this->stack[] = $action[1]; 
79893  $symbol = null;
79894 if (!$preErrorSymbol) { 
79895  $yyleng = $this->lexer->yyleng;
79896 $yytext = $this->lexer->yytext;
79897 $yylineno = $this->lexer->yylineno;
79898 $yyloc = $this->lexer->yylloc;
79899 if ($recovering > 0) {
79900 $recovering--;
79901 }
79902 } else { 
79903  $symbol = $preErrorSymbol;
79904 $preErrorSymbol = null;
79905 }
79906 break;
79907
79908 case 2: 
79909  $len = $this->productions_[$action[1]][1];
79910
79911
79912  $yyval->token = $this->vstack[\count($this->vstack) - $len]; 
79913  
79914  $yyval->store = array( 
79915  'first_line' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_line'],
79916 'last_line' => $this->lstack[\count($this->lstack) - 1]['last_line'],
79917 'first_column' => $this->lstack[\count($this->lstack) - ($len ?: 1)]['first_column'],
79918 'last_column' => $this->lstack[\count($this->lstack) - 1]['last_column'],
79919 );
79920 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
79921
79922 if (!$r instanceof Undefined) {
79923 return $r;
79924 }
79925
79926 if ($len) {
79927 $this->popStack($len);
79928 }
79929
79930 $this->stack[] = $this->productions_[$action[1]][0]; 
79931  $this->vstack[] = $yyval->token;
79932 $this->lstack[] = $yyval->store;
79933 $newState = $this->table[$this->stack[\count($this->stack)-2]][$this->stack[\count($this->stack)-1]];
79934 $this->stack[] = $newState;
79935 break;
79936
79937 case 3: 
79938
79939 return true;
79940 }
79941 }
79942
79943 return true;
79944 }
79945
79946 protected function parseError($str, $hash)
79947 {
79948 throw new ParsingException($str, $hash);
79949 }
79950
79951
79952  
79953  
79954  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
79955 {
79956
79957  $len = \count($tokens) - 1;
79958 switch ($yystate) {
79959 case 1:
79960 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
79961 $yyval->token = $yytext;
79962 break;
79963 case 2:
79964 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
79965 $yyval->token = \floatval($yytext);
79966 } else {
79967 $yyval->token = strpos($yytext, '.') === false ? \intval($yytext) : \floatval($yytext);
79968 }
79969 break;
79970 case 3:
79971 $yyval->token = null;
79972 break;
79973 case 4:
79974 $yyval->token = true;
79975 break;
79976 case 5:
79977 $yyval->token = false;
79978 break;
79979 case 6:
79980 return $yyval->token = $tokens[$len-1];
79981 case 13:
79982 if ($this->flags & self::PARSE_TO_ASSOC) {
79983 $yyval->token = array();
79984 } else {
79985 $yyval->token = new stdClass;
79986 }
79987 break;
79988 case 14:
79989 $yyval->token = $tokens[$len-1];
79990 break;
79991 case 15:
79992 $yyval->token = array($tokens[$len-2], $tokens[$len]);
79993 break;
79994 case 16:
79995 if (PHP_VERSION_ID < 70100) {
79996 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
79997 } else {
79998 $property = $tokens[$len][0];
79999 }
80000 if ($this->flags & self::PARSE_TO_ASSOC) {
80001 $yyval->token = array();
80002 $yyval->token[$property] = $tokens[$len][1];
80003 } else {
80004 $yyval->token = new stdClass;
80005 $yyval->token->$property = $tokens[$len][1];
80006 }
80007 break;
80008 case 17:
80009 if ($this->flags & self::PARSE_TO_ASSOC) {
80010 $yyval->token =& $tokens[$len-2];
80011 $key = $tokens[$len][0];
80012 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
80013 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
80014 $errStr .= $this->lexer->showPosition() . "\n";
80015 $errStr .= "Duplicate key: ".$tokens[$len][0];
80016 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
80017 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
80018 $duplicateCount = 1;
80019 do {
80020 $duplicateKey = $key . '.' . $duplicateCount++;
80021 } while (isset($tokens[$len-2][$duplicateKey]));
80022 $key = $duplicateKey;
80023 }
80024 $tokens[$len-2][$key] = $tokens[$len][1];
80025 } else {
80026 $yyval->token = $tokens[$len-2];
80027 if (PHP_VERSION_ID < 70100) {
80028 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
80029 } else {
80030 $key = $tokens[$len][0];
80031 }
80032 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
80033 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
80034 $errStr .= $this->lexer->showPosition() . "\n";
80035 $errStr .= "Duplicate key: ".$tokens[$len][0];
80036 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
80037 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
80038 $duplicateCount = 1;
80039 do {
80040 $duplicateKey = $key . '.' . $duplicateCount++;
80041 } while (isset($tokens[$len-2]->$duplicateKey));
80042 $key = $duplicateKey;
80043 }
80044 $tokens[$len-2]->$key = $tokens[$len][1];
80045 }
80046 break;
80047 case 18:
80048 $yyval->token = array();
80049 break;
80050 case 19:
80051 $yyval->token = $tokens[$len-1];
80052 break;
80053 case 20:
80054 $yyval->token = array($tokens[$len]);
80055 break;
80056 case 21:
80057 $tokens[$len-2][] = $tokens[$len];
80058 $yyval->token = $tokens[$len-2];
80059 break;
80060 }
80061
80062 return new Undefined();
80063 }
80064
80065 private function stringInterpolation($match)
80066 {
80067 switch ($match[0]) {
80068 case '\\\\':
80069 return '\\';
80070 case '\"':
80071 return '"';
80072 case '\b':
80073 return \chr(8);
80074 case '\f':
80075 return \chr(12);
80076 case '\n':
80077 return "\n";
80078 case '\r':
80079 return "\r";
80080 case '\t':
80081 return "\t";
80082 case '\/':
80083 return "/";
80084 default:
80085 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', ENT_QUOTES, 'UTF-8');
80086 }
80087 }
80088
80089 private function popStack($n)
80090 {
80091 $this->stack = \array_slice($this->stack, 0, - (2 * $n));
80092 $this->vstack = \array_slice($this->vstack, 0, - $n);
80093 $this->lstack = \array_slice($this->lstack, 0, - $n);
80094 }
80095
80096 private function lex()
80097 {
80098 $token = $this->lexer->lex() ?: 1; 
80099  
80100  if (!is_numeric($token)) {
80101 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
80102 }
80103
80104 return $token;
80105 }
80106
80107 private function failOnBOM($input)
80108 {
80109
80110  $bom = "\xEF\xBB\xBF";
80111
80112 if (substr($input, 0, 3) === $bom) {
80113 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
80114 }
80115 }
80116 }
80117 <?php
80118
80119
80120
80121
80122
80123
80124
80125
80126
80127
80128 namespace Seld\JsonLint;
80129
80130
80131
80132
80133
80134
80135 class Lexer
80136 {
80137 private $EOF = 1;
80138 private $rules = array(
80139 0 => '/\G\s+/',
80140 1 => '/\G-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
80141 2 => '{\G"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
80142 3 => '/\G\{/',
80143 4 => '/\G\}/',
80144 5 => '/\G\[/',
80145 6 => '/\G\]/',
80146 7 => '/\G,/',
80147 8 => '/\G:/',
80148 9 => '/\Gtrue\b/',
80149 10 => '/\Gfalse\b/',
80150 11 => '/\Gnull\b/',
80151 12 => '/\G$/',
80152 13 => '/\G./',
80153 );
80154
80155 private $conditions = array(
80156 "INITIAL" => array(
80157 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
80158 "inclusive" => true,
80159 ),
80160 );
80161
80162 private $conditionStack;
80163 private $input;
80164 private $more;
80165 private $done;
80166 private $offset;
80167
80168 public $match;
80169 public $yylineno;
80170 public $yyleng;
80171 public $yytext;
80172 public $yylloc;
80173
80174 public function lex()
80175 {
80176 $r = $this->next();
80177 if (!$r instanceof Undefined) {
80178 return $r;
80179 }
80180
80181 return $this->lex();
80182 }
80183
80184 public function setInput($input)
80185 {
80186 $this->input = $input;
80187 $this->more = false;
80188 $this->done = false;
80189 $this->offset = 0;
80190 $this->yylineno = $this->yyleng = 0;
80191 $this->yytext = $this->match = '';
80192 $this->conditionStack = array('INITIAL');
80193 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
80194
80195 return $this;
80196 }
80197
80198 public function showPosition()
80199 {
80200 $pre = str_replace("\n", '', $this->getPastInput());
80201 $c = str_repeat('-', max(0, \strlen($pre) - 1)); 
80202
80203 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
80204 }
80205
80206 public function getPastInput()
80207 {
80208 $pastLength = $this->offset - \strlen($this->match);
80209
80210 return ($pastLength > 20 ? '...' : '') . substr($this->input, max(0, $pastLength - 20), min(20, $pastLength));
80211 }
80212
80213 public function getUpcomingInput()
80214 {
80215 $next = $this->match;
80216 if (\strlen($next) < 20) {
80217 $next .= substr($this->input, $this->offset, 20 - \strlen($next));
80218 }
80219
80220 return substr($next, 0, 20) . (\strlen($next) > 20 ? '...' : '');
80221 }
80222
80223 public function getFullUpcomingInput()
80224 {
80225 $next = $this->match;
80226 if (substr($next, 0, 1) === '"' && substr_count($next, '"') === 1) {
80227 $len = \strlen($this->input);
80228 $strEnd = min(strpos($this->input, '"', $this->offset + 1) ?: $len, strpos($this->input, "\n", $this->offset + 1) ?: $len);
80229 $next .= substr($this->input, $this->offset, $strEnd - $this->offset);
80230 } elseif (\strlen($next) < 20) {
80231 $next .= substr($this->input, $this->offset, 20 - \strlen($next));
80232 }
80233
80234 return $next;
80235 }
80236
80237 protected function parseError($str, $hash)
80238 {
80239 throw new \Exception($str);
80240 }
80241
80242 private function next()
80243 {
80244 if ($this->done) {
80245 return $this->EOF;
80246 }
80247 if ($this->offset === \strlen($this->input)) {
80248 $this->done = true;
80249 }
80250
80251 $token = null;
80252 $match = null;
80253 $col = null;
80254 $lines = null;
80255
80256 if (!$this->more) {
80257 $this->yytext = '';
80258 $this->match = '';
80259 }
80260
80261 $rules = $this->getCurrentRules();
80262 $rulesLen = \count($rules);
80263
80264 for ($i=0; $i < $rulesLen; $i++) {
80265 if (preg_match($this->rules[$rules[$i]], $this->input, $match, 0, $this->offset)) {
80266 preg_match_all('/\n.*/', $match[0], $lines);
80267 $lines = $lines[0];
80268 if ($lines) {
80269 $this->yylineno += \count($lines);
80270 }
80271
80272 $this->yylloc = array(
80273 'first_line' => $this->yylloc['last_line'],
80274 'last_line' => $this->yylineno+1,
80275 'first_column' => $this->yylloc['last_column'],
80276 'last_column' => $lines ? \strlen($lines[\count($lines) - 1]) - 1 : $this->yylloc['last_column'] + \strlen($match[0]),
80277 );
80278 $this->yytext .= $match[0];
80279 $this->match .= $match[0];
80280 $this->yyleng = \strlen($this->yytext);
80281 $this->more = false;
80282 $this->offset += \strlen($match[0]);
80283 $token = $this->performAction($rules[$i], $this->conditionStack[\count($this->conditionStack)-1]);
80284 if ($token) {
80285 return $token;
80286 }
80287
80288 return new Undefined();
80289 }
80290 }
80291
80292 if ($this->offset === \strlen($this->input)) {
80293 return $this->EOF;
80294 }
80295
80296 $this->parseError(
80297 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
80298 array(
80299 'text' => "",
80300 'token' => null,
80301 'line' => $this->yylineno,
80302 )
80303 );
80304 }
80305
80306 private function getCurrentRules()
80307 {
80308 return $this->conditions[$this->conditionStack[\count($this->conditionStack)-1]]['rules'];
80309 }
80310
80311 private function performAction($avoiding_name_collisions, $YY_START)
80312 {
80313 switch ($avoiding_name_collisions) {
80314 case 0:
80315 break;
80316 case 1:
80317 return 6;
80318 break;
80319 case 2:
80320 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
80321
80322 return 4;
80323 case 3:
80324 return 17;
80325 case 4:
80326 return 18;
80327 case 5:
80328 return 23;
80329 case 6:
80330 return 24;
80331 case 7:
80332 return 22;
80333 case 8:
80334 return 21;
80335 case 9:
80336 return 10;
80337 case 10:
80338 return 11;
80339 case 11:
80340 return 8;
80341 case 12:
80342 return 14;
80343 case 13:
80344 return 'INVALID';
80345 }
80346 }
80347 }
80348 <?php
80349
80350
80351
80352
80353
80354
80355
80356
80357
80358
80359 namespace Seld\JsonLint;
80360
80361 class ParsingException extends \Exception
80362 {
80363 protected $details;
80364
80365 public function __construct($message, $details = array())
80366 {
80367 $this->details = $details;
80368 parent::__construct($message);
80369 }
80370
80371 public function getDetails()
80372 {
80373 return $this->details;
80374 }
80375 }
80376 <?php
80377
80378
80379
80380
80381
80382
80383
80384
80385
80386
80387 namespace Seld\JsonLint;
80388
80389 class Undefined
80390 {
80391 }
80392 MIT License
80393
80394 Copyright (c) 2016
80395
80396 Permission is hereby granted, free of charge, to any person obtaining a copy
80397 of this software and associated documentation files (the "Software"), to deal
80398 in the Software without restriction, including without limitation the rights
80399 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
80400 copies of the Software, and to permit persons to whom the Software is
80401 furnished to do so, subject to the following conditions:
80402
80403 The above copyright notice and this permission notice shall be included in all
80404 copies or substantial portions of the Software.
80405
80406 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80407 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80408 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80409 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80410 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80411 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
80412 SOFTWARE.
80413 <?php
80414
80415 require __DIR__ . '/../vendor/autoload.php';
80416
80417 $data = json_decode(file_get_contents('data.json'));
80418
80419
80420 $validator = new JsonSchema\Validator();
80421 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
80422
80423 if ($validator->isValid()) {
80424 echo "The supplied JSON validates against the schema.\n";
80425 } else {
80426 echo "JSON does not validate. Violations:\n";
80427 foreach ($validator->getErrors() as $error) {
80428 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
80429 }
80430 }
80431 <?php
80432
80433
80434
80435
80436
80437
80438
80439
80440 namespace JsonSchema\Constraints;
80441
80442 use JsonSchema\Entity\JsonPointer;
80443 use JsonSchema\Exception\InvalidArgumentException;
80444 use JsonSchema\Exception\ValidationException;
80445 use JsonSchema\Validator;
80446
80447
80448
80449
80450
80451 class BaseConstraint
80452 {
80453
80454
80455
80456 protected $errors = array();
80457
80458
80459
80460
80461 protected $errorMask = Validator::ERROR_NONE;
80462
80463
80464
80465
80466 protected $factory;
80467
80468
80469
80470
80471 public function __construct(Factory $factory = null)
80472 {
80473 $this->factory = $factory ?: new Factory();
80474 }
80475
80476 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
80477 {
80478 $error = array(
80479 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
80480 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
80481 'message' => $message,
80482 'constraint' => $constraint,
80483 'context' => $this->factory->getErrorContext(),
80484 );
80485
80486 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
80487 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
80488 }
80489
80490 if (is_array($more) && count($more) > 0) {
80491 $error += $more;
80492 }
80493
80494 $this->errors[] = $error;
80495 $this->errorMask |= $error['context'];
80496 }
80497
80498 public function addErrors(array $errors)
80499 {
80500 if ($errors) {
80501 $this->errors = array_merge($this->errors, $errors);
80502 $errorMask = &$this->errorMask;
80503 array_walk($errors, function ($error) use (&$errorMask) {
80504 if (isset($error['context'])) {
80505 $errorMask |= $error['context'];
80506 }
80507 });
80508 }
80509 }
80510
80511 public function getErrors($errorContext = Validator::ERROR_ALL)
80512 {
80513 if ($errorContext === Validator::ERROR_ALL) {
80514 return $this->errors;
80515 }
80516
80517 return array_filter($this->errors, function ($error) use ($errorContext) {
80518 if ($errorContext & $error['context']) {
80519 return true;
80520 }
80521 });
80522 }
80523
80524 public function numErrors($errorContext = Validator::ERROR_ALL)
80525 {
80526 if ($errorContext === Validator::ERROR_ALL) {
80527 return count($this->errors);
80528 }
80529
80530 return count($this->getErrors($errorContext));
80531 }
80532
80533 public function isValid()
80534 {
80535 return !$this->getErrors();
80536 }
80537
80538
80539
80540
80541
80542 public function reset()
80543 {
80544 $this->errors = array();
80545 $this->errorMask = Validator::ERROR_NONE;
80546 }
80547
80548
80549
80550
80551
80552
80553 public function getErrorMask()
80554 {
80555 return $this->errorMask;
80556 }
80557
80558
80559
80560
80561
80562
80563
80564
80565 public static function arrayToObjectRecursive($array)
80566 {
80567 $json = json_encode($array);
80568 if (json_last_error() !== \JSON_ERROR_NONE) {
80569 $message = 'Unable to encode schema array as JSON';
80570 if (function_exists('json_last_error_msg')) {
80571 $message .= ': ' . json_last_error_msg();
80572 }
80573 throw new InvalidArgumentException($message);
80574 }
80575
80576 return (object) json_decode($json);
80577 }
80578 }
80579 <?php
80580
80581
80582
80583
80584
80585
80586
80587
80588 namespace JsonSchema\Constraints;
80589
80590 use JsonSchema\Entity\JsonPointer;
80591
80592
80593
80594
80595
80596
80597
80598 class CollectionConstraint extends Constraint
80599 {
80600
80601
80602
80603 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
80604 {
80605
80606  if (isset($schema->minItems) && count($value) < $schema->minItems) {
80607 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
80608 }
80609
80610
80611  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
80612 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
80613 }
80614
80615
80616  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
80617 $unique = $value;
80618 if (is_array($value) && count($value)) {
80619 $unique = array_map(function ($e) {
80620 return var_export($e, true);
80621 }, $value);
80622 }
80623 if (count(array_unique($unique)) != count($value)) {
80624 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
80625 }
80626 }
80627
80628
80629  if (isset($schema->items)) {
80630 $this->validateItems($value, $schema, $path, $i);
80631 }
80632 }
80633
80634
80635
80636
80637
80638
80639
80640
80641
80642 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
80643 {
80644 if (is_object($schema->items)) {
80645
80646  foreach ($value as $k => &$v) {
80647 $initErrors = $this->getErrors();
80648
80649
80650  $this->checkUndefined($v, $schema->items, $path, $k);
80651
80652
80653  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
80654 $secondErrors = $this->getErrors();
80655 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
80656 }
80657
80658
80659  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
80660 $this->errors = $secondErrors;
80661 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
80662 $this->errors = $initErrors;
80663 }
80664 }
80665 unset($v); 
80666
80667 } else {
80668
80669  foreach ($value as $k => &$v) {
80670 if (array_key_exists($k, $schema->items)) {
80671 $this->checkUndefined($v, $schema->items[$k], $path, $k);
80672 } else {
80673
80674  if (property_exists($schema, 'additionalItems')) {
80675 if ($schema->additionalItems !== false) {
80676 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
80677 } else {
80678 $this->addError(
80679 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
80680 }
80681 } else {
80682
80683  $this->checkUndefined($v, new \stdClass(), $path, $k);
80684 }
80685 }
80686 }
80687 unset($v); 
80688
80689
80690
80691  if (count($value) > 0) {
80692 for ($k = count($value); $k < count($schema->items); $k++) {
80693 $undefinedInstance = $this->factory->createInstanceFor('undefined');
80694 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
80695 }
80696 }
80697 }
80698 }
80699 }
80700 <?php
80701
80702
80703
80704
80705
80706
80707
80708
80709 namespace JsonSchema\Constraints;
80710
80711 use JsonSchema\Entity\JsonPointer;
80712
80713
80714
80715
80716
80717
80718
80719 abstract class Constraint extends BaseConstraint implements ConstraintInterface
80720 {
80721 protected $inlineSchemaProperty = '$schema';
80722
80723 const CHECK_MODE_NONE = 0x00000000;
80724 const CHECK_MODE_NORMAL = 0x00000001;
80725 const CHECK_MODE_TYPE_CAST = 0x00000002;
80726 const CHECK_MODE_COERCE_TYPES = 0x00000004;
80727 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
80728 const CHECK_MODE_EXCEPTIONS = 0x00000010;
80729 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
80730 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
80731 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
80732
80733
80734
80735
80736
80737
80738
80739
80740
80741 protected function incrementPath(JsonPointer $path = null, $i)
80742 {
80743 $path = $path ?: new JsonPointer('');
80744 $path = $path->withPropertyPaths(
80745 array_merge(
80746 $path->getPropertyPaths(),
80747 array_filter(array($i), 'strlen')
80748 )
80749 );
80750
80751 return $path;
80752 }
80753
80754
80755
80756
80757
80758
80759
80760
80761
80762 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
80763 {
80764 $validator = $this->factory->createInstanceFor('collection');
80765 $validator->check($value, $schema, $path, $i);
80766
80767 $this->addErrors($validator->getErrors());
80768 }
80769
80770
80771
80772
80773
80774
80775
80776
80777
80778
80779
80780 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
80781 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
80782 {
80783 $validator = $this->factory->createInstanceFor('object');
80784 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
80785
80786 $this->addErrors($validator->getErrors());
80787 }
80788
80789
80790
80791
80792
80793
80794
80795
80796
80797 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
80798 {
80799 $validator = $this->factory->createInstanceFor('type');
80800 $validator->check($value, $schema, $path, $i);
80801
80802 $this->addErrors($validator->getErrors());
80803 }
80804
80805
80806
80807
80808
80809
80810
80811
80812
80813 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
80814 {
80815 $validator = $this->factory->createInstanceFor('undefined');
80816
80817 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
80818
80819 $this->addErrors($validator->getErrors());
80820 }
80821
80822
80823
80824
80825
80826
80827
80828
80829
80830 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
80831 {
80832 $validator = $this->factory->createInstanceFor('string');
80833 $validator->check($value, $schema, $path, $i);
80834
80835 $this->addErrors($validator->getErrors());
80836 }
80837
80838
80839
80840
80841
80842
80843
80844
80845
80846 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
80847 {
80848 $validator = $this->factory->createInstanceFor('number');
80849 $validator->check($value, $schema, $path, $i);
80850
80851 $this->addErrors($validator->getErrors());
80852 }
80853
80854
80855
80856
80857
80858
80859
80860
80861
80862 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
80863 {
80864 $validator = $this->factory->createInstanceFor('enum');
80865 $validator->check($value, $schema, $path, $i);
80866
80867 $this->addErrors($validator->getErrors());
80868 }
80869
80870
80871
80872
80873
80874
80875
80876
80877
80878 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
80879 {
80880 $validator = $this->factory->createInstanceFor('format');
80881 $validator->check($value, $schema, $path, $i);
80882
80883 $this->addErrors($validator->getErrors());
80884 }
80885
80886
80887
80888
80889
80890
80891 protected function getTypeCheck()
80892 {
80893 return $this->factory->getTypeCheck();
80894 }
80895
80896
80897
80898
80899
80900
80901 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
80902 {
80903 $result = array_map(
80904 function ($path) {
80905 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
80906 },
80907 $pointer->getPropertyPaths()
80908 );
80909
80910 return trim(implode('', $result), '.');
80911 }
80912 }
80913 <?php
80914
80915
80916
80917
80918
80919
80920
80921
80922 namespace JsonSchema\Constraints;
80923
80924 use JsonSchema\Entity\JsonPointer;
80925
80926
80927
80928
80929
80930
80931 interface ConstraintInterface
80932 {
80933
80934
80935
80936
80937
80938 public function getErrors();
80939
80940
80941
80942
80943
80944
80945 public function addErrors(array $errors);
80946
80947
80948
80949
80950
80951
80952
80953
80954
80955 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
80956
80957
80958
80959
80960
80961
80962 public function isValid();
80963
80964
80965
80966
80967
80968
80969
80970
80971
80972
80973
80974
80975
80976 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
80977 }
80978 <?php
80979
80980
80981
80982
80983
80984
80985
80986
80987 namespace JsonSchema\Constraints;
80988
80989 use JsonSchema\Entity\JsonPointer;
80990
80991
80992
80993
80994
80995
80996
80997 class EnumConstraint extends Constraint
80998 {
80999
81000
81001
81002 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
81003 {
81004
81005  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
81006 return;
81007 }
81008 $type = gettype($element);
81009
81010 foreach ($schema->enum as $enum) {
81011 $enumType = gettype($enum);
81012 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
81013 if ((object) $element == $enum) {
81014 return;
81015 }
81016 }
81017
81018 if ($type === gettype($enum)) {
81019 if ($type == 'object') {
81020 if ($element == $enum) {
81021 return;
81022 }
81023 } elseif ($element === $enum) {
81024 return;
81025 }
81026 }
81027 }
81028
81029 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
81030 }
81031 }
81032 <?php
81033
81034
81035
81036
81037
81038
81039
81040
81041 namespace JsonSchema\Constraints;
81042
81043 use JsonSchema\Exception\InvalidArgumentException;
81044 use JsonSchema\SchemaStorage;
81045 use JsonSchema\SchemaStorageInterface;
81046 use JsonSchema\Uri\UriRetriever;
81047 use JsonSchema\UriRetrieverInterface;
81048 use JsonSchema\Validator;
81049
81050
81051
81052
81053 class Factory
81054 {
81055
81056
81057
81058 protected $schemaStorage;
81059
81060
81061
81062
81063 protected $uriRetriever;
81064
81065
81066
81067
81068 private $checkMode = Constraint::CHECK_MODE_NORMAL;
81069
81070
81071
81072
81073 private $typeCheck = array();
81074
81075
81076
81077
81078 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
81079
81080
81081
81082
81083 protected $constraintMap = array(
81084 'array' => 'JsonSchema\Constraints\CollectionConstraint',
81085 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
81086 'object' => 'JsonSchema\Constraints\ObjectConstraint',
81087 'type' => 'JsonSchema\Constraints\TypeConstraint',
81088 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
81089 'string' => 'JsonSchema\Constraints\StringConstraint',
81090 'number' => 'JsonSchema\Constraints\NumberConstraint',
81091 'enum' => 'JsonSchema\Constraints\EnumConstraint',
81092 'format' => 'JsonSchema\Constraints\FormatConstraint',
81093 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
81094 'validator' => 'JsonSchema\Validator'
81095 );
81096
81097
81098
81099
81100 private $instanceCache = array();
81101
81102
81103
81104
81105
81106
81107 public function __construct(
81108 SchemaStorageInterface $schemaStorage = null,
81109 UriRetrieverInterface $uriRetriever = null,
81110 $checkMode = Constraint::CHECK_MODE_NORMAL
81111 ) {
81112
81113  $this->setConfig($checkMode);
81114
81115 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
81116 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
81117 }
81118
81119
81120
81121
81122
81123
81124 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
81125 {
81126 $this->checkMode = $checkMode;
81127 }
81128
81129
81130
81131
81132
81133
81134 public function addConfig($options)
81135 {
81136 $this->checkMode |= $options;
81137 }
81138
81139
81140
81141
81142
81143
81144 public function removeConfig($options)
81145 {
81146 $this->checkMode &= ~$options;
81147 }
81148
81149
81150
81151
81152
81153
81154
81155
81156 public function getConfig($options = null)
81157 {
81158 if ($options === null) {
81159 return $this->checkMode;
81160 }
81161
81162 return $this->checkMode & $options;
81163 }
81164
81165
81166
81167
81168 public function getUriRetriever()
81169 {
81170 return $this->uriRetriever;
81171 }
81172
81173 public function getSchemaStorage()
81174 {
81175 return $this->schemaStorage;
81176 }
81177
81178 public function getTypeCheck()
81179 {
81180 if (!isset($this->typeCheck[$this->checkMode])) {
81181 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
81182 ? new TypeCheck\LooseTypeCheck()
81183 : new TypeCheck\StrictTypeCheck();
81184 }
81185
81186 return $this->typeCheck[$this->checkMode];
81187 }
81188
81189
81190
81191
81192
81193
81194
81195 public function setConstraintClass($name, $class)
81196 {
81197
81198  if (!class_exists($class)) {
81199 throw new InvalidArgumentException('Unknown constraint ' . $name);
81200 }
81201
81202  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
81203 throw new InvalidArgumentException('Invalid class ' . $name);
81204 }
81205 $this->constraintMap[$name] = $class;
81206
81207 return $this;
81208 }
81209
81210
81211
81212
81213
81214
81215
81216
81217
81218
81219 public function createInstanceFor($constraintName)
81220 {
81221 if (!isset($this->constraintMap[$constraintName])) {
81222 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
81223 }
81224
81225 if (!isset($this->instanceCache[$constraintName])) {
81226 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
81227 }
81228
81229 return clone $this->instanceCache[$constraintName];
81230 }
81231
81232
81233
81234
81235
81236
81237 public function getErrorContext()
81238 {
81239 return $this->errorContext;
81240 }
81241
81242
81243
81244
81245
81246
81247 public function setErrorContext($errorContext)
81248 {
81249 $this->errorContext = $errorContext;
81250 }
81251 }
81252 <?php
81253
81254
81255
81256
81257
81258
81259
81260
81261 namespace JsonSchema\Constraints;
81262
81263 use JsonSchema\Entity\JsonPointer;
81264 use JsonSchema\Rfc3339;
81265
81266
81267
81268
81269
81270
81271
81272
81273 class FormatConstraint extends Constraint
81274 {
81275
81276
81277
81278 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
81279 {
81280 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
81281 return;
81282 }
81283
81284 switch ($schema->format) {
81285 case 'date':
81286 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
81287 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
81288 }
81289 break;
81290
81291 case 'time':
81292 if (!$this->validateDateTime($element, 'H:i:s')) {
81293 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
81294 }
81295 break;
81296
81297 case 'date-time':
81298 if (null === Rfc3339::createFromString($element)) {
81299 $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));
81300 }
81301 break;
81302
81303 case 'utc-millisec':
81304 if (!$this->validateDateTime($element, 'U')) {
81305 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
81306 }
81307 break;
81308
81309 case 'regex':
81310 if (!$this->validateRegex($element)) {
81311 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
81312 }
81313 break;
81314
81315 case 'color':
81316 if (!$this->validateColor($element)) {
81317 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
81318 }
81319 break;
81320
81321 case 'style':
81322 if (!$this->validateStyle($element)) {
81323 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
81324 }
81325 break;
81326
81327 case 'phone':
81328 if (!$this->validatePhone($element)) {
81329 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
81330 }
81331 break;
81332
81333 case 'uri':
81334 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
81335 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
81336 }
81337 break;
81338
81339 case 'uriref':
81340 case 'uri-reference':
81341 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
81342
81343  
81344  
81345  if (substr($element, 0, 2) === '//') { 
81346  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
81347 } elseif (substr($element, 0, 1) === '/') { 
81348  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
81349 } elseif (strlen($element)) { 
81350  $pathParts = explode('/', $element, 2);
81351 if (strpos($pathParts[0], ':') !== false) {
81352 $validURL = null;
81353 } else {
81354 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
81355 }
81356 } else {
81357 $validURL = null;
81358 }
81359 if ($validURL === null) {
81360 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
81361 }
81362 }
81363 break;
81364
81365 case 'email':
81366 $filterFlags = FILTER_NULL_ON_FAILURE;
81367 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
81368
81369  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
81370  }
81371 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
81372 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
81373 }
81374 break;
81375
81376 case 'ip-address':
81377 case 'ipv4':
81378 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
81379 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
81380 }
81381 break;
81382
81383 case 'ipv6':
81384 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
81385 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
81386 }
81387 break;
81388
81389 case 'host-name':
81390 case 'hostname':
81391 if (!$this->validateHostname($element)) {
81392 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
81393 }
81394 break;
81395
81396 default:
81397
81398  
81399  
81400  
81401  
81402  
81403  break;
81404 }
81405 }
81406
81407 protected function validateDateTime($datetime, $format)
81408 {
81409 $dt = \DateTime::createFromFormat($format, $datetime);
81410
81411 if (!$dt) {
81412 return false;
81413 }
81414
81415 if ($datetime === $dt->format($format)) {
81416 return true;
81417 }
81418
81419
81420  
81421  
81422  
81423  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
81424 return true;
81425 }
81426
81427 return false;
81428 }
81429
81430 protected function validateRegex($regex)
81431 {
81432 return false !== @preg_match('/' . $regex . '/u', '');
81433 }
81434
81435 protected function validateColor($color)
81436 {
81437 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
81438 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
81439 'red', 'silver', 'teal', 'white', 'yellow'))) {
81440 return true;
81441 }
81442
81443 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
81444 }
81445
81446 protected function validateStyle($style)
81447 {
81448 $properties = explode(';', rtrim($style, ';'));
81449 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
81450
81451 return empty($invalidEntries);
81452 }
81453
81454 protected function validatePhone($phone)
81455 {
81456 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
81457 }
81458
81459 protected function validateHostname($host)
81460 {
81461 $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';
81462
81463 return preg_match($hostnameRegex, $host);
81464 }
81465 }
81466 <?php
81467
81468
81469
81470
81471
81472
81473
81474
81475 namespace JsonSchema\Constraints;
81476
81477 use JsonSchema\Entity\JsonPointer;
81478
81479
81480
81481
81482
81483
81484
81485 class NumberConstraint extends Constraint
81486 {
81487
81488
81489
81490 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
81491 {
81492
81493  if (isset($schema->exclusiveMinimum)) {
81494 if (isset($schema->minimum)) {
81495 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
81496 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
81497 } elseif ($element < $schema->minimum) {
81498 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
81499 }
81500 } else {
81501 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
81502 }
81503 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
81504 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
81505 }
81506
81507
81508  if (isset($schema->exclusiveMaximum)) {
81509 if (isset($schema->maximum)) {
81510 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
81511 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
81512 } elseif ($element > $schema->maximum) {
81513 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
81514 }
81515 } else {
81516 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
81517 }
81518 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
81519 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
81520 }
81521
81522
81523  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
81524 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
81525 }
81526
81527
81528  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
81529 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
81530 }
81531
81532 $this->checkFormat($element, $schema, $path, $i);
81533 }
81534
81535 private function fmod($number1, $number2)
81536 {
81537 $modulus = ($number1 - round($number1 / $number2) * $number2);
81538 $precision = 0.0000000001;
81539
81540 if (-$precision < $modulus && $modulus < $precision) {
81541 return 0.0;
81542 }
81543
81544 return $modulus;
81545 }
81546 }
81547 <?php
81548
81549
81550
81551
81552
81553
81554
81555
81556 namespace JsonSchema\Constraints;
81557
81558 use JsonSchema\Entity\JsonPointer;
81559
81560
81561
81562
81563
81564
81565
81566 class ObjectConstraint extends Constraint
81567 {
81568
81569
81570
81571 protected $appliedDefaults = array();
81572
81573
81574
81575
81576 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
81577 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
81578 {
81579 if ($element instanceof UndefinedConstraint) {
81580 return;
81581 }
81582
81583 $this->appliedDefaults = $appliedDefaults;
81584
81585 $matches = array();
81586 if ($patternProperties) {
81587
81588  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
81589 }
81590
81591 if ($properties) {
81592
81593  $this->validateProperties($element, $properties, $path);
81594 }
81595
81596
81597  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
81598 }
81599
81600 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
81601 {
81602 $try = array('/', '#', '+', '~', '%');
81603 $matches = array();
81604 foreach ($patternProperties as $pregex => $schema) {
81605 $delimiter = '/';
81606
81607  foreach ($try as $delimiter) {
81608 if (strpos($pregex, $delimiter) === false) { 
81609  break;
81610 }
81611 }
81612
81613
81614  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
81615 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
81616 continue;
81617 }
81618 foreach ($element as $i => $value) {
81619 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
81620 $matches[] = $i;
81621 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
81622 }
81623 }
81624 }
81625
81626 return $matches;
81627 }
81628
81629
81630
81631
81632
81633
81634
81635
81636
81637
81638
81639 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
81640 $properties = null, $additionalProp = null)
81641 {
81642 $this->validateMinMaxConstraint($element, $schema, $path);
81643
81644 foreach ($element as $i => $value) {
81645 $definition = $this->getProperty($properties, $i);
81646
81647
81648  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
81649 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
81650 }
81651
81652
81653  if (!in_array($i, $matches) && $additionalProp && !$definition) {
81654 if ($additionalProp === true) {
81655 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
81656 } else {
81657 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
81658 }
81659 }
81660
81661
81662  $require = $this->getProperty($definition, 'requires');
81663 if ($require && !$this->getProperty($element, $require)) {
81664 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
81665 }
81666
81667 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
81668 if (is_object($property)) {
81669 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
81670 }
81671 }
81672 }
81673
81674
81675
81676
81677
81678
81679
81680
81681 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
81682 {
81683 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
81684
81685 foreach ($properties as $i => $value) {
81686 $property = &$this->getProperty($element, $i, $undefinedConstraint);
81687 $definition = $this->getProperty($properties, $i);
81688
81689 if (is_object($definition)) {
81690
81691  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
81692 }
81693 }
81694 }
81695
81696
81697
81698
81699
81700
81701
81702
81703
81704
81705 protected function &getProperty(&$element, $property, $fallback = null)
81706 {
81707 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
81708 return $element[$property];
81709 } elseif (is_object($element) && property_exists($element, $property)) {
81710 return $element->$property;
81711 }
81712
81713 return $fallback;
81714 }
81715
81716
81717
81718
81719
81720
81721
81722
81723 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
81724 {
81725
81726  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
81727 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
81728 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
81729 }
81730 }
81731
81732  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
81733 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
81734 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
81735 }
81736 }
81737 }
81738 }
81739 <?php
81740
81741
81742
81743
81744
81745
81746
81747
81748 namespace JsonSchema\Constraints;
81749
81750 use JsonSchema\Entity\JsonPointer;
81751 use JsonSchema\Exception\InvalidArgumentException;
81752 use JsonSchema\Exception\InvalidSchemaException;
81753 use JsonSchema\Exception\RuntimeException;
81754 use JsonSchema\Validator;
81755
81756
81757
81758
81759
81760
81761
81762 class SchemaConstraint extends Constraint
81763 {
81764 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
81765
81766
81767
81768
81769 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
81770 {
81771 if ($schema !== null) {
81772
81773  $validationSchema = $schema;
81774 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
81775
81776  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
81777 } else {
81778 throw new InvalidArgumentException('no schema found to verify against');
81779 }
81780
81781
81782  if (is_array($validationSchema)) {
81783 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
81784 }
81785
81786
81787  
81788  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
81789 if (!$this->getTypeCheck()->isObject($validationSchema)) {
81790 throw new RuntimeException('Cannot validate the schema of a non-object');
81791 }
81792 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
81793 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
81794 } else {
81795 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
81796 }
81797
81798
81799  $schemaStorage = $this->factory->getSchemaStorage();
81800 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
81801 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
81802 }
81803
81804
81805  $initialErrorCount = $this->numErrors();
81806 $initialConfig = $this->factory->getConfig();
81807 $initialContext = $this->factory->getErrorContext();
81808 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
81809 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
81810 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
81811
81812
81813  try {
81814 $this->check($validationSchema, $schemaSpec);
81815 } catch (\Exception $e) {
81816 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
81817 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
81818 }
81819 }
81820 if ($this->numErrors() > $initialErrorCount) {
81821 $this->addError($path, 'Schema is not valid', 'schema');
81822 }
81823
81824
81825  $this->factory->setConfig($initialConfig);
81826 $this->factory->setErrorContext($initialContext);
81827 }
81828
81829
81830  $this->checkUndefined($element, $validationSchema, $path, $i);
81831 }
81832 }
81833 <?php
81834
81835
81836
81837
81838
81839
81840
81841
81842 namespace JsonSchema\Constraints;
81843
81844 use JsonSchema\Entity\JsonPointer;
81845
81846
81847
81848
81849
81850
81851
81852 class StringConstraint extends Constraint
81853 {
81854
81855
81856
81857 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
81858 {
81859
81860  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
81861 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
81862 'maxLength' => $schema->maxLength,
81863 ));
81864 }
81865
81866
81867  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
81868 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
81869 'minLength' => $schema->minLength,
81870 ));
81871 }
81872
81873
81874  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
81875 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
81876 'pattern' => $schema->pattern,
81877 ));
81878 }
81879
81880 $this->checkFormat($element, $schema, $path, $i);
81881 }
81882
81883 private function strlen($string)
81884 {
81885 if (extension_loaded('mbstring')) {
81886 return mb_strlen($string, mb_detect_encoding($string));
81887 }
81888
81889
81890  return strlen($string); 
81891  }
81892 }
81893 <?php
81894
81895 namespace JsonSchema\Constraints\TypeCheck;
81896
81897 class LooseTypeCheck implements TypeCheckInterface
81898 {
81899 public static function isObject($value)
81900 {
81901 return
81902 is_object($value) ||
81903 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
81904 }
81905
81906 public static function isArray($value)
81907 {
81908 return
81909 is_array($value) &&
81910 (count($value) == 0 || !self::isAssociativeArray($value));
81911 }
81912
81913 public static function propertyGet($value, $property)
81914 {
81915 if (is_object($value)) {
81916 return $value->{$property};
81917 }
81918
81919 return $value[$property];
81920 }
81921
81922 public static function propertySet(&$value, $property, $data)
81923 {
81924 if (is_object($value)) {
81925 $value->{$property} = $data;
81926 } else {
81927 $value[$property] = $data;
81928 }
81929 }
81930
81931 public static function propertyExists($value, $property)
81932 {
81933 if (is_object($value)) {
81934 return property_exists($value, $property);
81935 }
81936
81937 return array_key_exists($property, $value);
81938 }
81939
81940 public static function propertyCount($value)
81941 {
81942 if (is_object($value)) {
81943 return count(get_object_vars($value));
81944 }
81945
81946 return count($value);
81947 }
81948
81949
81950
81951
81952
81953
81954
81955
81956 private static function isAssociativeArray($arr)
81957 {
81958 return array_keys($arr) !== range(0, count($arr) - 1);
81959 }
81960 }
81961 <?php
81962
81963 namespace JsonSchema\Constraints\TypeCheck;
81964
81965 class StrictTypeCheck implements TypeCheckInterface
81966 {
81967 public static function isObject($value)
81968 {
81969 return is_object($value);
81970 }
81971
81972 public static function isArray($value)
81973 {
81974 return is_array($value);
81975 }
81976
81977 public static function propertyGet($value, $property)
81978 {
81979 return $value->{$property};
81980 }
81981
81982 public static function propertySet(&$value, $property, $data)
81983 {
81984 $value->{$property} = $data;
81985 }
81986
81987 public static function propertyExists($value, $property)
81988 {
81989 return property_exists($value, $property);
81990 }
81991
81992 public static function propertyCount($value)
81993 {
81994 if (!is_object($value)) {
81995 return 0;
81996 }
81997
81998 return count(get_object_vars($value));
81999 }
82000 }
82001 <?php
82002
82003 namespace JsonSchema\Constraints\TypeCheck;
82004
82005 interface TypeCheckInterface
82006 {
82007 public static function isObject($value);
82008
82009 public static function isArray($value);
82010
82011 public static function propertyGet($value, $property);
82012
82013 public static function propertySet(&$value, $property, $data);
82014
82015 public static function propertyExists($value, $property);
82016
82017 public static function propertyCount($value);
82018 }
82019 <?php
82020
82021
82022
82023
82024
82025
82026
82027
82028 namespace JsonSchema\Constraints;
82029
82030 use JsonSchema\Entity\JsonPointer;
82031 use JsonSchema\Exception\InvalidArgumentException;
82032 use UnexpectedValueException as StandardUnexpectedValueException;
82033
82034
82035
82036
82037
82038
82039
82040 class TypeConstraint extends Constraint
82041 {
82042
82043
82044
82045 public static $wording = array(
82046 'integer' => 'an integer',
82047 'number' => 'a number',
82048 'boolean' => 'a boolean',
82049 'object' => 'an object',
82050 'array' => 'an array',
82051 'string' => 'a string',
82052 'null' => 'a null',
82053 'any' => null, 
82054  0 => null, 
82055  );
82056
82057
82058
82059
82060 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
82061 {
82062 $type = isset($schema->type) ? $schema->type : null;
82063 $isValid = false;
82064 $wording = array();
82065
82066 if (is_array($type)) {
82067 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
82068 } elseif (is_object($type)) {
82069 $this->checkUndefined($value, $type, $path);
82070
82071 return;
82072 } else {
82073 $isValid = $this->validateType($value, $type);
82074 }
82075
82076 if ($isValid === false) {
82077 if (!is_array($type)) {
82078 $this->validateTypeNameWording($type);
82079 $wording[] = self::$wording[$type];
82080 }
82081 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
82082 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
82083 }
82084 }
82085
82086
82087
82088
82089
82090
82091
82092
82093
82094
82095
82096
82097 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
82098 {
82099 foreach ($type as $tp) {
82100
82101  
82102  if (is_object($tp)) {
82103 if (!$isValid) {
82104 $validator = $this->factory->createInstanceFor('type');
82105 $subSchema = new \stdClass();
82106 $subSchema->type = $tp;
82107 $validator->check($value, $subSchema, $path, null);
82108 $error = $validator->getErrors();
82109 $isValid = !(bool) $error;
82110 $validTypesWording[] = self::$wording['object'];
82111 }
82112 } else {
82113 $this->validateTypeNameWording($tp);
82114 $validTypesWording[] = self::$wording[$tp];
82115 if (!$isValid) {
82116 $isValid = $this->validateType($value, $tp);
82117 }
82118 }
82119 }
82120 }
82121
82122
82123
82124
82125
82126
82127
82128
82129
82130
82131
82132
82133 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
82134 {
82135 if ($listEnd === false || !isset($elements[1])) {
82136 return implode($delimiter, $elements);
82137 }
82138 $lastElement = array_slice($elements, -1);
82139 $firsElements = join($delimiter, array_slice($elements, 0, -1));
82140 $implodedElements = array_merge(array($firsElements), $lastElement);
82141
82142 return join(" $listEnd ", $implodedElements);
82143 }
82144
82145
82146
82147
82148
82149
82150
82151
82152
82153 protected function validateTypeNameWording($type)
82154 {
82155 if (!isset(self::$wording[$type])) {
82156 throw new StandardUnexpectedValueException(
82157 sprintf(
82158 'No wording for %s available, expected wordings are: [%s]',
82159 var_export($type, true),
82160 implode(', ', array_filter(self::$wording)))
82161 );
82162 }
82163 }
82164
82165
82166
82167
82168
82169
82170
82171
82172
82173
82174
82175 protected function validateType(&$value, $type)
82176 {
82177
82178  if (!$type) {
82179 return true;
82180 }
82181
82182 if ('any' === $type) {
82183 return true;
82184 }
82185
82186 if ('object' === $type) {
82187 return $this->getTypeCheck()->isObject($value);
82188 }
82189
82190 if ('array' === $type) {
82191 return $this->getTypeCheck()->isArray($value);
82192 }
82193
82194 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
82195
82196 if ('integer' === $type) {
82197 if ($coerce) {
82198 $value = $this->toInteger($value);
82199 }
82200
82201 return is_int($value);
82202 }
82203
82204 if ('number' === $type) {
82205 if ($coerce) {
82206 $value = $this->toNumber($value);
82207 }
82208
82209 return is_numeric($value) && !is_string($value);
82210 }
82211
82212 if ('boolean' === $type) {
82213 if ($coerce) {
82214 $value = $this->toBoolean($value);
82215 }
82216
82217 return is_bool($value);
82218 }
82219
82220 if ('string' === $type) {
82221 return is_string($value);
82222 }
82223
82224 if ('email' === $type) {
82225 return is_string($value);
82226 }
82227
82228 if ('null' === $type) {
82229 return is_null($value);
82230 }
82231
82232 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
82233 }
82234
82235
82236
82237
82238
82239
82240
82241
82242 protected function toBoolean($value)
82243 {
82244 if ($value === 'true') {
82245 return true;
82246 }
82247
82248 if ($value === 'false') {
82249 return false;
82250 }
82251
82252 return $value;
82253 }
82254
82255
82256
82257
82258
82259
82260
82261
82262 protected function toNumber($value)
82263 {
82264 if (is_numeric($value)) {
82265 return $value + 0; 
82266  }
82267
82268 return $value;
82269 }
82270
82271 protected function toInteger($value)
82272 {
82273 if (is_numeric($value) && (int) $value == $value) {
82274 return (int) $value; 
82275  }
82276
82277 return $value;
82278 }
82279 }
82280 <?php
82281
82282
82283
82284
82285
82286
82287
82288
82289 namespace JsonSchema\Constraints;
82290
82291 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
82292 use JsonSchema\Entity\JsonPointer;
82293 use JsonSchema\Exception\ValidationException;
82294 use JsonSchema\Uri\UriResolver;
82295
82296
82297
82298
82299
82300
82301
82302 class UndefinedConstraint extends Constraint
82303 {
82304
82305
82306
82307 protected $appliedDefaults = array();
82308
82309
82310
82311
82312 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
82313 {
82314 if (is_null($schema) || !is_object($schema)) {
82315 return;
82316 }
82317
82318 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
82319 if ($fromDefault) {
82320 $path->setFromDefault();
82321 }
82322
82323
82324  $this->validateCommonProperties($value, $schema, $path, $i);
82325
82326
82327  $this->validateOfProperties($value, $schema, $path, '');
82328
82329
82330  $this->validateTypes($value, $schema, $path, $i);
82331 }
82332
82333
82334
82335
82336
82337
82338
82339
82340
82341 public function validateTypes(&$value, $schema, JsonPointer $path, $i = null)
82342 {
82343
82344  if ($this->getTypeCheck()->isArray($value)) {
82345 $this->checkArray($value, $schema, $path, $i);
82346 }
82347
82348
82349  if (LooseTypeCheck::isObject($value)) { 
82350  
82351  
82352  $this->checkObject(
82353 $value,
82354 $schema,
82355 $path,
82356 isset($schema->properties) ? $schema->properties : null,
82357 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
82358 isset($schema->patternProperties) ? $schema->patternProperties : null,
82359 $this->appliedDefaults
82360 );
82361 }
82362
82363
82364  if (is_string($value)) {
82365 $this->checkString($value, $schema, $path, $i);
82366 }
82367
82368
82369  if (is_numeric($value)) {
82370 $this->checkNumber($value, $schema, $path, $i);
82371 }
82372
82373
82374  if (isset($schema->enum)) {
82375 $this->checkEnum($value, $schema, $path, $i);
82376 }
82377 }
82378
82379
82380
82381
82382
82383
82384
82385
82386
82387 protected function validateCommonProperties(&$value, $schema, JsonPointer $path, $i = '')
82388 {
82389
82390  if (isset($schema->extends)) {
82391 if (is_string($schema->extends)) {
82392 $schema->extends = $this->validateUri($schema, $schema->extends);
82393 }
82394 if (is_array($schema->extends)) {
82395 foreach ($schema->extends as $extends) {
82396 $this->checkUndefined($value, $extends, $path, $i);
82397 }
82398 } else {
82399 $this->checkUndefined($value, $schema->extends, $path, $i);
82400 }
82401 }
82402
82403
82404  if (!$path->fromDefault()) {
82405 $this->applyDefaultValues($value, $schema, $path);
82406 }
82407
82408
82409  if ($this->getTypeCheck()->isObject($value)) {
82410 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
82411
82412  foreach ($schema->required as $required) {
82413 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
82414 $this->addError(
82415 $this->incrementPath($path ?: new JsonPointer(''), $required),
82416 'The property ' . $required . ' is required',
82417 'required'
82418 );
82419 }
82420 }
82421 } elseif (isset($schema->required) && !is_array($schema->required)) {
82422
82423  if ($schema->required && $value instanceof self) {
82424 $propertyPaths = $path->getPropertyPaths();
82425 $propertyName = end($propertyPaths);
82426 $this->addError(
82427 $path,
82428 'The property ' . $propertyName . ' is required',
82429 'required'
82430 );
82431 }
82432 } else {
82433
82434  
82435  if ($value instanceof self) {
82436 return;
82437 }
82438 }
82439 }
82440
82441
82442  if (!($value instanceof self)) {
82443 $this->checkType($value, $schema, $path, $i);
82444 }
82445
82446
82447  if (isset($schema->disallow)) {
82448 $initErrors = $this->getErrors();
82449
82450 $typeSchema = new \stdClass();
82451 $typeSchema->type = $schema->disallow;
82452 $this->checkType($value, $typeSchema, $path);
82453
82454
82455  if (count($this->getErrors()) == count($initErrors)) {
82456 $this->addError($path, 'Disallowed value was matched', 'disallow');
82457 } else {
82458 $this->errors = $initErrors;
82459 }
82460 }
82461
82462 if (isset($schema->not)) {
82463 $initErrors = $this->getErrors();
82464 $this->checkUndefined($value, $schema->not, $path, $i);
82465
82466
82467  if (count($this->getErrors()) == count($initErrors)) {
82468 $this->addError($path, 'Matched a schema which it should not', 'not');
82469 } else {
82470 $this->errors = $initErrors;
82471 }
82472 }
82473
82474
82475  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
82476 $this->validateDependencies($value, $schema->dependencies, $path);
82477 }
82478 }
82479
82480
82481
82482
82483
82484
82485
82486
82487
82488
82489 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
82490 {
82491
82492  if (!$requiredOnly) {
82493 return true;
82494 }
82495
82496  if (
82497 $name !== null
82498 && isset($parentSchema->required)
82499 && is_array($parentSchema->required)
82500 && in_array($name, $parentSchema->required)
82501 ) {
82502 return true;
82503 }
82504
82505  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
82506 return true;
82507 }
82508
82509  return false;
82510 }
82511
82512
82513
82514
82515
82516
82517
82518
82519 protected function applyDefaultValues(&$value, $schema, $path)
82520 {
82521
82522  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
82523 return;
82524 }
82525
82526
82527  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
82528 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
82529
82530  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
82531 $propertyDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($propertyDefinition);
82532 if (
82533 !LooseTypeCheck::propertyExists($value, $currentProperty)
82534 && property_exists($propertyDefinition, 'default')
82535 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
82536 ) {
82537
82538  if (is_object($propertyDefinition->default)) {
82539 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
82540 } else {
82541 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
82542 }
82543 $this->appliedDefaults[] = $currentProperty;
82544 }
82545 }
82546 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
82547 $items = array();
82548 if (LooseTypeCheck::isArray($schema->items)) {
82549 $items = $schema->items;
82550 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
82551 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
82552 }
82553
82554  foreach ($items as $currentItem => $itemDefinition) {
82555 $itemDefinition = $this->factory->getSchemaStorage()->resolveRefSchema($itemDefinition);
82556 if (
82557 !array_key_exists($currentItem, $value)
82558 && property_exists($itemDefinition, 'default')
82559 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
82560 if (is_object($itemDefinition->default)) {
82561 $value[$currentItem] = clone $itemDefinition->default;
82562 } else {
82563 $value[$currentItem] = $itemDefinition->default;
82564 }
82565 }
82566 $path->setFromDefault();
82567 }
82568 } elseif (
82569 $value instanceof self
82570 && property_exists($schema, 'default')
82571 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
82572
82573  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
82574 $path->setFromDefault();
82575 }
82576 }
82577
82578
82579
82580
82581
82582
82583
82584
82585
82586 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
82587 {
82588
82589  if ($value instanceof self) {
82590 return;
82591 }
82592
82593 if (isset($schema->allOf)) {
82594 $isValid = true;
82595 foreach ($schema->allOf as $allOf) {
82596 $initErrors = $this->getErrors();
82597 $this->checkUndefined($value, $allOf, $path, $i);
82598 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
82599 }
82600 if (!$isValid) {
82601 $this->addError($path, 'Failed to match all schemas', 'allOf');
82602 }
82603 }
82604
82605 if (isset($schema->anyOf)) {
82606 $isValid = false;
82607 $startErrors = $this->getErrors();
82608 $caughtException = null;
82609 foreach ($schema->anyOf as $anyOf) {
82610 $initErrors = $this->getErrors();
82611 try {
82612 $this->checkUndefined($value, $anyOf, $path, $i);
82613 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
82614 break;
82615 }
82616 } catch (ValidationException $e) {
82617 $isValid = false;
82618 }
82619 }
82620 if (!$isValid) {
82621 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
82622 } else {
82623 $this->errors = $startErrors;
82624 }
82625 }
82626
82627 if (isset($schema->oneOf)) {
82628 $allErrors = array();
82629 $matchedSchemas = 0;
82630 $startErrors = $this->getErrors();
82631 foreach ($schema->oneOf as $oneOf) {
82632 try {
82633 $this->errors = array();
82634 $this->checkUndefined($value, $oneOf, $path, $i);
82635 if (count($this->getErrors()) == 0) {
82636 $matchedSchemas++;
82637 }
82638 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
82639 } catch (ValidationException $e) {
82640
82641  
82642  }
82643 }
82644 if ($matchedSchemas !== 1) {
82645 $this->addErrors(array_merge($allErrors, $startErrors));
82646 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
82647 } else {
82648 $this->errors = $startErrors;
82649 }
82650 }
82651 }
82652
82653
82654
82655
82656
82657
82658
82659
82660
82661 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
82662 {
82663 foreach ($dependencies as $key => $dependency) {
82664 if ($this->getTypeCheck()->propertyExists($value, $key)) {
82665 if (is_string($dependency)) {
82666
82667  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
82668 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
82669 }
82670 } elseif (is_array($dependency)) {
82671
82672  foreach ($dependency as $d) {
82673 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
82674 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
82675 }
82676 }
82677 } elseif (is_object($dependency)) {
82678
82679  $this->checkUndefined($value, $dependency, $path, $i);
82680 }
82681 }
82682 }
82683 }
82684
82685 protected function validateUri($schema, $schemaUri = null)
82686 {
82687 $resolver = new UriResolver();
82688 $retriever = $this->factory->getUriRetriever();
82689
82690 $jsonSchema = null;
82691 if ($resolver->isValid($schemaUri)) {
82692 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
82693 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
82694 }
82695
82696 return $jsonSchema;
82697 }
82698 }
82699 <?php
82700
82701
82702
82703
82704
82705
82706
82707
82708 namespace JsonSchema\Entity;
82709
82710 use JsonSchema\Exception\InvalidArgumentException;
82711
82712
82713
82714
82715
82716
82717 class JsonPointer
82718 {
82719
82720 private $filename;
82721
82722
82723 private $propertyPaths = array();
82724
82725
82726
82727
82728 private $fromDefault = false;
82729
82730
82731
82732
82733
82734
82735 public function __construct($value)
82736 {
82737 if (!is_string($value)) {
82738 throw new InvalidArgumentException('Ref value must be a string');
82739 }
82740
82741 $splitRef = explode('#', $value, 2);
82742 $this->filename = $splitRef[0];
82743 if (array_key_exists(1, $splitRef)) {
82744 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
82745 }
82746 }
82747
82748
82749
82750
82751
82752
82753 private function decodePropertyPaths($propertyPathString)
82754 {
82755 $paths = array();
82756 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
82757 $path = $this->decodePath($path);
82758 if (is_string($path) && '' !== $path) {
82759 $paths[] = $path;
82760 }
82761 }
82762
82763 return $paths;
82764 }
82765
82766
82767
82768
82769 private function encodePropertyPaths()
82770 {
82771 return array_map(
82772 array($this, 'encodePath'),
82773 $this->getPropertyPaths()
82774 );
82775 }
82776
82777
82778
82779
82780
82781
82782 private function decodePath($path)
82783 {
82784 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
82785 }
82786
82787
82788
82789
82790
82791
82792 private function encodePath($path)
82793 {
82794 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
82795 }
82796
82797
82798
82799
82800 public function getFilename()
82801 {
82802 return $this->filename;
82803 }
82804
82805
82806
82807
82808 public function getPropertyPaths()
82809 {
82810 return $this->propertyPaths;
82811 }
82812
82813
82814
82815
82816
82817
82818 public function withPropertyPaths(array $propertyPaths)
82819 {
82820 $new = clone $this;
82821 $new->propertyPaths = $propertyPaths;
82822
82823 return $new;
82824 }
82825
82826
82827
82828
82829 public function getPropertyPathAsString()
82830 {
82831 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
82832 }
82833
82834
82835
82836
82837 public function __toString()
82838 {
82839 return $this->getFilename() . $this->getPropertyPathAsString();
82840 }
82841
82842
82843
82844
82845 public function setFromDefault()
82846 {
82847 $this->fromDefault = true;
82848 }
82849
82850
82851
82852
82853
82854
82855 public function fromDefault()
82856 {
82857 return $this->fromDefault;
82858 }
82859 }
82860 <?php
82861
82862 namespace JsonSchema\Exception;
82863
82864 interface ExceptionInterface
82865 {
82866 }
82867 <?php
82868
82869
82870
82871
82872
82873
82874
82875
82876 namespace JsonSchema\Exception;
82877
82878
82879
82880
82881 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
82882 {
82883 }
82884 <?php
82885
82886
82887
82888
82889
82890
82891
82892
82893 namespace JsonSchema\Exception;
82894
82895
82896
82897
82898 class InvalidConfigException extends RuntimeException
82899 {
82900 }
82901 <?php
82902
82903
82904
82905
82906
82907
82908
82909
82910 namespace JsonSchema\Exception;
82911
82912
82913
82914
82915 class InvalidSchemaException extends RuntimeException
82916 {
82917 }
82918 <?php
82919
82920
82921
82922
82923
82924
82925
82926
82927 namespace JsonSchema\Exception;
82928
82929
82930
82931
82932 class InvalidSchemaMediaTypeException extends RuntimeException
82933 {
82934 }
82935 <?php
82936
82937
82938
82939
82940
82941
82942
82943
82944 namespace JsonSchema\Exception;
82945
82946
82947
82948
82949 class InvalidSourceUriException extends InvalidArgumentException
82950 {
82951 }
82952 <?php
82953
82954
82955
82956
82957
82958
82959
82960
82961 namespace JsonSchema\Exception;
82962
82963
82964
82965
82966 class JsonDecodingException extends RuntimeException
82967 {
82968 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
82969 {
82970 switch ($code) {
82971 case JSON_ERROR_DEPTH:
82972 $message = 'The maximum stack depth has been exceeded';
82973 break;
82974 case JSON_ERROR_STATE_MISMATCH:
82975 $message = 'Invalid or malformed JSON';
82976 break;
82977 case JSON_ERROR_CTRL_CHAR:
82978 $message = 'Control character error, possibly incorrectly encoded';
82979 break;
82980 case JSON_ERROR_UTF8:
82981 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
82982 break;
82983 case JSON_ERROR_SYNTAX:
82984 $message = 'JSON syntax is malformed';
82985 break;
82986 default:
82987 $message = 'Syntax error';
82988 }
82989 parent::__construct($message, $code, $previous);
82990 }
82991 }
82992 <?php
82993
82994
82995
82996
82997
82998
82999
83000
83001 namespace JsonSchema\Exception;
83002
83003
83004
83005
83006 class ResourceNotFoundException extends RuntimeException
83007 {
83008 }
83009 <?php
83010
83011
83012
83013
83014
83015
83016
83017
83018 namespace JsonSchema\Exception;
83019
83020
83021
83022
83023 class RuntimeException extends \RuntimeException implements ExceptionInterface
83024 {
83025 }
83026 <?php
83027
83028
83029
83030
83031
83032
83033
83034
83035 namespace JsonSchema\Exception;
83036
83037
83038
83039
83040
83041
83042 class UnresolvableJsonPointerException extends InvalidArgumentException
83043 {
83044 }
83045 <?php
83046
83047
83048
83049
83050
83051
83052
83053
83054 namespace JsonSchema\Exception;
83055
83056
83057
83058
83059 class UriResolverException extends RuntimeException
83060 {
83061 }
83062 <?php
83063
83064
83065
83066
83067
83068
83069
83070
83071 namespace JsonSchema\Exception;
83072
83073 class ValidationException extends RuntimeException
83074 {
83075 }
83076 <?php
83077
83078
83079
83080
83081
83082
83083
83084
83085 namespace JsonSchema\Iterator;
83086
83087
83088
83089
83090
83091
83092 class ObjectIterator implements \Iterator, \Countable
83093 {
83094
83095 private $object;
83096
83097
83098 private $position = 0;
83099
83100
83101 private $data = array();
83102
83103
83104 private $initialized = false;
83105
83106
83107
83108
83109 public function __construct($object)
83110 {
83111 $this->object = $object;
83112 }
83113
83114
83115
83116
83117 public function current()
83118 {
83119 $this->initialize();
83120
83121 return $this->data[$this->position];
83122 }
83123
83124
83125
83126
83127 public function next()
83128 {
83129 $this->initialize();
83130 $this->position++;
83131 }
83132
83133
83134
83135
83136 public function key()
83137 {
83138 $this->initialize();
83139
83140 return $this->position;
83141 }
83142
83143
83144
83145
83146 public function valid()
83147 {
83148 $this->initialize();
83149
83150 return isset($this->data[$this->position]);
83151 }
83152
83153
83154
83155
83156 public function rewind()
83157 {
83158 $this->initialize();
83159 $this->position = 0;
83160 }
83161
83162
83163
83164
83165 public function count()
83166 {
83167 $this->initialize();
83168
83169 return count($this->data);
83170 }
83171
83172
83173
83174
83175 private function initialize()
83176 {
83177 if (!$this->initialized) {
83178 $this->data = $this->buildDataFromObject($this->object);
83179 $this->initialized = true;
83180 }
83181 }
83182
83183
83184
83185
83186
83187
83188 private function buildDataFromObject($object)
83189 {
83190 $result = array();
83191
83192 $stack = new \SplStack();
83193 $stack->push($object);
83194
83195 while (!$stack->isEmpty()) {
83196 $current = $stack->pop();
83197 if (is_object($current)) {
83198 array_push($result, $current);
83199 }
83200
83201 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
83202 if (is_object($propertyValue) || is_array($propertyValue)) {
83203 $stack->push($propertyValue);
83204 }
83205 }
83206 }
83207
83208 return $result;
83209 }
83210
83211
83212
83213
83214
83215
83216 private function getDataFromItem($item)
83217 {
83218 if (!is_object($item) && !is_array($item)) {
83219 return array();
83220 }
83221
83222 return is_object($item) ? get_object_vars($item) : $item;
83223 }
83224 }
83225 <?php
83226
83227 namespace JsonSchema;
83228
83229 class Rfc3339
83230 {
83231 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
83232
83233
83234
83235
83236
83237
83238
83239
83240 public static function createFromString($string)
83241 {
83242 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
83243 return null;
83244 }
83245
83246 $dateAndTime = $matches[1];
83247 $microseconds = $matches[2] ?: '.000000';
83248 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
83249 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
83250 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
83251
83252 return $dateTime ?: null;
83253 }
83254 }
83255 <?php
83256
83257 namespace JsonSchema;
83258
83259 use JsonSchema\Constraints\BaseConstraint;
83260 use JsonSchema\Entity\JsonPointer;
83261 use JsonSchema\Exception\UnresolvableJsonPointerException;
83262 use JsonSchema\Uri\UriResolver;
83263 use JsonSchema\Uri\UriRetriever;
83264
83265 class SchemaStorage implements SchemaStorageInterface
83266 {
83267 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema/';
83268
83269 protected $uriRetriever;
83270 protected $uriResolver;
83271 protected $schemas = array();
83272
83273 public function __construct(
83274 UriRetrieverInterface $uriRetriever = null,
83275 UriResolverInterface $uriResolver = null
83276 ) {
83277 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
83278 $this->uriResolver = $uriResolver ?: new UriResolver();
83279 }
83280
83281
83282
83283
83284 public function getUriRetriever()
83285 {
83286 return $this->uriRetriever;
83287 }
83288
83289
83290
83291
83292 public function getUriResolver()
83293 {
83294 return $this->uriResolver;
83295 }
83296
83297
83298
83299
83300 public function addSchema($id, $schema = null)
83301 {
83302 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
83303
83304  
83305  
83306  $schema = $this->uriRetriever->retrieve($id);
83307 }
83308
83309
83310  if (is_array($schema)) {
83311 $schema = BaseConstraint::arrayToObjectRecursive($schema);
83312 }
83313
83314
83315  
83316  if (is_object($schema) && property_exists($schema, 'id')) {
83317 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
83318 $schema->properties->id->format = 'uri-reference';
83319 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
83320 $schema->properties->id->format = 'uri-reference';
83321 $schema->properties->{'$ref'}->format = 'uri-reference';
83322 }
83323 }
83324
83325
83326  $this->expandRefs($schema, $id);
83327
83328 $this->schemas[$id] = $schema;
83329 }
83330
83331
83332
83333
83334
83335
83336
83337 private function expandRefs(&$schema, $base = null)
83338 {
83339 if (!is_object($schema)) {
83340 if (is_array($schema)) {
83341 foreach ($schema as &$member) {
83342 $this->expandRefs($member, $base);
83343 }
83344 }
83345
83346 return;
83347 }
83348
83349 if (property_exists($schema, 'id') && is_string($schema->id) && $base != $schema->id) {
83350 $base = $this->uriResolver->resolve($schema->id, $base);
83351 }
83352
83353 if (property_exists($schema, '$ref') && is_string($schema->{'$ref'})) {
83354 $refPointer = new JsonPointer($this->uriResolver->resolve($schema->{'$ref'}, $base));
83355 $schema->{'$ref'} = (string) $refPointer;
83356 }
83357
83358 foreach ($schema as &$member) {
83359 $this->expandRefs($member, $base);
83360 }
83361 }
83362
83363
83364
83365
83366 public function getSchema($id)
83367 {
83368 if (!array_key_exists($id, $this->schemas)) {
83369 $this->addSchema($id);
83370 }
83371
83372 return $this->schemas[$id];
83373 }
83374
83375
83376
83377
83378 public function resolveRef($ref)
83379 {
83380 $jsonPointer = new JsonPointer($ref);
83381
83382
83383  $fileName = $jsonPointer->getFilename();
83384 if (!strlen($fileName)) {
83385 throw new UnresolvableJsonPointerException(sprintf(
83386 "Could not resolve fragment '%s': no file is defined",
83387 $jsonPointer->getPropertyPathAsString()
83388 ));
83389 }
83390
83391
83392  $refSchema = $this->getSchema($fileName);
83393 foreach ($jsonPointer->getPropertyPaths() as $path) {
83394 if (is_object($refSchema) && property_exists($refSchema, $path)) {
83395 $refSchema = $this->resolveRefSchema($refSchema->{$path});
83396 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
83397 $refSchema = $this->resolveRefSchema($refSchema[$path]);
83398 } else {
83399 throw new UnresolvableJsonPointerException(sprintf(
83400 'File: %s is found, but could not resolve fragment: %s',
83401 $jsonPointer->getFilename(),
83402 $jsonPointer->getPropertyPathAsString()
83403 ));
83404 }
83405 }
83406
83407 return $refSchema;
83408 }
83409
83410
83411
83412
83413 public function resolveRefSchema($refSchema)
83414 {
83415 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
83416 $newSchema = $this->resolveRef($refSchema->{'$ref'});
83417 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
83418 unset($refSchema->{'$ref'});
83419 }
83420
83421 return $refSchema;
83422 }
83423 }
83424 <?php
83425
83426 namespace JsonSchema;
83427
83428 interface SchemaStorageInterface
83429 {
83430
83431
83432
83433
83434
83435
83436 public function addSchema($id, $schema = null);
83437
83438
83439
83440
83441
83442
83443
83444
83445 public function getSchema($id);
83446
83447
83448
83449
83450
83451
83452
83453
83454 public function resolveRef($ref);
83455
83456
83457
83458
83459
83460
83461
83462
83463 public function resolveRefSchema($refSchema);
83464 }
83465 <?php
83466
83467
83468
83469
83470
83471
83472 namespace JsonSchema\Uri\Retrievers;
83473
83474
83475
83476
83477
83478
83479
83480 abstract class AbstractRetriever implements UriRetrieverInterface
83481 {
83482
83483
83484
83485
83486
83487 protected $contentType;
83488
83489
83490
83491
83492
83493
83494 public function getContentType()
83495 {
83496 return $this->contentType;
83497 }
83498 }
83499 <?php
83500
83501
83502
83503
83504
83505
83506
83507
83508 namespace JsonSchema\Uri\Retrievers;
83509
83510 use JsonSchema\Exception\RuntimeException;
83511 use JsonSchema\Validator;
83512
83513
83514
83515
83516
83517
83518 class Curl extends AbstractRetriever
83519 {
83520 protected $messageBody;
83521
83522 public function __construct()
83523 {
83524 if (!function_exists('curl_init')) {
83525
83526  throw new RuntimeException('cURL not installed'); 
83527  }
83528 }
83529
83530
83531
83532
83533
83534
83535 public function retrieve($uri)
83536 {
83537 $ch = curl_init();
83538
83539 curl_setopt($ch, CURLOPT_URL, $uri);
83540 curl_setopt($ch, CURLOPT_HEADER, true);
83541 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
83542 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
83543
83544 $response = curl_exec($ch);
83545 if (false === $response) {
83546 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
83547 }
83548
83549 $this->fetchMessageBody($response);
83550 $this->fetchContentType($response);
83551
83552 curl_close($ch);
83553
83554 return $this->messageBody;
83555 }
83556
83557
83558
83559
83560 private function fetchMessageBody($response)
83561 {
83562 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
83563 $this->messageBody = $match[1];
83564 }
83565
83566
83567
83568
83569
83570
83571 protected function fetchContentType($response)
83572 {
83573 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
83574 $this->contentType = trim($match[1]);
83575
83576 return true;
83577 }
83578
83579 return false;
83580 }
83581 }
83582 <?php
83583
83584
83585
83586
83587
83588
83589
83590
83591 namespace JsonSchema\Uri\Retrievers;
83592
83593 use JsonSchema\Exception\ResourceNotFoundException;
83594
83595
83596
83597
83598
83599
83600 class FileGetContents extends AbstractRetriever
83601 {
83602 protected $messageBody;
83603
83604
83605
83606
83607
83608
83609 public function retrieve($uri)
83610 {
83611 $errorMessage = null;
83612 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
83613 $errorMessage = $errstr;
83614 });
83615 $response = file_get_contents($uri);
83616 restore_error_handler();
83617
83618 if ($errorMessage) {
83619 throw new ResourceNotFoundException($errorMessage);
83620 }
83621
83622 if (false === $response) {
83623 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
83624 }
83625
83626 if ($response == ''
83627 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
83628 ) {
83629 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
83630 }
83631
83632 $this->messageBody = $response;
83633 if (!empty($http_response_header)) {
83634
83635  
83636  $this->fetchContentType($http_response_header); 
83637  } else { 
83638  
83639  $this->contentType = null;
83640 }
83641
83642 return $this->messageBody;
83643 }
83644
83645
83646
83647
83648
83649
83650 private function fetchContentType(array $headers)
83651 {
83652 foreach ($headers as $header) {
83653 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
83654 return true;
83655 }
83656 }
83657
83658 return false;
83659 }
83660
83661
83662
83663
83664
83665
83666 protected static function getContentTypeMatchInHeader($header)
83667 {
83668 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
83669 return trim($match[1]);
83670 }
83671
83672 return null;
83673 }
83674 }
83675 <?php
83676
83677 namespace JsonSchema\Uri\Retrievers;
83678
83679 use JsonSchema\Validator;
83680
83681
83682
83683
83684
83685
83686
83687
83688
83689
83690
83691
83692
83693 class PredefinedArray extends AbstractRetriever
83694 {
83695
83696
83697
83698
83699
83700 private $schemas;
83701
83702
83703
83704
83705
83706
83707
83708 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
83709 {
83710 $this->schemas = $schemas;
83711 $this->contentType = $contentType;
83712 }
83713
83714
83715
83716
83717
83718
83719 public function retrieve($uri)
83720 {
83721 if (!array_key_exists($uri, $this->schemas)) {
83722 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
83723 'The JSON schema "%s" was not found.',
83724 $uri
83725 ));
83726 }
83727
83728 return $this->schemas[$uri];
83729 }
83730 }
83731 <?php
83732
83733
83734
83735
83736
83737
83738
83739
83740 namespace JsonSchema\Uri\Retrievers;
83741
83742
83743
83744
83745
83746
83747 interface UriRetrieverInterface
83748 {
83749
83750
83751
83752
83753
83754
83755
83756
83757
83758 public function retrieve($uri);
83759
83760
83761
83762
83763
83764
83765 public function getContentType();
83766 }
83767 <?php
83768
83769
83770
83771
83772
83773
83774
83775
83776 namespace JsonSchema\Uri;
83777
83778 use JsonSchema\Exception\UriResolverException;
83779 use JsonSchema\UriResolverInterface;
83780
83781
83782
83783
83784
83785
83786 class UriResolver implements UriResolverInterface
83787 {
83788
83789
83790
83791
83792
83793
83794
83795 public function parse($uri)
83796 {
83797 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
83798
83799 $components = array();
83800 if (5 < count($match)) {
83801 $components = array(
83802 'scheme' => $match[2],
83803 'authority' => $match[4],
83804 'path' => $match[5]
83805 );
83806 }
83807 if (7 < count($match)) {
83808 $components['query'] = $match[7];
83809 }
83810 if (9 < count($match)) {
83811 $components['fragment'] = $match[9];
83812 }
83813
83814 return $components;
83815 }
83816
83817
83818
83819
83820
83821
83822
83823
83824 public function generate(array $components)
83825 {
83826 $uri = $components['scheme'] . '://'
83827 . $components['authority']
83828 . $components['path'];
83829
83830 if (array_key_exists('query', $components) && strlen($components['query'])) {
83831 $uri .= '?' . $components['query'];
83832 }
83833 if (array_key_exists('fragment', $components)) {
83834 $uri .= '#' . $components['fragment'];
83835 }
83836
83837 return $uri;
83838 }
83839
83840
83841
83842
83843 public function resolve($uri, $baseUri = null)
83844 {
83845
83846  if (
83847 !is_null($baseUri) &&
83848 !filter_var($baseUri, \FILTER_VALIDATE_URL) &&
83849 !preg_match('|^[^/]+://|u', $baseUri)
83850 ) {
83851 if (is_file($baseUri)) {
83852 $baseUri = 'file://' . realpath($baseUri);
83853 } elseif (is_dir($baseUri)) {
83854 $baseUri = 'file://' . realpath($baseUri) . '/';
83855 } else {
83856 $baseUri = 'file://' . getcwd() . '/' . $baseUri;
83857 }
83858 }
83859
83860 if ($uri == '') {
83861 return $baseUri;
83862 }
83863
83864 $components = $this->parse($uri);
83865 $path = $components['path'];
83866
83867 if (!empty($components['scheme'])) {
83868 return $uri;
83869 }
83870 $baseComponents = $this->parse($baseUri);
83871 $basePath = $baseComponents['path'];
83872
83873 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
83874 if (isset($components['fragment'])) {
83875 $baseComponents['fragment'] = $components['fragment'];
83876 }
83877
83878 return $this->generate($baseComponents);
83879 }
83880
83881
83882
83883
83884
83885
83886
83887
83888
83889
83890
83891 public static function combineRelativePathWithBasePath($relativePath, $basePath)
83892 {
83893 $relativePath = self::normalizePath($relativePath);
83894 if ($relativePath == '') {
83895 return $basePath;
83896 }
83897 if ($relativePath[0] == '/') {
83898 return $relativePath;
83899 }
83900
83901 $basePathSegments = explode('/', $basePath);
83902
83903 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
83904 $numLevelUp = strlen($match[0]) /3 + 1;
83905 if ($numLevelUp >= count($basePathSegments)) {
83906 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
83907 }
83908
83909 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
83910 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
83911
83912 return implode('/', $basePathSegments) . '/' . $path;
83913 }
83914
83915
83916
83917
83918
83919
83920
83921
83922 private static function normalizePath($path)
83923 {
83924 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
83925 $path = preg_replace('|//|', '/', $path);
83926
83927 return $path;
83928 }
83929
83930
83931
83932
83933
83934
83935 public function isValid($uri)
83936 {
83937 $components = $this->parse($uri);
83938
83939 return !empty($components);
83940 }
83941 }
83942 <?php
83943
83944
83945
83946
83947
83948
83949
83950
83951 namespace JsonSchema\Uri;
83952
83953 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
83954 use JsonSchema\Exception\JsonDecodingException;
83955 use JsonSchema\Exception\ResourceNotFoundException;
83956 use JsonSchema\Uri\Retrievers\FileGetContents;
83957 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
83958 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
83959 use JsonSchema\Validator;
83960
83961
83962
83963
83964
83965
83966 class UriRetriever implements BaseUriRetrieverInterface
83967 {
83968
83969
83970
83971 protected $translationMap = array(
83972
83973  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
83974 );
83975
83976
83977
83978
83979 protected $allowedInvalidContentTypeEndpoints = array(
83980 'http://json-schema.org/',
83981 'https://json-schema.org/'
83982 );
83983
83984
83985
83986
83987 protected $uriRetriever = null;
83988
83989
83990
83991
83992
83993
83994 private $schemaCache = array();
83995
83996
83997
83998
83999
84000
84001 public function addInvalidContentTypeEndpoint($endpoint)
84002 {
84003 $this->allowedInvalidContentTypeEndpoints[] = $endpoint;
84004 }
84005
84006
84007
84008
84009
84010
84011
84012
84013
84014 public function confirmMediaType($uriRetriever, $uri)
84015 {
84016 $contentType = $uriRetriever->getContentType();
84017
84018 if (is_null($contentType)) {
84019
84020  return;
84021 }
84022
84023 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
84024 return;
84025 }
84026
84027 foreach ($this->allowedInvalidContentTypeEndpoints as $endpoint) {
84028 if (strpos($uri, $endpoint) === 0) {
84029 return true;
84030 }
84031 }
84032
84033 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
84034 }
84035
84036
84037
84038
84039
84040
84041
84042
84043
84044 public function getUriRetriever()
84045 {
84046 if (is_null($this->uriRetriever)) {
84047 $this->setUriRetriever(new FileGetContents());
84048 }
84049
84050 return $this->uriRetriever;
84051 }
84052
84053
84054
84055
84056
84057
84058
84059
84060
84061
84062
84063
84064
84065
84066
84067 public function resolvePointer($jsonSchema, $uri)
84068 {
84069 $resolver = new UriResolver();
84070 $parsed = $resolver->parse($uri);
84071 if (empty($parsed['fragment'])) {
84072 return $jsonSchema;
84073 }
84074
84075 $path = explode('/', $parsed['fragment']);
84076 while ($path) {
84077 $pathElement = array_shift($path);
84078 if (!empty($pathElement)) {
84079 $pathElement = str_replace('~1', '/', $pathElement);
84080 $pathElement = str_replace('~0', '~', $pathElement);
84081 if (!empty($jsonSchema->$pathElement)) {
84082 $jsonSchema = $jsonSchema->$pathElement;
84083 } else {
84084 throw new ResourceNotFoundException(
84085 'Fragment "' . $parsed['fragment'] . '" not found'
84086 . ' in ' . $uri
84087 );
84088 }
84089
84090 if (!is_object($jsonSchema)) {
84091 throw new ResourceNotFoundException(
84092 'Fragment part "' . $pathElement . '" is no object '
84093 . ' in ' . $uri
84094 );
84095 }
84096 }
84097 }
84098
84099 return $jsonSchema;
84100 }
84101
84102
84103
84104
84105 public function retrieve($uri, $baseUri = null, $translate = true)
84106 {
84107 $resolver = new UriResolver();
84108 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
84109
84110
84111  $arParts = $resolver->parse($resolvedUri);
84112 if (isset($arParts['fragment'])) {
84113 unset($arParts['fragment']);
84114 $fetchUri = $resolver->generate($arParts);
84115 }
84116
84117
84118  if ($translate) {
84119 $fetchUri = $this->translate($fetchUri);
84120 }
84121
84122 $jsonSchema = $this->loadSchema($fetchUri);
84123
84124
84125  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
84126
84127 if ($jsonSchema instanceof \stdClass) {
84128 $jsonSchema->id = $resolvedUri;
84129 }
84130
84131 return $jsonSchema;
84132 }
84133
84134
84135
84136
84137
84138
84139
84140
84141
84142 protected function loadSchema($fetchUri)
84143 {
84144 if (isset($this->schemaCache[$fetchUri])) {
84145 return $this->schemaCache[$fetchUri];
84146 }
84147
84148 $uriRetriever = $this->getUriRetriever();
84149 $contents = $this->uriRetriever->retrieve($fetchUri);
84150 $this->confirmMediaType($uriRetriever, $fetchUri);
84151 $jsonSchema = json_decode($contents);
84152
84153 if (JSON_ERROR_NONE < $error = json_last_error()) {
84154 throw new JsonDecodingException($error);
84155 }
84156
84157 $this->schemaCache[$fetchUri] = $jsonSchema;
84158
84159 return $jsonSchema;
84160 }
84161
84162
84163
84164
84165
84166
84167
84168
84169 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
84170 {
84171 $this->uriRetriever = $uriRetriever;
84172
84173 return $this;
84174 }
84175
84176
84177
84178
84179
84180
84181
84182
84183 public function parse($uri)
84184 {
84185 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
84186
84187 $components = array();
84188 if (5 < count($match)) {
84189 $components = array(
84190 'scheme' => $match[2],
84191 'authority' => $match[4],
84192 'path' => $match[5]
84193 );
84194 }
84195
84196 if (7 < count($match)) {
84197 $components['query'] = $match[7];
84198 }
84199
84200 if (9 < count($match)) {
84201 $components['fragment'] = $match[9];
84202 }
84203
84204 return $components;
84205 }
84206
84207
84208
84209
84210
84211
84212
84213
84214 public function generate(array $components)
84215 {
84216 $uri = $components['scheme'] . '://'
84217 . $components['authority']
84218 . $components['path'];
84219
84220 if (array_key_exists('query', $components)) {
84221 $uri .= $components['query'];
84222 }
84223
84224 if (array_key_exists('fragment', $components)) {
84225 $uri .= $components['fragment'];
84226 }
84227
84228 return $uri;
84229 }
84230
84231
84232
84233
84234
84235
84236
84237
84238
84239 public function resolve($uri, $baseUri = null)
84240 {
84241 $components = $this->parse($uri);
84242 $path = $components['path'];
84243
84244 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
84245 return $uri;
84246 }
84247
84248 $baseComponents = $this->parse($baseUri);
84249 $basePath = $baseComponents['path'];
84250
84251 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
84252
84253 return $this->generate($baseComponents);
84254 }
84255
84256
84257
84258
84259
84260
84261 public function isValid($uri)
84262 {
84263 $components = $this->parse($uri);
84264
84265 return !empty($components);
84266 }
84267
84268
84269
84270
84271 public function setTranslation($from, $to)
84272 {
84273 $this->translationMap[$from] = $to;
84274 }
84275
84276
84277
84278
84279 public function translate($uri)
84280 {
84281 foreach ($this->translationMap as $from => $to) {
84282 $uri = preg_replace($from, $to, $uri);
84283 }
84284
84285
84286  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
84287
84288 return $uri;
84289 }
84290 }
84291 <?php
84292
84293
84294
84295
84296
84297
84298
84299
84300 namespace JsonSchema;
84301
84302
84303
84304
84305 interface UriResolverInterface
84306 {
84307
84308
84309
84310
84311
84312
84313
84314
84315 public function resolve($uri, $baseUri = null);
84316 }
84317 <?php
84318
84319
84320
84321
84322
84323
84324
84325
84326 namespace JsonSchema;
84327
84328
84329
84330
84331 interface UriRetrieverInterface
84332 {
84333
84334
84335
84336
84337
84338
84339
84340
84341 public function retrieve($uri, $baseUri = null);
84342 }
84343 <?php
84344
84345
84346
84347
84348
84349
84350
84351
84352 namespace JsonSchema;
84353
84354 use JsonSchema\Constraints\BaseConstraint;
84355 use JsonSchema\Constraints\Constraint;
84356
84357
84358
84359
84360
84361
84362
84363
84364
84365 class Validator extends BaseConstraint
84366 {
84367 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
84368
84369 const ERROR_NONE = 0x00000000;
84370 const ERROR_ALL = 0xFFFFFFFF;
84371 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
84372 const ERROR_SCHEMA_VALIDATION = 0x00000002;
84373
84374
84375
84376
84377
84378
84379
84380
84381 public function validate(&$value, $schema = null, $checkMode = null)
84382 {
84383
84384  if (is_array($schema)) {
84385 $schema = self::arrayToObjectRecursive($schema);
84386 }
84387
84388
84389  $initialCheckMode = $this->factory->getConfig();
84390 if ($checkMode !== null) {
84391 $this->factory->setConfig($checkMode);
84392 }
84393
84394
84395  if (is_object($schema) && property_exists($schema, 'id')) {
84396 $schemaURI = $schema->id;
84397 } else {
84398 $schemaURI = SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI;
84399 }
84400 $this->factory->getSchemaStorage()->addSchema($schemaURI, $schema);
84401
84402 $validator = $this->factory->createInstanceFor('schema');
84403 $validator->check(
84404 $value,
84405 $this->factory->getSchemaStorage()->getSchema($schemaURI)
84406 );
84407
84408 $this->factory->setConfig($initialCheckMode);
84409
84410 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
84411
84412 return $validator->getErrorMask();
84413 }
84414
84415
84416
84417
84418 public function check($value, $schema)
84419 {
84420 return $this->validate($value, $schema);
84421 }
84422
84423
84424
84425
84426 public function coerce(&$value, $schema)
84427 {
84428 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
84429 }
84430 }
84431 Copyright (C) 2015 Composer
84432
84433 Permission is hereby granted, free of charge, to any person obtaining a copy of
84434 this software and associated documentation files (the "Software"), to deal in
84435 the Software without restriction, including without limitation the rights to
84436 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
84437 of the Software, and to permit persons to whom the Software is furnished to do
84438 so, subject to the following conditions:
84439
84440 The above copyright notice and this permission notice shall be included in all
84441 copies or substantial portions of the Software.
84442
84443 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84444 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84445 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84446 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84447 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84448 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
84449 SOFTWARE.
84450 <?php
84451
84452
84453
84454
84455
84456
84457
84458
84459
84460
84461 namespace Composer\Spdx;
84462
84463 class SpdxLicenses
84464 {
84465
84466 const LICENSES_FILE = 'spdx-licenses.json';
84467
84468
84469 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
84470
84471
84472
84473
84474
84475
84476
84477
84478
84479
84480
84481
84482
84483
84484 private $licenses;
84485
84486
84487
84488
84489 private $licensesExpression;
84490
84491
84492
84493
84494
84495
84496
84497
84498
84499
84500
84501
84502
84503
84504 private $exceptions;
84505
84506
84507
84508
84509 private $exceptionsExpression;
84510
84511 public function __construct()
84512 {
84513 $this->loadLicenses();
84514 $this->loadExceptions();
84515 }
84516
84517
84518
84519
84520
84521
84522
84523
84524
84525
84526
84527
84528
84529 public function getLicenseByIdentifier($identifier)
84530 {
84531 $key = strtolower($identifier);
84532
84533 if (!isset($this->licenses[$key])) {
84534 return;
84535 }
84536
84537 list($identifier, $name, $isOsiApproved, $isDeprecatedLicenseId) = $this->licenses[$key];
84538
84539 return array(
84540 $name,
84541 $isOsiApproved,
84542 'https://spdx.org/licenses/' . $identifier . '.html#licenseText',
84543 $isDeprecatedLicenseId,
84544 );
84545 }
84546
84547
84548
84549
84550
84551
84552 public function getLicenses()
84553 {
84554 return $this->licenses;
84555 }
84556
84557
84558
84559
84560
84561
84562
84563
84564
84565
84566
84567
84568
84569 public function getExceptionByIdentifier($identifier)
84570 {
84571 $key = strtolower($identifier);
84572
84573 if (!isset($this->exceptions[$key])) {
84574 return;
84575 }
84576
84577 list($identifier, $name) = $this->exceptions[$key];
84578
84579 return array(
84580 $name,
84581 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText',
84582 );
84583 }
84584
84585
84586
84587
84588
84589
84590
84591
84592 public function getIdentifierByName($name)
84593 {
84594 foreach ($this->licenses as $licenseData) {
84595 if ($licenseData[1] === $name) {
84596 return $licenseData[0];
84597 }
84598 }
84599
84600 foreach ($this->exceptions as $licenseData) {
84601 if ($licenseData[1] === $name) {
84602 return $licenseData[0];
84603 }
84604 }
84605 }
84606
84607
84608
84609
84610
84611
84612
84613
84614 public function isOsiApprovedByIdentifier($identifier)
84615 {
84616 return $this->licenses[strtolower($identifier)][2];
84617 }
84618
84619
84620
84621
84622
84623
84624
84625
84626 public function isDeprecatedByIdentifier($identifier)
84627 {
84628 return $this->licenses[strtolower($identifier)][3];
84629 }
84630
84631
84632
84633
84634
84635
84636
84637
84638 public function validate($license)
84639 {
84640 if (is_array($license)) {
84641 $count = count($license);
84642 if ($count !== count(array_filter($license, 'is_string'))) {
84643 throw new \InvalidArgumentException('Array of strings expected.');
84644 }
84645 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
84646 }
84647
84648 if (!is_string($license)) {
84649 throw new \InvalidArgumentException(sprintf(
84650 'Array or String expected, %s given.',
84651 gettype($license)
84652 ));
84653 }
84654
84655 return $this->isValidLicenseString($license);
84656 }
84657
84658
84659
84660
84661 public static function getResourcesDir()
84662 {
84663 return dirname(__DIR__) . '/res';
84664 }
84665
84666 private function loadLicenses()
84667 {
84668 if (null !== $this->licenses) {
84669 return;
84670 }
84671
84672 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
84673 $this->licenses = array();
84674
84675 foreach (json_decode($json, true) as $identifier => $license) {
84676 $this->licenses[strtolower($identifier)] = array($identifier, $license[0], $license[1], $license[2]);
84677 }
84678 }
84679
84680 private function loadExceptions()
84681 {
84682 if (null !== $this->exceptions) {
84683 return;
84684 }
84685
84686 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
84687 $this->exceptions = array();
84688
84689 foreach (json_decode($json, true) as $identifier => $exception) {
84690 $this->exceptions[strtolower($identifier)] = array($identifier, $exception[0]);
84691 }
84692 }
84693
84694
84695
84696
84697 private function getLicensesExpression()
84698 {
84699 if (null === $this->licensesExpression) {
84700 $licenses = array_map('preg_quote', array_keys($this->licenses));
84701 rsort($licenses);
84702 $licenses = implode('|', $licenses);
84703 $this->licensesExpression = $licenses;
84704 }
84705
84706 return $this->licensesExpression;
84707 }
84708
84709
84710
84711
84712 private function getExceptionsExpression()
84713 {
84714 if (null === $this->exceptionsExpression) {
84715 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
84716 rsort($exceptions);
84717 $exceptions = implode('|', $exceptions);
84718 $this->exceptionsExpression = $exceptions;
84719 }
84720
84721 return $this->exceptionsExpression;
84722 }
84723
84724
84725
84726
84727
84728
84729
84730
84731 private function isValidLicenseString($license)
84732 {
84733 if (isset($this->licenses[strtolower($license)])) {
84734 return true;
84735 }
84736
84737 $licenses = $this->getLicensesExpression();
84738 $exceptions = $this->getExceptionsExpression();
84739
84740 $regex = <<<REGEX
84741 {
84742 (?(DEFINE)
84743     # idstring: 1*( ALPHA / DIGIT / - / . )
84744     (?<idstring>[\pL\pN.-]{1,})
84745
84746     # license-id: taken from list
84747     (?<licenseid>${licenses})
84748
84749     # license-exception-id: taken from list
84750     (?<licenseexceptionid>${exceptions})
84751
84752     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
84753     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
84754
84755     # simple-expresssion: license-id / license-id+ / license-ref
84756     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
84757
84758     # compound-expression: 1*(
84759     #   simple-expression /
84760     #   simple-expression WITH license-exception-id /
84761     #   compound-expression AND compound-expression /
84762     #   compound-expression OR compound-expression
84763     # ) / ( compound-expression ) )
84764     (?<compound_head>
84765         (?&simple_expression) ( \s+ WITH \s+ (?&licenseexceptionid))?
84766             | \( \s* (?&compound_expression) \s* \)
84767     )
84768     (?<compound_expression>
84769         (?&compound_head) (?: \s+ (?:AND|OR) \s+ (?&compound_expression))?
84770     )
84771
84772     # license-expression: 1*1(simple-expression / compound-expression)
84773     (?<license_expression>(?&compound_expression) | (?&simple_expression))
84774 ) # end of define
84775
84776 ^(NONE | NOASSERTION | (?&license_expression))$
84777 }xi
84778 REGEX;
84779
84780 $match = preg_match($regex, $license);
84781
84782 if (0 === $match) {
84783 return false;
84784 }
84785
84786 if (false === $match) {
84787 throw new \RuntimeException('Regex failed to compile/run.');
84788 }
84789
84790 return true;
84791 }
84792 }
84793 Copyright (C) 2015 Composer
84794
84795 Permission is hereby granted, free of charge, to any person obtaining a copy of
84796 this software and associated documentation files (the "Software"), to deal in
84797 the Software without restriction, including without limitation the rights to
84798 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
84799 of the Software, and to permit persons to whom the Software is furnished to do
84800 so, subject to the following conditions:
84801
84802 The above copyright notice and this permission notice shall be included in all
84803 copies or substantial portions of the Software.
84804
84805 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84806 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
84807 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
84808 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84809 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84810 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
84811 SOFTWARE.
84812 <?php
84813
84814
84815
84816
84817
84818
84819
84820
84821
84822
84823 namespace Composer\Semver;
84824
84825 use Composer\Semver\Constraint\Constraint;
84826
84827 class Comparator
84828 {
84829
84830
84831
84832
84833
84834
84835
84836
84837 public static function greaterThan($version1, $version2)
84838 {
84839 return self::compare($version1, '>', $version2);
84840 }
84841
84842
84843
84844
84845
84846
84847
84848
84849
84850 public static function greaterThanOrEqualTo($version1, $version2)
84851 {
84852 return self::compare($version1, '>=', $version2);
84853 }
84854
84855
84856
84857
84858
84859
84860
84861
84862
84863 public static function lessThan($version1, $version2)
84864 {
84865 return self::compare($version1, '<', $version2);
84866 }
84867
84868
84869
84870
84871
84872
84873
84874
84875
84876 public static function lessThanOrEqualTo($version1, $version2)
84877 {
84878 return self::compare($version1, '<=', $version2);
84879 }
84880
84881
84882
84883
84884
84885
84886
84887
84888
84889 public static function equalTo($version1, $version2)
84890 {
84891 return self::compare($version1, '==', $version2);
84892 }
84893
84894
84895
84896
84897
84898
84899
84900
84901
84902 public static function notEqualTo($version1, $version2)
84903 {
84904 return self::compare($version1, '!=', $version2);
84905 }
84906
84907
84908
84909
84910
84911
84912
84913
84914
84915
84916 public static function compare($version1, $operator, $version2)
84917 {
84918 $constraint = new Constraint($operator, $version2);
84919
84920 return $constraint->matches(new Constraint('==', $version1));
84921 }
84922 }
84923 <?php
84924
84925
84926
84927
84928
84929
84930
84931
84932
84933
84934 namespace Composer\Semver\Constraint;
84935
84936 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);
84937
84938
84939
84940
84941 abstract class AbstractConstraint implements ConstraintInterface
84942 {
84943
84944 protected $prettyString;
84945
84946
84947
84948
84949
84950
84951 public function matches(ConstraintInterface $provider)
84952 {
84953 if ($provider instanceof $this) {
84954
84955  return $this->matchSpecific($provider);
84956 }
84957
84958
84959  return $provider->matches($this);
84960 }
84961
84962
84963
84964
84965 public function setPrettyString($prettyString)
84966 {
84967 $this->prettyString = $prettyString;
84968 }
84969
84970
84971
84972
84973 public function getPrettyString()
84974 {
84975 if ($this->prettyString) {
84976 return $this->prettyString;
84977 }
84978
84979 return $this->__toString();
84980 }
84981
84982
84983  
84984  
84985 }
84986 <?php
84987
84988
84989
84990
84991
84992
84993
84994
84995
84996
84997 namespace Composer\Semver\Constraint;
84998
84999
85000
85001
85002 class Constraint implements ConstraintInterface
85003 {
85004
85005 const OP_EQ = 0;
85006 const OP_LT = 1;
85007 const OP_LE = 2;
85008 const OP_GT = 3;
85009 const OP_GE = 4;
85010 const OP_NE = 5;
85011
85012
85013
85014
85015
85016
85017 private static $transOpStr = array(
85018 '=' => self::OP_EQ,
85019 '==' => self::OP_EQ,
85020 '<' => self::OP_LT,
85021 '<=' => self::OP_LE,
85022 '>' => self::OP_GT,
85023 '>=' => self::OP_GE,
85024 '<>' => self::OP_NE,
85025 '!=' => self::OP_NE,
85026 );
85027
85028
85029
85030
85031
85032
85033 private static $transOpInt = array(
85034 self::OP_EQ => '==',
85035 self::OP_LT => '<',
85036 self::OP_LE => '<=',
85037 self::OP_GT => '>',
85038 self::OP_GE => '>=',
85039 self::OP_NE => '!=',
85040 );
85041
85042
85043 protected $operator;
85044
85045
85046 protected $version;
85047
85048
85049 protected $prettyString;
85050
85051
85052
85053
85054
85055
85056 public function matches(ConstraintInterface $provider)
85057 {
85058 if ($provider instanceof $this) {
85059 return $this->matchSpecific($provider);
85060 }
85061
85062
85063  return $provider->matches($this);
85064 }
85065
85066
85067
85068
85069 public function setPrettyString($prettyString)
85070 {
85071 $this->prettyString = $prettyString;
85072 }
85073
85074
85075
85076
85077 public function getPrettyString()
85078 {
85079 if ($this->prettyString) {
85080 return $this->prettyString;
85081 }
85082
85083 return $this->__toString();
85084 }
85085
85086
85087
85088
85089
85090
85091 public static function getSupportedOperators()
85092 {
85093 return array_keys(self::$transOpStr);
85094 }
85095
85096
85097
85098
85099
85100
85101
85102
85103
85104 public function __construct($operator, $version)
85105 {
85106 if (!isset(self::$transOpStr[$operator])) {
85107 throw new \InvalidArgumentException(sprintf(
85108 'Invalid operator "%s" given, expected one of: %s',
85109 $operator,
85110 implode(', ', self::getSupportedOperators())
85111 ));
85112 }
85113
85114 $this->operator = self::$transOpStr[$operator];
85115 $this->version = $version;
85116 }
85117
85118
85119
85120
85121
85122
85123
85124
85125
85126
85127
85128 public function versionCompare($a, $b, $operator, $compareBranches = false)
85129 {
85130 if (!isset(self::$transOpStr[$operator])) {
85131 throw new \InvalidArgumentException(sprintf(
85132 'Invalid operator "%s" given, expected one of: %s',
85133 $operator,
85134 implode(', ', self::getSupportedOperators())
85135 ));
85136 }
85137
85138 $aIsBranch = 'dev-' === substr($a, 0, 4);
85139 $bIsBranch = 'dev-' === substr($b, 0, 4);
85140
85141 if ($aIsBranch && $bIsBranch) {
85142 return $operator === '==' && $a === $b;
85143 }
85144
85145
85146  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
85147 return false;
85148 }
85149
85150 return version_compare($a, $b, $operator);
85151 }
85152
85153
85154
85155
85156
85157
85158
85159 public function matchSpecific(Constraint $provider, $compareBranches = false)
85160 {
85161 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
85162 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
85163
85164 $isEqualOp = self::OP_EQ === $this->operator;
85165 $isNonEqualOp = self::OP_NE === $this->operator;
85166 $isProviderEqualOp = self::OP_EQ === $provider->operator;
85167 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
85168
85169
85170  
85171  if ($isNonEqualOp || $isProviderNonEqualOp) {
85172 return (!$isEqualOp && !$isProviderEqualOp)
85173 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
85174 }
85175
85176
85177  
85178  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
85179 return true;
85180 }
85181
85182 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
85183
85184  
85185  return !($provider->version === $this->version
85186 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
85187 && self::$transOpInt[$this->operator] !== $noEqualOp);
85188 }
85189
85190 return false;
85191 }
85192
85193
85194
85195
85196 public function __toString()
85197 {
85198 return self::$transOpInt[$this->operator] . ' ' . $this->version;
85199 }
85200 }
85201 <?php
85202
85203
85204
85205
85206
85207
85208
85209
85210
85211
85212 namespace Composer\Semver\Constraint;
85213
85214 interface ConstraintInterface
85215 {
85216
85217
85218
85219
85220
85221 public function matches(ConstraintInterface $provider);
85222
85223
85224
85225
85226 public function getPrettyString();
85227
85228
85229
85230
85231 public function __toString();
85232 }
85233 <?php
85234
85235
85236
85237
85238
85239
85240
85241
85242
85243
85244 namespace Composer\Semver\Constraint;
85245
85246
85247
85248
85249 class EmptyConstraint implements ConstraintInterface
85250 {
85251
85252 protected $prettyString;
85253
85254
85255
85256
85257
85258
85259 public function matches(ConstraintInterface $provider)
85260 {
85261 return true;
85262 }
85263
85264
85265
85266
85267 public function setPrettyString($prettyString)
85268 {
85269 $this->prettyString = $prettyString;
85270 }
85271
85272
85273
85274
85275 public function getPrettyString()
85276 {
85277 if ($this->prettyString) {
85278 return $this->prettyString;
85279 }
85280
85281 return (string) $this;
85282 }
85283
85284
85285
85286
85287 public function __toString()
85288 {
85289 return '[]';
85290 }
85291 }
85292 <?php
85293
85294
85295
85296
85297
85298
85299
85300
85301
85302
85303 namespace Composer\Semver\Constraint;
85304
85305
85306
85307
85308 class MultiConstraint implements ConstraintInterface
85309 {
85310
85311 protected $constraints;
85312
85313
85314 protected $prettyString;
85315
85316
85317 protected $conjunctive;
85318
85319
85320
85321
85322
85323 public function __construct(array $constraints, $conjunctive = true)
85324 {
85325 $this->constraints = $constraints;
85326 $this->conjunctive = $conjunctive;
85327 }
85328
85329
85330
85331
85332 public function getConstraints()
85333 {
85334 return $this->constraints;
85335 }
85336
85337
85338
85339
85340 public function isConjunctive()
85341 {
85342 return $this->conjunctive;
85343 }
85344
85345
85346
85347
85348 public function isDisjunctive()
85349 {
85350 return !$this->conjunctive;
85351 }
85352
85353
85354
85355
85356
85357
85358 public function matches(ConstraintInterface $provider)
85359 {
85360 if (false === $this->conjunctive) {
85361 foreach ($this->constraints as $constraint) {
85362 if ($constraint->matches($provider)) {
85363 return true;
85364 }
85365 }
85366
85367 return false;
85368 }
85369
85370 foreach ($this->constraints as $constraint) {
85371 if (!$constraint->matches($provider)) {
85372 return false;
85373 }
85374 }
85375
85376 return true;
85377 }
85378
85379
85380
85381
85382 public function setPrettyString($prettyString)
85383 {
85384 $this->prettyString = $prettyString;
85385 }
85386
85387
85388
85389
85390 public function getPrettyString()
85391 {
85392 if ($this->prettyString) {
85393 return $this->prettyString;
85394 }
85395
85396 return (string) $this;
85397 }
85398
85399
85400
85401
85402 public function __toString()
85403 {
85404 $constraints = array();
85405 foreach ($this->constraints as $constraint) {
85406 $constraints[] = (string) $constraint;
85407 }
85408
85409 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
85410 }
85411 }
85412 <?php
85413
85414
85415
85416
85417
85418
85419
85420
85421
85422
85423 namespace Composer\Semver;
85424
85425 use Composer\Semver\Constraint\Constraint;
85426
85427 class Semver
85428 {
85429 const SORT_ASC = 1;
85430 const SORT_DESC = -1;
85431
85432
85433 private static $versionParser;
85434
85435
85436
85437
85438
85439
85440
85441
85442
85443 public static function satisfies($version, $constraints)
85444 {
85445 if (null === self::$versionParser) {
85446 self::$versionParser = new VersionParser();
85447 }
85448
85449 $versionParser = self::$versionParser;
85450 $provider = new Constraint('==', $versionParser->normalize($version));
85451 $parsedConstraints = $versionParser->parseConstraints($constraints);
85452
85453 return $parsedConstraints->matches($provider);
85454 }
85455
85456
85457
85458
85459
85460
85461
85462
85463
85464 public static function satisfiedBy(array $versions, $constraints)
85465 {
85466 $versions = array_filter($versions, function ($version) use ($constraints) {
85467 return Semver::satisfies($version, $constraints);
85468 });
85469
85470 return array_values($versions);
85471 }
85472
85473
85474
85475
85476
85477
85478
85479
85480 public static function sort(array $versions)
85481 {
85482 return self::usort($versions, self::SORT_ASC);
85483 }
85484
85485
85486
85487
85488
85489
85490
85491
85492 public static function rsort(array $versions)
85493 {
85494 return self::usort($versions, self::SORT_DESC);
85495 }
85496
85497
85498
85499
85500
85501
85502
85503 private static function usort(array $versions, $direction)
85504 {
85505 if (null === self::$versionParser) {
85506 self::$versionParser = new VersionParser();
85507 }
85508
85509 $versionParser = self::$versionParser;
85510 $normalized = array();
85511
85512
85513  
85514  foreach ($versions as $key => $version) {
85515 $normalized[] = array($versionParser->normalize($version), $key);
85516 }
85517
85518 usort($normalized, function (array $left, array $right) use ($direction) {
85519 if ($left[0] === $right[0]) {
85520 return 0;
85521 }
85522
85523 if (Comparator::lessThan($left[0], $right[0])) {
85524 return -$direction;
85525 }
85526
85527 return $direction;
85528 });
85529
85530
85531  $sorted = array();
85532 foreach ($normalized as $item) {
85533 $sorted[] = $versions[$item[1]];
85534 }
85535
85536 return $sorted;
85537 }
85538 }
85539 <?php
85540
85541
85542
85543
85544
85545
85546
85547
85548
85549
85550 namespace Composer\Semver;
85551
85552 use Composer\Semver\Constraint\ConstraintInterface;
85553 use Composer\Semver\Constraint\EmptyConstraint;
85554 use Composer\Semver\Constraint\MultiConstraint;
85555 use Composer\Semver\Constraint\Constraint;
85556
85557
85558
85559
85560
85561
85562 class VersionParser
85563 {
85564
85565
85566
85567
85568
85569
85570
85571
85572
85573
85574
85575
85576
85577 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
85578
85579
85580 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
85581
85582
85583
85584
85585
85586
85587
85588
85589 public static function parseStability($version)
85590 {
85591 $version = preg_replace('{#.+$}i', '', $version);
85592
85593 if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) {
85594 return 'dev';
85595 }
85596
85597 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
85598
85599 if (!empty($match[3])) {
85600 return 'dev';
85601 }
85602
85603 if (!empty($match[1])) {
85604 if ('beta' === $match[1] || 'b' === $match[1]) {
85605 return 'beta';
85606 }
85607 if ('alpha' === $match[1] || 'a' === $match[1]) {
85608 return 'alpha';
85609 }
85610 if ('rc' === $match[1]) {
85611 return 'RC';
85612 }
85613 }
85614
85615 return 'stable';
85616 }
85617
85618
85619
85620
85621
85622
85623 public static function normalizeStability($stability)
85624 {
85625 $stability = strtolower($stability);
85626
85627 return $stability === 'rc' ? 'RC' : $stability;
85628 }
85629
85630
85631
85632
85633
85634
85635
85636
85637
85638
85639
85640 public function normalize($version, $fullVersion = null)
85641 {
85642 $version = trim($version);
85643 if (null === $fullVersion) {
85644 $fullVersion = $version;
85645 }
85646
85647
85648  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
85649
85650  $this->normalize($match[2]);
85651
85652 $version = $match[1];
85653 }
85654
85655
85656  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
85657 return '9999999-dev';
85658 }
85659
85660
85661  if (stripos($version, 'dev-') === 0) {
85662 return 'dev-' . substr($version, 4);
85663 }
85664
85665
85666  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
85667 $version = $match[1];
85668 }
85669
85670
85671  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
85672 $version = $matches[1]
85673 . (!empty($matches[2]) ? $matches[2] : '.0')
85674 . (!empty($matches[3]) ? $matches[3] : '.0')
85675 . (!empty($matches[4]) ? $matches[4] : '.0');
85676 $index = 5;
85677
85678  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
85679 $version = preg_replace('{\D}', '.', $matches[1]);
85680 $index = 2;
85681 }
85682
85683
85684  if (isset($index)) {
85685 if (!empty($matches[$index])) {
85686 if ('stable' === $matches[$index]) {
85687 return $version;
85688 }
85689 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
85690 }
85691
85692 if (!empty($matches[$index + 2])) {
85693 $version .= '-dev';
85694 }
85695
85696 return $version;
85697 }
85698
85699
85700  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
85701 try {
85702 return $this->normalizeBranch($match[1]);
85703 } catch (\Exception $e) {
85704 }
85705 }
85706
85707 $extraMessage = '';
85708 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
85709 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
85710 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
85711 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
85712 }
85713
85714 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
85715 }
85716
85717
85718
85719
85720
85721
85722
85723
85724 public function parseNumericAliasPrefix($branch)
85725 {
85726 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
85727 return $matches['version'] . '.';
85728 }
85729
85730 return false;
85731 }
85732
85733
85734
85735
85736
85737
85738
85739
85740 public function normalizeBranch($name)
85741 {
85742 $name = trim($name);
85743
85744 if (in_array($name, array('master', 'trunk', 'default'))) {
85745 return $this->normalize($name);
85746 }
85747
85748 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
85749 $version = '';
85750 for ($i = 1; $i < 5; ++$i) {
85751 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
85752 }
85753
85754 return str_replace('x', '9999999', $version) . '-dev';
85755 }
85756
85757 return 'dev-' . $name;
85758 }
85759
85760
85761
85762
85763
85764
85765
85766
85767 public function parseConstraints($constraints)
85768 {
85769 $prettyConstraint = $constraints;
85770
85771 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
85772 $constraints = empty($match[1]) ? '*' : $match[1];
85773 }
85774
85775 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
85776 $constraints = $match[1];
85777 }
85778
85779 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
85780 $orGroups = array();
85781
85782 foreach ($orConstraints as $constraints) {
85783 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
85784 if (count($andConstraints) > 1) {
85785 $constraintObjects = array();
85786 foreach ($andConstraints as $constraint) {
85787 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
85788 $constraintObjects[] = $parsedConstraint;
85789 }
85790 }
85791 } else {
85792 $constraintObjects = $this->parseConstraint($andConstraints[0]);
85793 }
85794
85795 if (1 === count($constraintObjects)) {
85796 $constraint = $constraintObjects[0];
85797 } else {
85798 $constraint = new MultiConstraint($constraintObjects);
85799 }
85800
85801 $orGroups[] = $constraint;
85802 }
85803
85804 if (1 === count($orGroups)) {
85805 $constraint = $orGroups[0];
85806 } elseif (2 === count($orGroups)
85807
85808  
85809  && $orGroups[0] instanceof MultiConstraint
85810 && $orGroups[1] instanceof MultiConstraint
85811 && 2 === count($orGroups[0]->getConstraints())
85812 && 2 === count($orGroups[1]->getConstraints())
85813 && ($a = (string) $orGroups[0])
85814 && strpos($a, '[>=') === 0 && (false !== ($posA = strpos($a, '<', 4)))
85815 && ($b = (string) $orGroups[1])
85816 && strpos($b, '[>=') === 0 && (false !== ($posB = strpos($b, '<', 4)))
85817 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
85818 ) {
85819 $constraint = new MultiConstraint(array(
85820 new Constraint('>=', substr($a, 4, $posA - 5)),
85821 new Constraint('<', substr($b, $posB + 2, -1)),
85822 ));
85823 } else {
85824 $constraint = new MultiConstraint($orGroups, false);
85825 }
85826
85827 $constraint->setPrettyString($prettyConstraint);
85828
85829 return $constraint;
85830 }
85831
85832
85833
85834
85835
85836
85837
85838
85839 private function parseConstraint($constraint)
85840 {
85841 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
85842 $constraint = $match[1];
85843 if ($match[2] !== 'stable') {
85844 $stabilityModifier = $match[2];
85845 }
85846 }
85847
85848 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
85849 return array(new EmptyConstraint());
85850 }
85851
85852 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
85853
85854
85855  
85856  
85857  
85858  
85859  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
85860 if (strpos($constraint, '~>') === 0) {
85861 throw new \UnexpectedValueException(
85862 'Could not parse version constraint ' . $constraint . ': ' .
85863 'Invalid operator "~>", you probably meant to use the "~" operator'
85864 );
85865 }
85866
85867
85868  if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
85869 $position = 4;
85870 } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
85871 $position = 3;
85872 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
85873 $position = 2;
85874 } else {
85875 $position = 1;
85876 }
85877
85878
85879  $stabilitySuffix = '';
85880 if (empty($matches[5]) && empty($matches[7])) {
85881 $stabilitySuffix .= '-dev';
85882 }
85883
85884 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
85885 $lowerBound = new Constraint('>=', $lowVersion);
85886
85887
85888  
85889  $highPosition = max(1, $position - 1);
85890 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
85891 $upperBound = new Constraint('<', $highVersion);
85892
85893 return array(
85894 $lowerBound,
85895 $upperBound,
85896 );
85897 }
85898
85899
85900  
85901  
85902  
85903  
85904  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
85905
85906  if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
85907 $position = 1;
85908 } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
85909 $position = 2;
85910 } else {
85911 $position = 3;
85912 }
85913
85914
85915  $stabilitySuffix = '';
85916 if (empty($matches[5]) && empty($matches[7])) {
85917 $stabilitySuffix .= '-dev';
85918 }
85919
85920 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
85921 $lowerBound = new Constraint('>=', $lowVersion);
85922
85923
85924  
85925  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
85926 $upperBound = new Constraint('<', $highVersion);
85927
85928 return array(
85929 $lowerBound,
85930 $upperBound,
85931 );
85932 }
85933
85934
85935  
85936  
85937  
85938  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
85939 if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
85940 $position = 3;
85941 } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
85942 $position = 2;
85943 } else {
85944 $position = 1;
85945 }
85946
85947 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
85948 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
85949
85950 if ($lowVersion === '0.0.0.0-dev') {
85951 return array(new Constraint('<', $highVersion));
85952 }
85953
85954 return array(
85955 new Constraint('>=', $lowVersion),
85956 new Constraint('<', $highVersion),
85957 );
85958 }
85959
85960
85961  
85962  
85963  
85964  
85965  
85966  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
85967
85968  $lowStabilitySuffix = '';
85969 if (empty($matches[6]) && empty($matches[8])) {
85970 $lowStabilitySuffix = '-dev';
85971 }
85972
85973 $lowVersion = $this->normalize($matches['from']);
85974 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
85975
85976 $empty = function ($x) {
85977 return ($x === 0 || $x === '0') ? false : empty($x);
85978 };
85979
85980 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
85981 $highVersion = $this->normalize($matches['to']);
85982 $upperBound = new Constraint('<=', $highVersion);
85983 } else {
85984 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
85985 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
85986 $upperBound = new Constraint('<', $highVersion);
85987 }
85988
85989 return array(
85990 $lowerBound,
85991 $upperBound,
85992 );
85993 }
85994
85995
85996  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
85997 try {
85998 $version = $this->normalize($matches[2]);
85999
86000 if (!empty($stabilityModifier) && self::parseStability($version) === 'stable') {
86001 $version .= '-' . $stabilityModifier;
86002 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
86003 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
86004 if (strpos($matches[2], 'dev-') !== 0) {
86005 $version .= '-dev';
86006 }
86007 }
86008 }
86009
86010 return array(new Constraint($matches[1] ?: '=', $version));
86011 } catch (\Exception $e) {
86012 }
86013 }
86014
86015 $message = 'Could not parse version constraint ' . $constraint;
86016 if (isset($e)) {
86017 $message .= ': ' . $e->getMessage();
86018 }
86019
86020 throw new \UnexpectedValueException($message);
86021 }
86022
86023
86024
86025
86026
86027
86028
86029
86030
86031
86032
86033
86034
86035 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
86036 {
86037 for ($i = 4; $i > 0; --$i) {
86038 if ($i > $position) {
86039 $matches[$i] = $pad;
86040 } elseif ($i === $position && $increment) {
86041 $matches[$i] += $increment;
86042
86043  if ($matches[$i] < 0) {
86044 $matches[$i] = $pad;
86045 --$position;
86046
86047
86048  if ($i === 1) {
86049 return null;
86050 }
86051 }
86052 }
86053 }
86054
86055 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
86056 }
86057
86058
86059
86060
86061
86062
86063
86064
86065 private function expandStability($stability)
86066 {
86067 $stability = strtolower($stability);
86068
86069 switch ($stability) {
86070 case 'a':
86071 return 'alpha';
86072 case 'b':
86073 return 'beta';
86074 case 'p':
86075 case 'pl':
86076 return 'patch';
86077 case 'rc':
86078 return 'RC';
86079 default:
86080 return $stability;
86081 }
86082 }
86083 }
86084 Copyright (C) 2016 Composer
86085
86086 Permission is hereby granted, free of charge, to any person obtaining a copy of
86087 this software and associated documentation files (the "Software"), to deal in
86088 the Software without restriction, including without limitation the rights to
86089 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
86090 of the Software, and to permit persons to whom the Software is furnished to do
86091 so, subject to the following conditions:
86092
86093 The above copyright notice and this permission notice shall be included in all
86094 copies or substantial portions of the Software.
86095
86096 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86097 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86098 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86099 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86100 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
86101 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
86102 SOFTWARE.
86103 <?php
86104
86105
86106
86107
86108
86109
86110
86111
86112
86113
86114 namespace Composer\CaBundle;
86115
86116 use Psr\Log\LoggerInterface;
86117 use Symfony\Component\Process\PhpProcess;
86118
86119
86120
86121
86122
86123 class CaBundle
86124 {
86125 private static $caPath;
86126 private static $caFileValidity = array();
86127 private static $useOpensslParse;
86128
86129
86130
86131
86132
86133
86134
86135
86136
86137
86138
86139
86140
86141
86142
86143
86144
86145
86146
86147
86148
86149
86150
86151
86152
86153
86154
86155
86156
86157
86158
86159
86160
86161
86162
86163
86164
86165
86166 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
86167 {
86168 if (self::$caPath !== null) {
86169 return self::$caPath;
86170 }
86171 $caBundlePaths = array();
86172
86173
86174
86175  
86176  $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE');
86177
86178
86179  
86180  $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR');
86181
86182 $caBundlePaths[] = ini_get('openssl.cafile');
86183 $caBundlePaths[] = ini_get('openssl.capath');
86184
86185 $otherLocations = array(
86186 '/etc/pki/tls/certs/ca-bundle.crt', 
86187  '/etc/ssl/certs/ca-certificates.crt', 
86188  '/etc/ssl/ca-bundle.pem', 
86189  '/usr/local/share/certs/ca-root-nss.crt', 
86190  '/usr/ssl/certs/ca-bundle.crt', 
86191  '/opt/local/share/curl/curl-ca-bundle.crt', 
86192  '/usr/local/share/curl/curl-ca-bundle.crt', 
86193  '/usr/share/ssl/certs/ca-bundle.crt', 
86194  '/etc/ssl/cert.pem', 
86195  '/usr/local/etc/ssl/cert.pem', 
86196  '/usr/local/etc/openssl/cert.pem', 
86197  '/usr/local/etc/openssl@1.1/cert.pem', 
86198  );
86199
86200 foreach($otherLocations as $location) {
86201 $otherLocations[] = dirname($location);
86202 }
86203
86204 $caBundlePaths = array_merge($caBundlePaths, $otherLocations);
86205
86206 foreach ($caBundlePaths as $caBundle) {
86207 if (self::caFileUsable($caBundle, $logger)) {
86208 return self::$caPath = $caBundle;
86209 }
86210
86211 if (self::caDirUsable($caBundle)) {
86212 return self::$caPath = $caBundle;
86213 }
86214 }
86215
86216 return self::$caPath = static::getBundledCaBundlePath(); 
86217  }
86218
86219
86220
86221
86222
86223
86224
86225
86226 public static function getBundledCaBundlePath()
86227 {
86228 $caBundleFile = __DIR__.'/../res/cacert.pem';
86229
86230
86231  
86232  if (0 === strpos($caBundleFile, 'phar://')) {
86233 file_put_contents(
86234 $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'),
86235 file_get_contents($caBundleFile)
86236 );
86237
86238 register_shutdown_function(function() use ($tempCaBundleFile) {
86239 @unlink($tempCaBundleFile);
86240 });
86241
86242 $caBundleFile = $tempCaBundleFile;
86243 }
86244
86245 return $caBundleFile;
86246 }
86247
86248
86249
86250
86251
86252
86253
86254
86255
86256 public static function validateCaFile($filename, LoggerInterface $logger = null)
86257 {
86258 static $warned = false;
86259
86260 if (isset(self::$caFileValidity[$filename])) {
86261 return self::$caFileValidity[$filename];
86262 }
86263
86264 $contents = file_get_contents($filename);
86265
86266
86267  
86268  if (!static::isOpensslParseSafe()) {
86269 if (!$warned && $logger) {
86270 $logger->warning(sprintf(
86271 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
86272 PHP_VERSION
86273 ));
86274 $warned = true;
86275 }
86276
86277 $isValid = !empty($contents);
86278 } else {
86279 $contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents);
86280 $isValid = (bool) openssl_x509_parse($contents);
86281 }
86282
86283 if ($logger) {
86284 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
86285 }
86286
86287 return self::$caFileValidity[$filename] = $isValid;
86288 }
86289
86290
86291
86292
86293
86294
86295
86296
86297
86298 public static function isOpensslParseSafe()
86299 {
86300 if (null !== self::$useOpensslParse) {
86301 return self::$useOpensslParse;
86302 }
86303
86304 if (PHP_VERSION_ID >= 50600) {
86305 return self::$useOpensslParse = true;
86306 }
86307
86308
86309  
86310  
86311  
86312  if (
86313 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
86314 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
86315 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
86316 ) {
86317
86318  return self::$useOpensslParse = true;
86319 }
86320
86321 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
86322
86323  return self::$useOpensslParse = false;
86324 }
86325
86326 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
86327 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
86328
86329 if (preg_match($regex, PHP_VERSION, $m)) {
86330 return ((int) $m[1]) >= $fixedVersion;
86331 }
86332
86333 return false;
86334 };
86335
86336
86337  if (
86338 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
86339  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
86340  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
86341  ) {
86342 return self::$useOpensslParse = true;
86343 }
86344
86345
86346  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
86347 return self::$useOpensslParse = false;
86348 }
86349
86350
86351  
86352  
86353  
86354  
86355  
86356
86357
86358  
86359  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
86360 $script = <<<'EOT'
86361
86362 error_reporting(-1);
86363 $info = openssl_x509_parse(base64_decode('%s'));
86364 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
86365
86366 EOT;
86367 $script = '<'."?php\n".sprintf($script, $cert);
86368
86369 try {
86370 $process = new PhpProcess($script);
86371 $process->mustRun();
86372 } catch (\Exception $e) {
86373
86374  
86375  return self::$useOpensslParse = false;
86376 }
86377
86378 $output = preg_split('{\r?\n}', trim($process->getOutput()));
86379 $errorOutput = trim($process->getErrorOutput());
86380
86381 if (
86382 count($output) === 3
86383 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
86384 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
86385 && $output[2] === 'int(-1)'
86386 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
86387 ) {
86388
86389  return self::$useOpensslParse = true;
86390 }
86391
86392 return self::$useOpensslParse = false;
86393 }
86394
86395
86396
86397
86398 public static function reset()
86399 {
86400 self::$caFileValidity = array();
86401 self::$caPath = null;
86402 self::$useOpensslParse = null;
86403 }
86404
86405 private static function getEnvVariable($name)
86406 {
86407 if (isset($_SERVER[$name])) {
86408 return (string) $_SERVER[$name];
86409 }
86410
86411 if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) {
86412 return (string) $value;
86413 }
86414
86415 return false;
86416 }
86417
86418 private static function caFileUsable($certFile, LoggerInterface $logger = null)
86419 {
86420 return $certFile && @is_file($certFile) && @is_readable($certFile) && static::validateCaFile($certFile, $logger);
86421 }
86422
86423 private static function caDirUsable($certDir)
86424 {
86425 return $certDir && @is_dir($certDir) && @is_readable($certDir) && glob($certDir . '/*');
86426 }
86427 }
86428 MIT License
86429
86430 Copyright (c) 2017 Composer
86431
86432 Permission is hereby granted, free of charge, to any person obtaining a copy
86433 of this software and associated documentation files (the "Software"), to deal
86434 in the Software without restriction, including without limitation the rights
86435 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
86436 copies of the Software, and to permit persons to whom the Software is
86437 furnished to do so, subject to the following conditions:
86438
86439 The above copyright notice and this permission notice shall be included in all
86440 copies or substantial portions of the Software.
86441
86442 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86443 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86444 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86445 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86446 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
86447 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
86448 SOFTWARE.
86449 <?php
86450
86451
86452
86453
86454
86455
86456
86457
86458
86459
86460 namespace Composer\XdebugHandler;
86461
86462
86463
86464
86465 class PhpConfig
86466 {
86467
86468
86469
86470
86471
86472 public function useOriginal()
86473 {
86474 $this->getDataAndReset();
86475 return array();
86476 }
86477
86478
86479
86480
86481
86482
86483 public function useStandard()
86484 {
86485 if ($data = $this->getDataAndReset()) {
86486 return array('-n', '-c', $data['tmpIni']);
86487 }
86488
86489 return array();
86490 }
86491
86492
86493
86494
86495
86496
86497 public function usePersistent()
86498 {
86499 if ($data = $this->getDataAndReset()) {
86500 Process::setEnv('PHPRC', $data['tmpIni']);
86501 Process::setEnv('PHP_INI_SCAN_DIR', '');
86502 }
86503
86504 return array();
86505 }
86506
86507
86508
86509
86510
86511
86512 private function getDataAndReset()
86513 {
86514 if ($data = XdebugHandler::getRestartSettings()) {
86515 Process::setEnv('PHPRC', $data['phprc']);
86516 Process::setEnv('PHP_INI_SCAN_DIR', $data['scanDir']);
86517 }
86518
86519 return $data;
86520 }
86521 }
86522 <?php
86523
86524
86525
86526
86527
86528
86529
86530
86531
86532
86533 namespace Composer\XdebugHandler;
86534
86535
86536
86537
86538
86539
86540
86541
86542 class Process
86543 {
86544
86545
86546
86547
86548
86549
86550
86551
86552
86553
86554 public static function addColorOption(array $args, $colorOption)
86555 {
86556 if (!$colorOption
86557 || in_array($colorOption, $args)
86558 || !preg_match('/^--([a-z]+$)|(^--[a-z]+=)/', $colorOption, $matches)) {
86559 return $args;
86560 }
86561
86562 if (isset($matches[2])) {
86563
86564  if (false !== ($index = array_search($matches[2].'auto', $args))) {
86565 $args[$index] = $colorOption;
86566 return $args;
86567 } elseif (preg_grep('/^'.$matches[2].'/', $args)) {
86568 return $args;
86569 }
86570 } elseif (in_array('--no-'.$matches[1], $args)) {
86571 return $args;
86572 }
86573
86574
86575  if (false !== getenv('NO_COLOR')) {
86576 return $args;
86577 }
86578
86579 if (false !== ($index = array_search('--', $args))) {
86580
86581  array_splice($args, $index, 0, $colorOption);
86582 } else {
86583 $args[] = $colorOption;
86584 }
86585
86586 return $args;
86587 }
86588
86589
86590
86591
86592
86593
86594
86595
86596
86597
86598
86599
86600
86601 public static function escape($arg, $meta = true, $module = false)
86602 {
86603 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
86604 return "'".str_replace("'", "'\\''", $arg)."'";
86605 }
86606
86607 $quote = strpbrk($arg, " \t") !== false || $arg === '';
86608
86609 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
86610
86611 if ($meta) {
86612 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
86613
86614 if (!$meta) {
86615 $quote = $quote || strpbrk($arg, '^&|<>()') !== false;
86616 } elseif ($module && !$dquotes && $quote) {
86617 $meta = false;
86618 }
86619 }
86620
86621 if ($quote) {
86622 $arg = '"'.preg_replace('/(\\\\*)$/', '$1$1', $arg).'"';
86623 }
86624
86625 if ($meta) {
86626 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
86627 }
86628
86629 return $arg;
86630 }
86631
86632
86633
86634
86635
86636
86637
86638
86639
86640
86641
86642 public static function supportsColor($output)
86643 {
86644 if ('Hyper' === getenv('TERM_PROGRAM')) {
86645 return true;
86646 }
86647
86648 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
86649 return (function_exists('sapi_windows_vt100_support')
86650 && sapi_windows_vt100_support($output))
86651 || false !== getenv('ANSICON')
86652 || 'ON' === getenv('ConEmuANSI')
86653 || 'xterm' === getenv('TERM');
86654 }
86655
86656 if (function_exists('stream_isatty')) {
86657 return stream_isatty($output);
86658 }
86659
86660 if (function_exists('posix_isatty')) {
86661 return posix_isatty($output);
86662 }
86663
86664 $stat = fstat($output);
86665
86666  return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
86667 }
86668
86669
86670
86671
86672
86673
86674
86675
86676
86677 public static function setEnv($name, $value = false)
86678 {
86679 $unset = false === $value;
86680
86681 if (!putenv($unset ? $name : $name.'='.$value)) {
86682 return false;
86683 }
86684
86685 if ($unset) {
86686 unset($_SERVER[$name]);
86687 } else {
86688 $_SERVER[$name] = $value;
86689 }
86690
86691
86692  if (false !== stripos((string) ini_get('variables_order'), 'E')) {
86693 if ($unset) {
86694 unset($_ENV[$name]);
86695 } else {
86696 $_ENV[$name] = $value;
86697 }
86698 }
86699
86700 return true;
86701 }
86702 }
86703 <?php
86704
86705
86706
86707
86708
86709
86710
86711
86712
86713
86714 namespace Composer\XdebugHandler;
86715
86716 use Psr\Log\LoggerInterface;
86717 use Psr\Log\LogLevel;
86718
86719
86720
86721
86722
86723 class Status
86724 {
86725 const ENV_RESTART = 'XDEBUG_HANDLER_RESTART';
86726 const CHECK = 'Check';
86727 const ERROR = 'Error';
86728 const INFO = 'Info';
86729 const NORESTART = 'NoRestart';
86730 const RESTART = 'Restart';
86731 const RESTARTING = 'Restarting';
86732 const RESTARTED = 'Restarted';
86733
86734 private $debug;
86735 private $envAllowXdebug;
86736 private $loaded;
86737 private $logger;
86738 private $time;
86739
86740
86741
86742
86743
86744
86745
86746 public function __construct($envAllowXdebug, $debug)
86747 {
86748 $start = getenv(self::ENV_RESTART);
86749 Process::setEnv(self::ENV_RESTART);
86750 $this->time = $start ? round((microtime(true) - $start) * 1000) : 0;
86751
86752 $this->envAllowXdebug = $envAllowXdebug;
86753 $this->debug = $debug && defined('STDERR');
86754 }
86755
86756
86757
86758
86759 public function setLogger(LoggerInterface $logger)
86760 {
86761 $this->logger = $logger;
86762 }
86763
86764
86765
86766
86767
86768
86769
86770 public function report($op, $data)
86771 {
86772 if ($this->logger || $this->debug) {
86773 call_user_func(array($this, 'report'.$op), $data);
86774 }
86775 }
86776
86777
86778
86779
86780
86781
86782
86783 private function output($text, $level = null)
86784 {
86785 if ($this->logger) {
86786 $this->logger->log($level ?: LogLevel::DEBUG, $text);
86787 }
86788
86789 if ($this->debug) {
86790 fwrite(STDERR, sprintf('xdebug-handler[%d] %s', getmypid(), $text.PHP_EOL));
86791 }
86792 }
86793
86794 private function reportCheck($loaded)
86795 {
86796 $this->loaded = $loaded;
86797 $this->output('Checking '.$this->envAllowXdebug);
86798 }
86799
86800 private function reportError($error)
86801 {
86802 $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
86803 }
86804
86805 private function reportInfo($info)
86806 {
86807 $this->output($info);
86808 }
86809
86810 private function reportNoRestart()
86811 {
86812 $this->output($this->getLoadedMessage());
86813
86814 if ($this->loaded) {
86815 $text = sprintf('No restart (%s)', $this->getEnvAllow());
86816 if (!getenv($this->envAllowXdebug)) {
86817 $text .= ' Allowed by application';
86818 }
86819 $this->output($text);
86820 }
86821 }
86822
86823 private function reportRestart()
86824 {
86825 $this->output($this->getLoadedMessage());
86826 Process::setEnv(self::ENV_RESTART, (string) microtime(true));
86827 }
86828
86829 private function reportRestarted()
86830 {
86831 $loaded = $this->getLoadedMessage();
86832 $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded);
86833 $level = $this->loaded ? LogLevel::WARNING : null;
86834 $this->output($text, $level);
86835 }
86836
86837 private function reportRestarting($command)
86838 {
86839 $text = sprintf('Process restarting (%s)', $this->getEnvAllow());
86840 $this->output($text);
86841 $text = 'Running '.$command;
86842 $this->output($text);
86843 }
86844
86845
86846
86847
86848
86849
86850 private function getEnvAllow()
86851 {
86852 return $this->envAllowXdebug.'='.getenv($this->envAllowXdebug);
86853 }
86854
86855
86856
86857
86858
86859
86860 private function getLoadedMessage()
86861 {
86862 $loaded = $this->loaded ? sprintf('loaded (%s)', $this->loaded) : 'not loaded';
86863 return 'The Xdebug extension is '.$loaded;
86864 }
86865 }
86866 <?php
86867
86868
86869
86870
86871
86872
86873
86874
86875
86876
86877 namespace Composer\XdebugHandler;
86878
86879 use Psr\Log\LoggerInterface;
86880
86881
86882
86883
86884 class XdebugHandler
86885 {
86886 const SUFFIX_ALLOW = '_ALLOW_XDEBUG';
86887 const SUFFIX_INIS = '_ORIGINAL_INIS';
86888 const RESTART_ID = 'internal';
86889 const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS';
86890 const DEBUG = 'XDEBUG_HANDLER_DEBUG';
86891
86892
86893 protected $tmpIni;
86894
86895 private static $inRestart;
86896 private static $name;
86897 private static $skipped;
86898
86899 private $cli;
86900 private $colorOption;
86901 private $debug;
86902 private $envAllowXdebug;
86903 private $envOriginalInis;
86904 private $loaded;
86905 private $persistent;
86906 private $script;
86907
86908 private $statusWriter;
86909
86910
86911
86912
86913
86914
86915
86916
86917
86918
86919
86920
86921 public function __construct($envPrefix, $colorOption = '')
86922 {
86923 if (!is_string($envPrefix) || empty($envPrefix) || !is_string($colorOption)) {
86924 throw new \RuntimeException('Invalid constructor parameter');
86925 }
86926
86927 self::$name = strtoupper($envPrefix);
86928 $this->envAllowXdebug = self::$name.self::SUFFIX_ALLOW;
86929 $this->envOriginalInis = self::$name.self::SUFFIX_INIS;
86930
86931 $this->colorOption = $colorOption;
86932
86933 if (extension_loaded('xdebug')) {
86934 $ext = new \ReflectionExtension('xdebug');
86935 $this->loaded = $ext->getVersion() ?: 'unknown';
86936 }
86937
86938 if ($this->cli = PHP_SAPI === 'cli') {
86939 $this->debug = getenv(self::DEBUG);
86940 }
86941
86942 $this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug);
86943 }
86944
86945
86946
86947
86948
86949
86950
86951
86952 public function setLogger(LoggerInterface $logger)
86953 {
86954 $this->statusWriter->setLogger($logger);
86955 return $this;
86956 }
86957
86958
86959
86960
86961
86962
86963
86964
86965 public function setMainScript($script)
86966 {
86967 $this->script = $script;
86968 return $this;
86969 }
86970
86971
86972
86973
86974
86975
86976 public function setPersistent()
86977 {
86978 $this->persistent = true;
86979 return $this;
86980 }
86981
86982
86983
86984
86985
86986
86987
86988
86989 public function check()
86990 {
86991 $this->notify(Status::CHECK, $this->loaded);
86992 $envArgs = explode('|', (string) getenv($this->envAllowXdebug));
86993
86994 if (empty($envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) {
86995
86996  $this->notify(Status::RESTART);
86997
86998 if ($this->prepareRestart()) {
86999 $command = $this->getCommand();
87000 $this->notify(Status::RESTARTING, $command);
87001 $this->restart($command);
87002 }
87003 return;
87004 }
87005
87006 if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
87007
87008  $this->notify(Status::RESTARTED);
87009
87010 Process::setEnv($this->envAllowXdebug);
87011 self::$inRestart = true;
87012
87013 if (!$this->loaded) {
87014
87015  self::$skipped = $envArgs[1];
87016 }
87017
87018
87019  $this->setEnvRestartSettings($envArgs);
87020 return;
87021 }
87022
87023 $this->notify(Status::NORESTART);
87024
87025 if ($settings = self::getRestartSettings()) {
87026
87027  $this->syncSettings($settings);
87028 }
87029 }
87030
87031
87032
87033
87034
87035
87036
87037
87038
87039 public static function getAllIniFiles()
87040 {
87041 if (!empty(self::$name)) {
87042 $env = getenv(self::$name.self::SUFFIX_INIS);
87043
87044 if (false !== $env) {
87045 return explode(PATH_SEPARATOR, $env);
87046 }
87047 }
87048
87049 $paths = array((string) php_ini_loaded_file());
87050
87051 if ($scanned = php_ini_scanned_files()) {
87052 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
87053 }
87054
87055 return $paths;
87056 }
87057
87058
87059
87060
87061
87062
87063
87064
87065
87066 public static function getRestartSettings()
87067 {
87068 $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS));
87069
87070 if (count($envArgs) !== 6
87071 || (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) {
87072 return;
87073 }
87074
87075 return array(
87076 'tmpIni' => $envArgs[0],
87077 'scannedInis' => (bool) $envArgs[1],
87078 'scanDir' => '*' === $envArgs[2] ? false : $envArgs[2],
87079 'phprc' => '*' === $envArgs[3] ? false : $envArgs[3],
87080 'inis' => explode(PATH_SEPARATOR, $envArgs[4]),
87081 'skipped' => $envArgs[5],
87082 );
87083 }
87084
87085
87086
87087
87088
87089
87090 public static function getSkippedVersion()
87091 {
87092 return (string) self::$skipped;
87093 }
87094
87095
87096
87097
87098
87099
87100
87101
87102 protected function requiresRestart($isLoaded)
87103 {
87104 return $isLoaded;
87105 }
87106
87107
87108
87109
87110
87111
87112 protected function restart($command)
87113 {
87114 $this->doRestart($command);
87115 }
87116
87117
87118
87119
87120
87121
87122 private function doRestart($command)
87123 {
87124 passthru($command, $exitCode);
87125 $this->notify(Status::INFO, 'Restarted process exited '.$exitCode);
87126
87127 if ($this->debug === '2') {
87128 $this->notify(Status::INFO, 'Temp ini saved: '.$this->tmpIni);
87129 } else {
87130 @unlink($this->tmpIni);
87131 }
87132
87133 exit($exitCode);
87134 }
87135
87136
87137
87138
87139
87140
87141
87142
87143
87144
87145
87146 private function prepareRestart()
87147 {
87148 $error = '';
87149 $iniFiles = self::getAllIniFiles();
87150 $scannedInis = count($iniFiles) > 1;
87151 $tmpDir = sys_get_temp_dir();
87152
87153 if (!$this->cli) {
87154 $error = 'Unsupported SAPI: '.PHP_SAPI;
87155 } elseif (!defined('PHP_BINARY')) {
87156 $error = 'PHP version is too old: '.PHP_VERSION;
87157 } elseif (!$this->checkConfiguration($info)) {
87158 $error = $info;
87159 } elseif (!$this->checkScanDirConfig()) {
87160 $error = 'PHP version does not report scanned inis: '.PHP_VERSION;
87161 } elseif (!$this->checkMainScript()) {
87162 $error = 'Unable to access main script: '.$this->script;
87163 } elseif (!$this->writeTmpIni($iniFiles, $tmpDir, $error)) {
87164 $error = $error ?: 'Unable to create temp ini file at: '.$tmpDir;
87165 } elseif (!$this->setEnvironment($scannedInis, $iniFiles)) {
87166 $error = 'Unable to set environment variables';
87167 }
87168
87169 if ($error) {
87170 $this->notify(Status::ERROR, $error);
87171 }
87172
87173 return empty($error);
87174 }
87175
87176
87177
87178
87179
87180
87181
87182
87183
87184
87185 private function writeTmpIni(array $iniFiles, $tmpDir, &$error)
87186 {
87187 if (!$this->tmpIni = @tempnam($tmpDir, '')) {
87188 return false;
87189 }
87190
87191
87192  if (empty($iniFiles[0])) {
87193 array_shift($iniFiles);
87194 }
87195
87196 $content = '';
87197 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
87198
87199 foreach ($iniFiles as $file) {
87200
87201  if (($data = @file_get_contents($file)) === false) {
87202 $error = 'Unable to read ini: '.$file;
87203 return false;
87204 }
87205 $content .= preg_replace($regex, ';$1', $data).PHP_EOL;
87206 }
87207
87208
87209  if ($config = parse_ini_string($content)) {
87210 $loaded = ini_get_all(null, false);
87211 $content .= $this->mergeLoadedConfig($loaded, $config);
87212 }
87213
87214
87215  $content .= 'opcache.enable_cli=0'.PHP_EOL;
87216
87217 return @file_put_contents($this->tmpIni, $content);
87218 }
87219
87220
87221
87222
87223
87224
87225 private function getCommand()
87226 {
87227 $php = array(PHP_BINARY);
87228 $args = array_slice($_SERVER['argv'], 1);
87229
87230 if (!$this->persistent) {
87231
87232  array_push($php, '-n', '-c', $this->tmpIni);
87233 }
87234
87235 if (defined('STDOUT') && Process::supportsColor(STDOUT)) {
87236 $args = Process::addColorOption($args, $this->colorOption);
87237 }
87238
87239 $args = array_merge($php, array($this->script), $args);
87240
87241 $cmd = Process::escape(array_shift($args), true, true);
87242 foreach ($args as $arg) {
87243 $cmd .= ' '.Process::escape($arg);
87244 }
87245
87246 return $cmd;
87247 }
87248
87249
87250
87251
87252
87253
87254
87255
87256
87257
87258
87259 private function setEnvironment($scannedInis, array $iniFiles)
87260 {
87261 $scanDir = getenv('PHP_INI_SCAN_DIR');
87262 $phprc = getenv('PHPRC');
87263
87264
87265  if (!putenv($this->envOriginalInis.'='.implode(PATH_SEPARATOR, $iniFiles))) {
87266 return false;
87267 }
87268
87269 if ($this->persistent) {
87270
87271  if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC='.$this->tmpIni)) {
87272 return false;
87273 }
87274 }
87275
87276
87277  $envArgs = array(
87278 self::RESTART_ID,
87279 $this->loaded,
87280 (int) $scannedInis,
87281 false === $scanDir ? '*' : $scanDir,
87282 false === $phprc ? '*' : $phprc,
87283 );
87284
87285 return putenv($this->envAllowXdebug.'='.implode('|', $envArgs));
87286 }
87287
87288
87289
87290
87291
87292
87293
87294 private function notify($op, $data = null)
87295 {
87296 $this->statusWriter->report($op, $data);
87297 }
87298
87299
87300
87301
87302
87303
87304
87305
87306
87307 private function mergeLoadedConfig(array $loadedConfig, array $iniConfig)
87308 {
87309 $content = '';
87310
87311 foreach ($loadedConfig as $name => $value) {
87312
87313  if (!is_string($value)
87314 || strpos($name, 'xdebug') === 0
87315 || $name === 'apc.mmap_file_mask') {
87316 continue;
87317 }
87318
87319 if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
87320
87321  $content .= $name.'="'.addcslashes($value, '\\"').'"'.PHP_EOL;
87322 }
87323 }
87324
87325 return $content;
87326 }
87327
87328
87329
87330
87331
87332
87333 private function checkMainScript()
87334 {
87335 if (null !== $this->script) {
87336
87337  return file_exists($this->script) || '--' === $this->script;
87338 }
87339
87340 if (file_exists($this->script = $_SERVER['argv'][0])) {
87341 return true;
87342 }
87343
87344
87345  $options = PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false;
87346 $trace = debug_backtrace($options);
87347
87348 if (($main = end($trace)) && isset($main['file'])) {
87349 return file_exists($this->script = $main['file']);
87350 }
87351
87352 return false;
87353 }
87354
87355
87356
87357
87358
87359
87360 private function setEnvRestartSettings($envArgs)
87361 {
87362 $settings = array(
87363 php_ini_loaded_file(),
87364 $envArgs[2],
87365 $envArgs[3],
87366 $envArgs[4],
87367 getenv($this->envOriginalInis),
87368 self::$skipped,
87369 );
87370
87371 Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings));
87372 }
87373
87374
87375
87376
87377
87378
87379 private function syncSettings(array $settings)
87380 {
87381 if (false === getenv($this->envOriginalInis)) {
87382
87383  Process::setEnv($this->envOriginalInis, implode(PATH_SEPARATOR, $settings['inis']));
87384 }
87385
87386 self::$skipped = $settings['skipped'];
87387 $this->notify(Status::INFO, 'Process called with existing restart settings');
87388 }
87389
87390
87391
87392
87393
87394
87395
87396
87397
87398 private function checkScanDirConfig()
87399 {
87400 return !(getenv('PHP_INI_SCAN_DIR')
87401 && !PHP_CONFIG_FILE_SCAN_DIR
87402 && (PHP_VERSION_ID < 70113
87403 || PHP_VERSION_ID === 70200));
87404 }
87405
87406
87407
87408
87409
87410
87411 private function checkConfiguration(&$info)
87412 {
87413 if (false !== strpos(ini_get('disable_functions'), 'passthru')) {
87414 $info = 'passthru function is disabled';
87415 return false;
87416 }
87417
87418 if (extension_loaded('uopz') && !ini_get('uopz.disable')) {
87419
87420  if (function_exists('uopz_allow_exit')) {
87421 @uopz_allow_exit(true);
87422 } else {
87423 $info = 'uopz extension is not compatible';
87424 return false;
87425 }
87426 }
87427
87428 return true;
87429 }
87430 }
87431 Copyright (c) 2012 PHP Framework Interoperability Group
87432
87433 Permission is hereby granted, free of charge, to any person obtaining a copy 
87434 of this software and associated documentation files (the "Software"), to deal
87435 in the Software without restriction, including without limitation the rights 
87436 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
87437 copies of the Software, and to permit persons to whom the Software is 
87438 furnished to do so, subject to the following conditions:
87439
87440 The above copyright notice and this permission notice shall be included in 
87441 all copies or substantial portions of the Software.
87442
87443 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
87444 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87445 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
87446 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87447 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
87448 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
87449 THE SOFTWARE.
87450 <?php
87451
87452 namespace Psr\Log;
87453
87454
87455
87456
87457
87458
87459
87460
87461 abstract class AbstractLogger implements LoggerInterface
87462 {
87463
87464
87465
87466
87467
87468
87469
87470
87471 public function emergency($message, array $context = array())
87472 {
87473 $this->log(LogLevel::EMERGENCY, $message, $context);
87474 }
87475
87476
87477
87478
87479
87480
87481
87482
87483
87484
87485
87486
87487 public function alert($message, array $context = array())
87488 {
87489 $this->log(LogLevel::ALERT, $message, $context);
87490 }
87491
87492
87493
87494
87495
87496
87497
87498
87499
87500
87501
87502 public function critical($message, array $context = array())
87503 {
87504 $this->log(LogLevel::CRITICAL, $message, $context);
87505 }
87506
87507
87508
87509
87510
87511
87512
87513
87514
87515
87516 public function error($message, array $context = array())
87517 {
87518 $this->log(LogLevel::ERROR, $message, $context);
87519 }
87520
87521
87522
87523
87524
87525
87526
87527
87528
87529
87530
87531
87532 public function warning($message, array $context = array())
87533 {
87534 $this->log(LogLevel::WARNING, $message, $context);
87535 }
87536
87537
87538
87539
87540
87541
87542
87543
87544
87545 public function notice($message, array $context = array())
87546 {
87547 $this->log(LogLevel::NOTICE, $message, $context);
87548 }
87549
87550
87551
87552
87553
87554
87555
87556
87557
87558
87559
87560 public function info($message, array $context = array())
87561 {
87562 $this->log(LogLevel::INFO, $message, $context);
87563 }
87564
87565
87566
87567
87568
87569
87570
87571
87572
87573 public function debug($message, array $context = array())
87574 {
87575 $this->log(LogLevel::DEBUG, $message, $context);
87576 }
87577 }
87578 <?php
87579
87580 namespace Psr\Log;
87581
87582 class InvalidArgumentException extends \InvalidArgumentException
87583 {
87584 }
87585 <?php
87586
87587 namespace Psr\Log;
87588
87589
87590
87591
87592 class LogLevel
87593 {
87594 const EMERGENCY = 'emergency';
87595 const ALERT = 'alert';
87596 const CRITICAL = 'critical';
87597 const ERROR = 'error';
87598 const WARNING = 'warning';
87599 const NOTICE = 'notice';
87600 const INFO = 'info';
87601 const DEBUG = 'debug';
87602 }
87603 <?php
87604
87605 namespace Psr\Log;
87606
87607
87608
87609
87610 interface LoggerAwareInterface
87611 {
87612
87613
87614
87615
87616
87617
87618
87619 public function setLogger(LoggerInterface $logger);
87620 }
87621 <?php
87622
87623 namespace Psr\Log;
87624
87625
87626
87627
87628 trait LoggerAwareTrait
87629 {
87630
87631
87632
87633
87634
87635 protected $logger;
87636
87637
87638
87639
87640
87641
87642 public function setLogger(LoggerInterface $logger)
87643 {
87644 $this->logger = $logger;
87645 }
87646 }
87647 <?php
87648
87649 namespace Psr\Log;
87650
87651
87652
87653
87654
87655
87656
87657
87658
87659
87660
87661
87662
87663
87664
87665
87666 interface LoggerInterface
87667 {
87668
87669
87670
87671
87672
87673
87674
87675
87676 public function emergency($message, array $context = array());
87677
87678
87679
87680
87681
87682
87683
87684
87685
87686
87687
87688
87689 public function alert($message, array $context = array());
87690
87691
87692
87693
87694
87695
87696
87697
87698
87699
87700
87701 public function critical($message, array $context = array());
87702
87703
87704
87705
87706
87707
87708
87709
87710
87711
87712 public function error($message, array $context = array());
87713
87714
87715
87716
87717
87718
87719
87720
87721
87722
87723
87724
87725 public function warning($message, array $context = array());
87726
87727
87728
87729
87730
87731
87732
87733
87734
87735 public function notice($message, array $context = array());
87736
87737
87738
87739
87740
87741
87742
87743
87744
87745
87746
87747 public function info($message, array $context = array());
87748
87749
87750
87751
87752
87753
87754
87755
87756
87757 public function debug($message, array $context = array());
87758
87759
87760
87761
87762
87763
87764
87765
87766
87767
87768
87769
87770 public function log($level, $message, array $context = array());
87771 }
87772 <?php
87773
87774 namespace Psr\Log;
87775
87776
87777
87778
87779
87780
87781
87782
87783
87784 trait LoggerTrait
87785 {
87786
87787
87788
87789
87790
87791
87792
87793
87794 public function emergency($message, array $context = array())
87795 {
87796 $this->log(LogLevel::EMERGENCY, $message, $context);
87797 }
87798
87799
87800
87801
87802
87803
87804
87805
87806
87807
87808
87809
87810 public function alert($message, array $context = array())
87811 {
87812 $this->log(LogLevel::ALERT, $message, $context);
87813 }
87814
87815
87816
87817
87818
87819
87820
87821
87822
87823
87824
87825 public function critical($message, array $context = array())
87826 {
87827 $this->log(LogLevel::CRITICAL, $message, $context);
87828 }
87829
87830
87831
87832
87833
87834
87835
87836
87837
87838
87839 public function error($message, array $context = array())
87840 {
87841 $this->log(LogLevel::ERROR, $message, $context);
87842 }
87843
87844
87845
87846
87847
87848
87849
87850
87851
87852
87853
87854
87855 public function warning($message, array $context = array())
87856 {
87857 $this->log(LogLevel::WARNING, $message, $context);
87858 }
87859
87860
87861
87862
87863
87864
87865
87866
87867
87868 public function notice($message, array $context = array())
87869 {
87870 $this->log(LogLevel::NOTICE, $message, $context);
87871 }
87872
87873
87874
87875
87876
87877
87878
87879
87880
87881
87882
87883 public function info($message, array $context = array())
87884 {
87885 $this->log(LogLevel::INFO, $message, $context);
87886 }
87887
87888
87889
87890
87891
87892
87893
87894
87895
87896 public function debug($message, array $context = array())
87897 {
87898 $this->log(LogLevel::DEBUG, $message, $context);
87899 }
87900
87901
87902
87903
87904
87905
87906
87907
87908
87909
87910
87911
87912 abstract public function log($level, $message, array $context = array());
87913 }
87914 <?php
87915
87916 namespace Psr\Log;
87917
87918
87919
87920
87921
87922
87923
87924
87925
87926 class NullLogger extends AbstractLogger
87927 {
87928
87929
87930
87931
87932
87933
87934
87935
87936
87937
87938
87939 public function log($level, $message, array $context = array())
87940 {
87941
87942  }
87943 }
87944 <?php
87945
87946 namespace Psr\Log\Test;
87947
87948
87949
87950
87951
87952
87953
87954
87955 class DummyTest
87956 {
87957 public function __toString()
87958 {
87959 return 'DummyTest';
87960 }
87961 }
87962 <?php
87963
87964 namespace Psr\Log\Test;
87965
87966 use Psr\Log\LoggerInterface;
87967 use Psr\Log\LogLevel;
87968 use PHPUnit\Framework\TestCase;
87969
87970
87971
87972
87973
87974
87975
87976 abstract class LoggerInterfaceTest extends TestCase
87977 {
87978
87979
87980
87981 abstract public function getLogger();
87982
87983
87984
87985
87986
87987
87988
87989
87990
87991
87992 abstract public function getLogs();
87993
87994 public function testImplements()
87995 {
87996 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
87997 }
87998
87999
88000
88001
88002 public function testLogsAtAllLevels($level, $message)
88003 {
88004 $logger = $this->getLogger();
88005 $logger->{$level}($message, array('user' => 'Bob'));
88006 $logger->log($level, $message, array('user' => 'Bob'));
88007
88008 $expected = array(
88009 $level.' message of level '.$level.' with context: Bob',
88010 $level.' message of level '.$level.' with context: Bob',
88011 );
88012 $this->assertEquals($expected, $this->getLogs());
88013 }
88014
88015 public function provideLevelsAndMessages()
88016 {
88017 return array(
88018 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
88019 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
88020 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
88021 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
88022 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
88023 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
88024 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
88025 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
88026 );
88027 }
88028
88029
88030
88031
88032 public function testThrowsOnInvalidLevel()
88033 {
88034 $logger = $this->getLogger();
88035 $logger->log('invalid level', 'Foo');
88036 }
88037
88038 public function testContextReplacement()
88039 {
88040 $logger = $this->getLogger();
88041 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
88042
88043 $expected = array('info {Message {nothing} Bob Bar a}');
88044 $this->assertEquals($expected, $this->getLogs());
88045 }
88046
88047 public function testObjectCastToString()
88048 {
88049 if (method_exists($this, 'createPartialMock')) {
88050 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
88051 } else {
88052 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
88053 }
88054 $dummy->expects($this->once())
88055 ->method('__toString')
88056 ->will($this->returnValue('DUMMY'));
88057
88058 $this->getLogger()->warning($dummy);
88059
88060 $expected = array('warning DUMMY');
88061 $this->assertEquals($expected, $this->getLogs());
88062 }
88063
88064 public function testContextCanContainAnything()
88065 {
88066 $closed = fopen('php://memory', 'r');
88067 fclose($closed);
88068
88069 $context = array(
88070 'bool' => true,
88071 'null' => null,
88072 'string' => 'Foo',
88073 'int' => 0,
88074 'float' => 0.5,
88075 'nested' => array('with object' => new DummyTest),
88076 'object' => new \DateTime,
88077 'resource' => fopen('php://memory', 'r'),
88078 'closed' => $closed,
88079 );
88080
88081 $this->getLogger()->warning('Crazy context data', $context);
88082
88083 $expected = array('warning Crazy context data');
88084 $this->assertEquals($expected, $this->getLogs());
88085 }
88086
88087 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
88088 {
88089 $logger = $this->getLogger();
88090 $logger->warning('Random message', array('exception' => 'oops'));
88091 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
88092
88093 $expected = array(
88094 'warning Random message',
88095 'critical Uncaught Exception!'
88096 );
88097 $this->assertEquals($expected, $this->getLogs());
88098 }
88099 }
88100 <?php
88101
88102 namespace Psr\Log\Test;
88103
88104 use Psr\Log\AbstractLogger;
88105
88106
88107
88108
88109
88110
88111
88112
88113
88114
88115
88116
88117
88118
88119
88120
88121
88122
88123
88124
88125
88126
88127
88128
88129
88130
88131
88132
88133
88134
88135
88136
88137
88138
88139
88140
88141
88142
88143
88144
88145
88146
88147
88148
88149
88150
88151
88152
88153
88154
88155
88156 class TestLogger extends AbstractLogger
88157 {
88158
88159
88160
88161 public $records = [];
88162
88163 public $recordsByLevel = [];
88164
88165
88166
88167
88168 public function log($level, $message, array $context = [])
88169 {
88170 $record = [
88171 'level' => $level,
88172 'message' => $message,
88173 'context' => $context,
88174 ];
88175
88176 $this->recordsByLevel[$record['level']][] = $record;
88177 $this->records[] = $record;
88178 }
88179
88180 public function hasRecords($level)
88181 {
88182 return isset($this->recordsByLevel[$level]);
88183 }
88184
88185 public function hasRecord($record, $level)
88186 {
88187 if (is_string($record)) {
88188 $record = ['message' => $record];
88189 }
88190 return $this->hasRecordThatPasses(function ($rec) use ($record) {
88191 if ($rec['message'] !== $record['message']) {
88192 return false;
88193 }
88194 if (isset($record['context']) && $rec['context'] !== $record['context']) {
88195 return false;
88196 }
88197 return true;
88198 }, $level);
88199 }
88200
88201 public function hasRecordThatContains($message, $level)
88202 {
88203 return $this->hasRecordThatPasses(function ($rec) use ($message) {
88204 return strpos($rec['message'], $message) !== false;
88205 }, $level);
88206 }
88207
88208 public function hasRecordThatMatches($regex, $level)
88209 {
88210 return $this->hasRecordThatPasses(function ($rec) use ($regex) {
88211 return preg_match($regex, $rec['message']) > 0;
88212 }, $level);
88213 }
88214
88215 public function hasRecordThatPasses(callable $predicate, $level)
88216 {
88217 if (!isset($this->recordsByLevel[$level])) {
88218 return false;
88219 }
88220 foreach ($this->recordsByLevel[$level] as $i => $rec) {
88221 if (call_user_func($predicate, $rec, $i)) {
88222 return true;
88223 }
88224 }
88225 return false;
88226 }
88227
88228 public function __call($method, $args)
88229 {
88230 if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
88231 $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
88232 $level = strtolower($matches[2]);
88233 if (method_exists($this, $genericMethod)) {
88234 $args[] = $level;
88235 return call_user_func_array([$this, $genericMethod], $args);
88236 }
88237 }
88238 throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
88239 }
88240
88241 public function reset()
88242 {
88243 $this->records = [];
88244 $this->recordsByLevel = [];
88245 }
88246 }
88247 <?php
88248
88249
88250
88251 require_once __DIR__ . '/composer/autoload_real.php';
88252
88253 return ComposerAutoloaderInitComposerPhar1591171436::getLoader();
88254 <?php
88255
88256
88257
88258 $vendorDir = dirname(dirname(__FILE__));
88259 $baseDir = dirname($vendorDir);
88260
88261 return array(
88262 );
88263 <?php
88264
88265
88266
88267 $vendorDir = dirname(dirname(__FILE__));
88268 $baseDir = dirname($vendorDir);
88269
88270 return array(
88271 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
88272 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
88273 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
88274 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
88275 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
88276 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
88277 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
88278 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
88279 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
88280 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
88281 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
88282 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
88283 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
88284 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
88285 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
88286 'Composer\\' => array($baseDir . '/src/Composer'),
88287 );
88288 <?php
88289
88290
88291
88292 $vendorDir = dirname(dirname(__FILE__));
88293 $baseDir = dirname($vendorDir);
88294
88295 return array(
88296 );
88297 <?php
88298
88299
88300
88301 $vendorDir = dirname(dirname(__FILE__));
88302 $baseDir = dirname($vendorDir);
88303
88304 return array(
88305 '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
88306 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
88307 );
88308 <?php
88309
88310
88311
88312 class ComposerAutoloaderInitComposerPhar1591171436
88313 {
88314 private static $loader;
88315
88316 public static function loadClassLoader($class)
88317 {
88318 if ('Composer\Autoload\ClassLoader' === $class) {
88319 require __DIR__ . '/ClassLoader.php';
88320 }
88321 }
88322
88323
88324
88325
88326 public static function getLoader()
88327 {
88328 if (null !== self::$loader) {
88329 return self::$loader;
88330 }
88331
88332 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1591171436', 'loadClassLoader'), true, true);
88333 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
88334 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1591171436', 'loadClassLoader'));
88335
88336 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
88337 if ($useStaticLoader) {
88338 require_once __DIR__ . '/autoload_static.php';
88339
88340 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1591171436::getInitializer($loader));
88341 } else {
88342 $map = require __DIR__ . '/autoload_namespaces.php';
88343 foreach ($map as $namespace => $path) {
88344 $loader->set($namespace, $path);
88345 }
88346
88347 $map = require __DIR__ . '/autoload_psr4.php';
88348 foreach ($map as $namespace => $path) {
88349 $loader->setPsr4($namespace, $path);
88350 }
88351
88352 $classMap = require __DIR__ . '/autoload_classmap.php';
88353 if ($classMap) {
88354 $loader->addClassMap($classMap);
88355 }
88356 }
88357
88358 $loader->register(true);
88359
88360 if ($useStaticLoader) {
88361 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1591171436::$files;
88362 } else {
88363 $includeFiles = require __DIR__ . '/autoload_files.php';
88364 }
88365 foreach ($includeFiles as $fileIdentifier => $file) {
88366 composerRequireComposerPhar1591171436($fileIdentifier, $file);
88367 }
88368
88369 return $loader;
88370 }
88371 }
88372
88373 function composerRequireComposerPhar1591171436($fileIdentifier, $file)
88374 {
88375 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
88376 require $file;
88377
88378 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
88379 }
88380 }
88381 <?php
88382
88383
88384
88385 namespace Composer\Autoload;
88386
88387 class ComposerStaticInitComposerPhar1591171436
88388 {
88389 public static $files = array (
88390 '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
88391 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
88392 );
88393
88394 public static $prefixLengthsPsr4 = array (
88395 'S' => 
88396 array (
88397 'Symfony\\Polyfill\\Mbstring\\' => 26,
88398 'Symfony\\Polyfill\\Ctype\\' => 23,
88399 'Symfony\\Component\\Process\\' => 26,
88400 'Symfony\\Component\\Finder\\' => 25,
88401 'Symfony\\Component\\Filesystem\\' => 29,
88402 'Symfony\\Component\\Debug\\' => 24,
88403 'Symfony\\Component\\Console\\' => 26,
88404 'Seld\\PharUtils\\' => 15,
88405 'Seld\\JsonLint\\' => 14,
88406 ),
88407 'P' => 
88408 array (
88409 'Psr\\Log\\' => 8,
88410 ),
88411 'J' => 
88412 array (
88413 'JsonSchema\\' => 11,
88414 ),
88415 'C' => 
88416 array (
88417 'Composer\\XdebugHandler\\' => 23,
88418 'Composer\\Spdx\\' => 14,
88419 'Composer\\Semver\\' => 16,
88420 'Composer\\CaBundle\\' => 18,
88421 'Composer\\' => 9,
88422 ),
88423 );
88424
88425 public static $prefixDirsPsr4 = array (
88426 'Symfony\\Polyfill\\Mbstring\\' => 
88427 array (
88428 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
88429 ),
88430 'Symfony\\Polyfill\\Ctype\\' => 
88431 array (
88432 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
88433 ),
88434 'Symfony\\Component\\Process\\' => 
88435 array (
88436 0 => __DIR__ . '/..' . '/symfony/process',
88437 ),
88438 'Symfony\\Component\\Finder\\' => 
88439 array (
88440 0 => __DIR__ . '/..' . '/symfony/finder',
88441 ),
88442 'Symfony\\Component\\Filesystem\\' => 
88443 array (
88444 0 => __DIR__ . '/..' . '/symfony/filesystem',
88445 ),
88446 'Symfony\\Component\\Debug\\' => 
88447 array (
88448 0 => __DIR__ . '/..' . '/symfony/debug',
88449 ),
88450 'Symfony\\Component\\Console\\' => 
88451 array (
88452 0 => __DIR__ . '/..' . '/symfony/console',
88453 ),
88454 'Seld\\PharUtils\\' => 
88455 array (
88456 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
88457 ),
88458 'Seld\\JsonLint\\' => 
88459 array (
88460 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
88461 ),
88462 'Psr\\Log\\' => 
88463 array (
88464 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
88465 ),
88466 'JsonSchema\\' => 
88467 array (
88468 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
88469 ),
88470 'Composer\\XdebugHandler\\' => 
88471 array (
88472 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
88473 ),
88474 'Composer\\Spdx\\' => 
88475 array (
88476 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
88477 ),
88478 'Composer\\Semver\\' => 
88479 array (
88480 0 => __DIR__ . '/..' . '/composer/semver/src',
88481 ),
88482 'Composer\\CaBundle\\' => 
88483 array (
88484 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
88485 ),
88486 'Composer\\' => 
88487 array (
88488 0 => __DIR__ . '/../..' . '/src/Composer',
88489 ),
88490 );
88491
88492 public static function getInitializer(ClassLoader $loader)
88493 {
88494 return \Closure::bind(function () use ($loader) {
88495 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1591171436::$prefixLengthsPsr4;
88496 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1591171436::$prefixDirsPsr4;
88497
88498 }, null, ClassLoader::class);
88499 }
88500 }
88501 <?php
88502
88503
88504
88505
88506
88507
88508
88509
88510
88511
88512
88513 namespace Composer\Autoload;
88514
88515
88516
88517
88518
88519
88520
88521
88522
88523
88524
88525
88526
88527
88528
88529
88530
88531
88532
88533
88534
88535
88536
88537
88538
88539
88540
88541
88542
88543 class ClassLoader
88544 {
88545
88546  private $prefixLengthsPsr4 = array();
88547 private $prefixDirsPsr4 = array();
88548 private $fallbackDirsPsr4 = array();
88549
88550
88551  private $prefixesPsr0 = array();
88552 private $fallbackDirsPsr0 = array();
88553
88554 private $useIncludePath = false;
88555 private $classMap = array();
88556 private $classMapAuthoritative = false;
88557 private $missingClasses = array();
88558 private $apcuPrefix;
88559
88560 public function getPrefixes()
88561 {
88562 if (!empty($this->prefixesPsr0)) {
88563 return call_user_func_array('array_merge', $this->prefixesPsr0);
88564 }
88565
88566 return array();
88567 }
88568
88569 public function getPrefixesPsr4()
88570 {
88571 return $this->prefixDirsPsr4;
88572 }
88573
88574 public function getFallbackDirs()
88575 {
88576 return $this->fallbackDirsPsr0;
88577 }
88578
88579 public function getFallbackDirsPsr4()
88580 {
88581 return $this->fallbackDirsPsr4;
88582 }
88583
88584 public function getClassMap()
88585 {
88586 return $this->classMap;
88587 }
88588
88589
88590
88591
88592 public function addClassMap(array $classMap)
88593 {
88594 if ($this->classMap) {
88595 $this->classMap = array_merge($this->classMap, $classMap);
88596 } else {
88597 $this->classMap = $classMap;
88598 }
88599 }
88600
88601
88602
88603
88604
88605
88606
88607
88608
88609 public function add($prefix, $paths, $prepend = false)
88610 {
88611 if (!$prefix) {
88612 if ($prepend) {
88613 $this->fallbackDirsPsr0 = array_merge(
88614 (array) $paths,
88615 $this->fallbackDirsPsr0
88616 );
88617 } else {
88618 $this->fallbackDirsPsr0 = array_merge(
88619 $this->fallbackDirsPsr0,
88620 (array) $paths
88621 );
88622 }
88623
88624 return;
88625 }
88626
88627 $first = $prefix[0];
88628 if (!isset($this->prefixesPsr0[$first][$prefix])) {
88629 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
88630
88631 return;
88632 }
88633 if ($prepend) {
88634 $this->prefixesPsr0[$first][$prefix] = array_merge(
88635 (array) $paths,
88636 $this->prefixesPsr0[$first][$prefix]
88637 );
88638 } else {
88639 $this->prefixesPsr0[$first][$prefix] = array_merge(
88640 $this->prefixesPsr0[$first][$prefix],
88641 (array) $paths
88642 );
88643 }
88644 }
88645
88646
88647
88648
88649
88650
88651
88652
88653
88654
88655
88656 public function addPsr4($prefix, $paths, $prepend = false)
88657 {
88658 if (!$prefix) {
88659
88660  if ($prepend) {
88661 $this->fallbackDirsPsr4 = array_merge(
88662 (array) $paths,
88663 $this->fallbackDirsPsr4
88664 );
88665 } else {
88666 $this->fallbackDirsPsr4 = array_merge(
88667 $this->fallbackDirsPsr4,
88668 (array) $paths
88669 );
88670 }
88671 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
88672
88673  $length = strlen($prefix);
88674 if ('\\' !== $prefix[$length - 1]) {
88675 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
88676 }
88677 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
88678 $this->prefixDirsPsr4[$prefix] = (array) $paths;
88679 } elseif ($prepend) {
88680
88681  $this->prefixDirsPsr4[$prefix] = array_merge(
88682 (array) $paths,
88683 $this->prefixDirsPsr4[$prefix]
88684 );
88685 } else {
88686
88687  $this->prefixDirsPsr4[$prefix] = array_merge(
88688 $this->prefixDirsPsr4[$prefix],
88689 (array) $paths
88690 );
88691 }
88692 }
88693
88694
88695
88696
88697
88698
88699
88700
88701 public function set($prefix, $paths)
88702 {
88703 if (!$prefix) {
88704 $this->fallbackDirsPsr0 = (array) $paths;
88705 } else {
88706 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
88707 }
88708 }
88709
88710
88711
88712
88713
88714
88715
88716
88717
88718
88719 public function setPsr4($prefix, $paths)
88720 {
88721 if (!$prefix) {
88722 $this->fallbackDirsPsr4 = (array) $paths;
88723 } else {
88724 $length = strlen($prefix);
88725 if ('\\' !== $prefix[$length - 1]) {
88726 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
88727 }
88728 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
88729 $this->prefixDirsPsr4[$prefix] = (array) $paths;
88730 }
88731 }
88732
88733
88734
88735
88736
88737
88738 public function setUseIncludePath($useIncludePath)
88739 {
88740 $this->useIncludePath = $useIncludePath;
88741 }
88742
88743
88744
88745
88746
88747
88748
88749 public function getUseIncludePath()
88750 {
88751 return $this->useIncludePath;
88752 }
88753
88754
88755
88756
88757
88758
88759
88760 public function setClassMapAuthoritative($classMapAuthoritative)
88761 {
88762 $this->classMapAuthoritative = $classMapAuthoritative;
88763 }
88764
88765
88766
88767
88768
88769
88770 public function isClassMapAuthoritative()
88771 {
88772 return $this->classMapAuthoritative;
88773 }
88774
88775
88776
88777
88778
88779
88780 public function setApcuPrefix($apcuPrefix)
88781 {
88782 $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
88783 }
88784
88785
88786
88787
88788
88789
88790 public function getApcuPrefix()
88791 {
88792 return $this->apcuPrefix;
88793 }
88794
88795
88796
88797
88798
88799
88800 public function register($prepend = false)
88801 {
88802 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
88803 }
88804
88805
88806
88807
88808 public function unregister()
88809 {
88810 spl_autoload_unregister(array($this, 'loadClass'));
88811 }
88812
88813
88814
88815
88816
88817
88818
88819 public function loadClass($class)
88820 {
88821 if ($file = $this->findFile($class)) {
88822 includeFile($file);
88823
88824 return true;
88825 }
88826 }
88827
88828
88829
88830
88831
88832
88833
88834
88835 public function findFile($class)
88836 {
88837
88838  if (isset($this->classMap[$class])) {
88839 return $this->classMap[$class];
88840 }
88841 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
88842 return false;
88843 }
88844 if (null !== $this->apcuPrefix) {
88845 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
88846 if ($hit) {
88847 return $file;
88848 }
88849 }
88850
88851 $file = $this->findFileWithExtension($class, '.php');
88852
88853
88854  if (false === $file && defined('HHVM_VERSION')) {
88855 $file = $this->findFileWithExtension($class, '.hh');
88856 }
88857
88858 if (null !== $this->apcuPrefix) {
88859 apcu_add($this->apcuPrefix.$class, $file);
88860 }
88861
88862 if (false === $file) {
88863
88864  $this->missingClasses[$class] = true;
88865 }
88866
88867 return $file;
88868 }
88869
88870 private function findFileWithExtension($class, $ext)
88871 {
88872
88873  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
88874
88875 $first = $class[0];
88876 if (isset($this->prefixLengthsPsr4[$first])) {
88877 $subPath = $class;
88878 while (false !== $lastPos = strrpos($subPath, '\\')) {
88879 $subPath = substr($subPath, 0, $lastPos);
88880 $search = $subPath . '\\';
88881 if (isset($this->prefixDirsPsr4[$search])) {
88882 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
88883 foreach ($this->prefixDirsPsr4[$search] as $dir) {
88884 if (file_exists($file = $dir . $pathEnd)) {
88885 return $file;
88886 }
88887 }
88888 }
88889 }
88890 }
88891
88892
88893  foreach ($this->fallbackDirsPsr4 as $dir) {
88894 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
88895 return $file;
88896 }
88897 }
88898
88899
88900  if (false !== $pos = strrpos($class, '\\')) {
88901
88902  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
88903 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
88904 } else {
88905
88906  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
88907 }
88908
88909 if (isset($this->prefixesPsr0[$first])) {
88910 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
88911 if (0 === strpos($class, $prefix)) {
88912 foreach ($dirs as $dir) {
88913 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
88914 return $file;
88915 }
88916 }
88917 }
88918 }
88919 }
88920
88921
88922  foreach ($this->fallbackDirsPsr0 as $dir) {
88923 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
88924 return $file;
88925 }
88926 }
88927
88928
88929  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
88930 return $file;
88931 }
88932
88933 return false;
88934 }
88935 }
88936
88937
88938
88939
88940
88941
88942 function includeFile($file)
88943 {
88944 include $file;
88945 }
88946 ##
88947 ## Bundle of CA Root Certificates
88948 ##
88949 ## Certificate data from Mozilla as of: Wed Jan  1 04:12:10 2020 GMT
88950 ##
88951 ## This is a bundle of X.509 certificates of public Certificate Authorities
88952 ## (CA). These were automatically extracted from Mozilla's root certificates
88953 ## file (certdata.txt).  This file can be found in the mozilla source tree:
88954 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
88955 ##
88956 ## It contains the certificates in PEM format and therefore
88957 ## can be directly used with curl / libcurl / php_curl, or with
88958 ## an Apache+mod_ssl webserver for SSL client authentication.
88959 ## Just configure this file as the SSLCACertificateFile.
88960 ##
88961 ## Conversion done with mk-ca-bundle.pl version 1.27.
88962 ## SHA256: f3bdcd74612952da8476a9d4147f50b29ad0710b7dd95b4c8690500209986d70
88963 ##
88964
88965
88966 GlobalSign Root CA
88967 ==================
88968 -----BEGIN CERTIFICATE-----
88969 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
88970 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
88971 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
88972 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
88973 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
88974 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
88975 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
88976 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
88977 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
88978 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
88979 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
88980 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
88981 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
88982 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
88983 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
88984 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
88985 -----END CERTIFICATE-----
88986
88987 GlobalSign Root CA - R2
88988 =======================
88989 -----BEGIN CERTIFICATE-----
88990 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
88991 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
88992 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
88993 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
88994 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
88995 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
88996 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
88997 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
88998 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
88999 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
89000 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
89001 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
89002 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
89003 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
89004 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
89005 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
89006 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
89007 -----END CERTIFICATE-----
89008
89009 Verisign Class 3 Public Primary Certification Authority - G3
89010 ============================================================
89011 -----BEGIN CERTIFICATE-----
89012 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
89013 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
89014 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
89015 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
89016 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
89017 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
89018 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
89019 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
89020 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
89021 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
89022 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
89023 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
89024 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
89025 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
89026 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
89027 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
89028 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
89029 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
89030 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
89031 -----END CERTIFICATE-----
89032
89033 Entrust.net Premium 2048 Secure Server CA
89034 =========================================
89035 -----BEGIN CERTIFICATE-----
89036 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
89037 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
89038 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
89039 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
89040 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
89041 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
89042 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
89043 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
89044 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
89045 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
89046 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
89047 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
89048 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
89049 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
89050 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
89051 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
89052 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
89053 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
89054 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
89055 -----END CERTIFICATE-----
89056
89057 Baltimore CyberTrust Root
89058 =========================
89059 -----BEGIN CERTIFICATE-----
89060 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
89061 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
89062 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
89063 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
89064 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
89065 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
89066 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
89067 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
89068 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
89069 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
89070 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
89071 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
89072 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
89073 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
89074 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
89075 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
89076 -----END CERTIFICATE-----
89077
89078 AddTrust External Root
89079 ======================
89080 -----BEGIN CERTIFICATE-----
89081 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
89082 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
89083 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
89084 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
89085 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
89086 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
89087 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
89088 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
89089 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
89090 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
89091 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
89092 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
89093 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
89094 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
89095 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
89096 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
89097 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
89098 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
89099 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
89100 -----END CERTIFICATE-----
89101
89102 Entrust Root Certification Authority
89103 ====================================
89104 -----BEGIN CERTIFICATE-----
89105 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
89106 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
89107 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
89108 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
89109 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
89110 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
89111 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
89112 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
89113 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
89114 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
89115 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
89116 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
89117 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
89118 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
89119 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
89120 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
89121 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
89122 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
89123 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
89124 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
89125 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
89126 -----END CERTIFICATE-----
89127
89128 GeoTrust Global CA
89129 ==================
89130 -----BEGIN CERTIFICATE-----
89131 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
89132 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
89133 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
89134 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
89135 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
89136 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
89137 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
89138 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
89139 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
89140 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
89141 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
89142 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
89143 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
89144 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
89145 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
89146 Mw==
89147 -----END CERTIFICATE-----
89148
89149 GeoTrust Universal CA
89150 =====================
89151 -----BEGIN CERTIFICATE-----
89152 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
89153 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
89154 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
89155 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
89156 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
89157 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
89158 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
89159 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
89160 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
89161 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
89162 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
89163 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
89164 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
89165 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
89166 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
89167 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
89168 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
89169 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
89170 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
89171 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
89172 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
89173 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
89174 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
89175 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
89176 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
89177 -----END CERTIFICATE-----
89178
89179 GeoTrust Universal CA 2
89180 =======================
89181 -----BEGIN CERTIFICATE-----
89182 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
89183 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
89184 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
89185 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
89186 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
89187 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
89188 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
89189 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
89190 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
89191 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
89192 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
89193 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
89194 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
89195 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
89196 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
89197 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
89198 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
89199 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
89200 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
89201 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
89202 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
89203 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
89204 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
89205 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
89206 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
89207 -----END CERTIFICATE-----
89208
89209 Comodo AAA Services root
89210 ========================
89211 -----BEGIN CERTIFICATE-----
89212 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
89213 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
89214 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
89215 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
89216 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
89217 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
89218 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
89219 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
89220 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
89221 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
89222 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
89223 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
89224 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
89225 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
89226 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
89227 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
89228 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
89229 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
89230 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
89231 -----END CERTIFICATE-----
89232
89233 QuoVadis Root CA
89234 ================
89235 -----BEGIN CERTIFICATE-----
89236 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
89237 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
89238 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
89239 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
89240 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
89241 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
89242 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
89243 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
89244 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
89245 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
89246 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
89247 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
89248 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
89249 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
89250 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
89251 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
89252 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
89253 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
89254 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
89255 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
89256 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
89257 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
89258 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
89259 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
89260 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
89261 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
89262 5nrQNiOKSnQ2+Q==
89263 -----END CERTIFICATE-----
89264
89265 QuoVadis Root CA 2
89266 ==================
89267 -----BEGIN CERTIFICATE-----
89268 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
89269 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
89270 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
89271 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
89272 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
89273 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
89274 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
89275 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
89276 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
89277 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
89278 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
89279 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
89280 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
89281 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
89282 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
89283 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
89284 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
89285 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
89286 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
89287 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
89288 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
89289 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
89290 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
89291 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
89292 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
89293 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
89294 -----END CERTIFICATE-----
89295
89296 QuoVadis Root CA 3
89297 ==================
89298 -----BEGIN CERTIFICATE-----
89299 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
89300 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
89301 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
89302 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
89303 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
89304 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
89305 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
89306 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
89307 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
89308 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
89309 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
89310 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
89311 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
89312 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
89313 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
89314 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
89315 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
89316 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
89317 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
89318 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
89319 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
89320 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
89321 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
89322 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
89323 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
89324 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
89325 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
89326 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
89327 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
89328 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
89329 -----END CERTIFICATE-----
89330
89331 Security Communication Root CA
89332 ==============================
89333 -----BEGIN CERTIFICATE-----
89334 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
89335 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
89336 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
89337 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
89338 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
89339 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
89340 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
89341 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
89342 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
89343 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
89344 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
89345 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
89346 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
89347 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
89348 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
89349 FL39vmwLAw==
89350 -----END CERTIFICATE-----
89351
89352 Sonera Class 2 Root CA
89353 ======================
89354 -----BEGIN CERTIFICATE-----
89355 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
89356 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
89357 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
89358 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
89359 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
89360 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
89361 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
89362 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
89363 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
89364 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
89365 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
89366 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
89367 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
89368 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
89369 llpwrN9M
89370 -----END CERTIFICATE-----
89371
89372 XRamp Global CA Root
89373 ====================
89374 -----BEGIN CERTIFICATE-----
89375 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
89376 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
89377 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
89378 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
89379 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
89380 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
89381 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
89382 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
89383 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
89384 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
89385 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
89386 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
89387 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
89388 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
89389 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
89390 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
89391 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
89392 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
89393 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
89394 -----END CERTIFICATE-----
89395
89396 Go Daddy Class 2 CA
89397 ===================
89398 -----BEGIN CERTIFICATE-----
89399 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
89400 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
89401 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
89402 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
89403 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
89404 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
89405 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
89406 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
89407 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
89408 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
89409 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
89410 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
89411 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
89412 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
89413 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
89414 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
89415 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
89416 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
89417 vZ8=
89418 -----END CERTIFICATE-----
89419
89420 Starfield Class 2 CA
89421 ====================
89422 -----BEGIN CERTIFICATE-----
89423 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
89424 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
89425 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
89426 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
89427 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
89428 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
89429 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
89430 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
89431 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
89432 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
89433 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
89434 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
89435 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
89436 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
89437 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
89438 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
89439 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
89440 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
89441 QBFGmh95DmK/D5fs4C8fF5Q=
89442 -----END CERTIFICATE-----
89443
89444 Taiwan GRCA
89445 ===========
89446 -----BEGIN CERTIFICATE-----
89447 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
89448 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
89449 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
89450 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
89451 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
89452 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
89453 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
89454 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
89455 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
89456 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
89457 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
89458 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
89459 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
89460 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
89461 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
89462 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
89463 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
89464 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
89465 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
89466 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
89467 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
89468 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
89469 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
89470 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
89471 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
89472 -----END CERTIFICATE-----
89473
89474 DigiCert Assured ID Root CA
89475 ===========================
89476 -----BEGIN CERTIFICATE-----
89477 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
89478 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
89479 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
89480 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
89481 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
89482 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
89483 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
89484 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
89485 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
89486 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
89487 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
89488 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
89489 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
89490 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
89491 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
89492 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
89493 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
89494 -----END CERTIFICATE-----
89495
89496 DigiCert Global Root CA
89497 =======================
89498 -----BEGIN CERTIFICATE-----
89499 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
89500 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
89501 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
89502 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
89503 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
89504 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
89505 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
89506 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
89507 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
89508 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
89509 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
89510 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
89511 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
89512 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
89513 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
89514 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
89515 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
89516 -----END CERTIFICATE-----
89517
89518 DigiCert High Assurance EV Root CA
89519 ==================================
89520 -----BEGIN CERTIFICATE-----
89521 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
89522 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
89523 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
89524 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
89525 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
89526 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
89527 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
89528 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
89529 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
89530 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
89531 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
89532 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
89533 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
89534 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
89535 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
89536 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
89537 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
89538 -----END CERTIFICATE-----
89539
89540 DST Root CA X3
89541 ==============
89542 -----BEGIN CERTIFICATE-----
89543 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
89544 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
89545 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
89546 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
89547 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
89548 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
89549 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
89550 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
89551 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
89552 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
89553 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
89554 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
89555 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
89556 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
89557 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
89558 -----END CERTIFICATE-----
89559
89560 SwissSign Gold CA - G2
89561 ======================
89562 -----BEGIN CERTIFICATE-----
89563 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
89564 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
89565 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
89566 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
89567 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
89568 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
89569 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
89570 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
89571 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
89572 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
89573 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
89574 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
89575 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
89576 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
89577 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
89578 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
89579 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
89580 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
89581 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
89582 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
89583 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
89584 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
89585 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
89586 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
89587 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
89588 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
89589 -----END CERTIFICATE-----
89590
89591 SwissSign Silver CA - G2
89592 ========================
89593 -----BEGIN CERTIFICATE-----
89594 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
89595 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
89596 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
89597 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
89598 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
89599 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
89600 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
89601 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
89602 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
89603 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
89604 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
89605 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
89606 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
89607 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
89608 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
89609 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
89610 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
89611 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
89612 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
89613 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
89614 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
89615 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
89616 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
89617 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
89618 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
89619 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
89620 -----END CERTIFICATE-----
89621
89622 GeoTrust Primary Certification Authority
89623 ========================================
89624 -----BEGIN CERTIFICATE-----
89625 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
89626 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
89627 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
89628 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
89629 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
89630 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
89631 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
89632 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
89633 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
89634 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
89635 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
89636 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
89637 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
89638 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
89639 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
89640 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
89641 -----END CERTIFICATE-----
89642
89643 thawte Primary Root CA
89644 ======================
89645 -----BEGIN CERTIFICATE-----
89646 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
89647 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
89648 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
89649 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
89650 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
89651 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
89652 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
89653 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
89654 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
89655 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
89656 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
89657 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
89658 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
89659 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
89660 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
89661 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
89662 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
89663 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
89664 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
89665 -----END CERTIFICATE-----
89666
89667 VeriSign Class 3 Public Primary Certification Authority - G5
89668 ============================================================
89669 -----BEGIN CERTIFICATE-----
89670 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
89671 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
89672 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
89673 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
89674 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
89675 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
89676 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
89677 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
89678 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
89679 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
89680 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
89681 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
89682 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
89683 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
89684 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
89685 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
89686 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
89687 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
89688 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
89689 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
89690 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
89691 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
89692 -----END CERTIFICATE-----
89693
89694 SecureTrust CA
89695 ==============
89696 -----BEGIN CERTIFICATE-----
89697 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
89698 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
89699 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
89700 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
89701 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
89702 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
89703 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
89704 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
89705 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
89706 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
89707 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
89708 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
89709 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
89710 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
89711 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
89712 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
89713 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
89714 -----END CERTIFICATE-----
89715
89716 Secure Global CA
89717 ================
89718 -----BEGIN CERTIFICATE-----
89719 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
89720 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
89721 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
89722 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
89723 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
89724 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
89725 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
89726 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
89727 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
89728 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
89729 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
89730 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
89731 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
89732 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
89733 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
89734 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
89735 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
89736 -----END CERTIFICATE-----
89737
89738 COMODO Certification Authority
89739 ==============================
89740 -----BEGIN CERTIFICATE-----
89741 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
89742 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
89743 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
89744 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
89745 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
89746 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
89747 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
89748 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
89749 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
89750 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
89751 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
89752 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
89753 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
89754 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
89755 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
89756 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
89757 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
89758 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
89759 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
89760 -----END CERTIFICATE-----
89761
89762 Network Solutions Certificate Authority
89763 =======================================
89764 -----BEGIN CERTIFICATE-----
89765 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
89766 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
89767 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
89768 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
89769 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
89770 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
89771 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
89772 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
89773 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
89774 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
89775 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
89776 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
89777 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
89778 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
89779 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
89780 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
89781 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
89782 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
89783 -----END CERTIFICATE-----
89784
89785 COMODO ECC Certification Authority
89786 ==================================
89787 -----BEGIN CERTIFICATE-----
89788 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
89789 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
89790 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
89791 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
89792 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
89793 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
89794 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
89795 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
89796 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
89797 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
89798 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
89799 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
89800 -----END CERTIFICATE-----
89801
89802 OISTE WISeKey Global Root GA CA
89803 ===============================
89804 -----BEGIN CERTIFICATE-----
89805 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
89806 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
89807 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
89808 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
89809 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
89810 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
89811 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
89812 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
89813 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
89814 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
89815 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
89816 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
89817 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
89818 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
89819 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
89820 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
89821 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
89822 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
89823 -----END CERTIFICATE-----
89824
89825 Certigna
89826 ========
89827 -----BEGIN CERTIFICATE-----
89828 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
89829 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
89830 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
89831 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
89832 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
89833 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
89834 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
89835 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
89836 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
89837 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
89838 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
89839 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
89840 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
89841 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
89842 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
89843 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
89844 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
89845 -----END CERTIFICATE-----
89846
89847 Cybertrust Global Root
89848 ======================
89849 -----BEGIN CERTIFICATE-----
89850 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
89851 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
89852 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
89853 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
89854 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
89855 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
89856 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
89857 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
89858 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
89859 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
89860 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
89861 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
89862 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
89863 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
89864 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
89865 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
89866 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
89867 -----END CERTIFICATE-----
89868
89869 ePKI Root Certification Authority
89870 =================================
89871 -----BEGIN CERTIFICATE-----
89872 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
89873 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
89874 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
89875 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
89876 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
89877 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
89878 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
89879 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
89880 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
89881 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
89882 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
89883 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
89884 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
89885 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
89886 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
89887 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
89888 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
89889 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
89890 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
89891 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
89892 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
89893 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
89894 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
89895 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
89896 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
89897 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
89898 -----END CERTIFICATE-----
89899
89900 certSIGN ROOT CA
89901 ================
89902 -----BEGIN CERTIFICATE-----
89903 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
89904 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
89905 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
89906 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
89907 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
89908 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
89909 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
89910 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
89911 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
89912 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
89913 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
89914 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
89915 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
89916 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
89917 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
89918 -----END CERTIFICATE-----
89919
89920 GeoTrust Primary Certification Authority - G3
89921 =============================================
89922 -----BEGIN CERTIFICATE-----
89923 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
89924 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
89925 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
89926 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
89927 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
89928 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
89929 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
89930 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
89931 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
89932 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
89933 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
89934 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
89935 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
89936 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
89937 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
89938 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
89939 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
89940 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
89941 -----END CERTIFICATE-----
89942
89943 thawte Primary Root CA - G2
89944 ===========================
89945 -----BEGIN CERTIFICATE-----
89946 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
89947 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
89948 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
89949 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
89950 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
89951 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
89952 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
89953 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
89954 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
89955 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
89956 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
89957 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
89958 -----END CERTIFICATE-----
89959
89960 thawte Primary Root CA - G3
89961 ===========================
89962 -----BEGIN CERTIFICATE-----
89963 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
89964 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
89965 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
89966 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
89967 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
89968 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
89969 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
89970 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
89971 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
89972 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
89973 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
89974 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
89975 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
89976 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
89977 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
89978 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
89979 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
89980 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
89981 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
89982 -----END CERTIFICATE-----
89983
89984 GeoTrust Primary Certification Authority - G2
89985 =============================================
89986 -----BEGIN CERTIFICATE-----
89987 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
89988 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
89989 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
89990 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
89991 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
89992 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
89993 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
89994 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
89995 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
89996 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
89997 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
89998 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
89999 npaqBA+K
90000 -----END CERTIFICATE-----
90001
90002 VeriSign Universal Root Certification Authority
90003 ===============================================
90004 -----BEGIN CERTIFICATE-----
90005 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
90006 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
90007 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
90008 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
90009 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
90010 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
90011 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
90012 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
90013 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
90014 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
90015 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
90016 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
90017 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
90018 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
90019 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
90020 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
90021 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
90022 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
90023 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
90024 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
90025 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
90026 mJO37M2CYfE45k+XmCpajQ==
90027 -----END CERTIFICATE-----
90028
90029 VeriSign Class 3 Public Primary Certification Authority - G4
90030 ============================================================
90031 -----BEGIN CERTIFICATE-----
90032 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
90033 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
90034 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
90035 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
90036 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
90037 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
90038 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
90039 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
90040 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
90041 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
90042 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
90043 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
90044 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
90045 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
90046 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
90047 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
90048 -----END CERTIFICATE-----
90049
90050 NetLock Arany (Class Gold) Főtanúsítvány
90051 ========================================
90052 -----BEGIN CERTIFICATE-----
90053 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
90054 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
90055 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
90056 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
90057 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
90058 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
90059 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
90060 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
90061 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
90062 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
90063 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
90064 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
90065 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
90066 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
90067 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
90068 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
90069 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
90070 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
90071 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
90072 -----END CERTIFICATE-----
90073
90074 Staat der Nederlanden Root CA - G2
90075 ==================================
90076 -----BEGIN CERTIFICATE-----
90077 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
90078 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
90079 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
90080 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
90081 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
90082 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
90083 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
90084 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
90085 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
90086 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
90087 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
90088 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
90089 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
90090 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
90091 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
90092 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
90093 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
90094 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
90095 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
90096 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
90097 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
90098 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
90099 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
90100 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
90101 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
90102 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
90103 66+KAQ==
90104 -----END CERTIFICATE-----
90105
90106 Hongkong Post Root CA 1
90107 =======================
90108 -----BEGIN CERTIFICATE-----
90109 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
90110 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
90111 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
90112 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
90113 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
90114 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
90115 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
90116 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
90117 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
90118 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
90119 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
90120 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
90121 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
90122 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
90123 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
90124 -----END CERTIFICATE-----
90125
90126 SecureSign RootCA11
90127 ===================
90128 -----BEGIN CERTIFICATE-----
90129 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
90130 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
90131 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
90132 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
90133 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
90134 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
90135 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
90136 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
90137 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
90138 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
90139 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
90140 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
90141 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
90142 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
90143 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
90144 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
90145 -----END CERTIFICATE-----
90146
90147 Microsec e-Szigno Root CA 2009
90148 ==============================
90149 -----BEGIN CERTIFICATE-----
90150 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
90151 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
90152 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
90153 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
90154 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
90155 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
90156 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
90157 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
90158 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
90159 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
90160 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
90161 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
90162 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
90163 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
90164 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
90165 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
90166 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
90167 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
90168 LXpUq3DDfSJlgnCW
90169 -----END CERTIFICATE-----
90170
90171 GlobalSign Root CA - R3
90172 =======================
90173 -----BEGIN CERTIFICATE-----
90174 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
90175 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
90176 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
90177 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
90178 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
90179 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
90180 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
90181 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
90182 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
90183 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
90184 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
90185 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
90186 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
90187 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
90188 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
90189 kpeDMdmztcpHWD9f
90190 -----END CERTIFICATE-----
90191
90192 Autoridad de Certificacion Firmaprofesional CIF A62634068
90193 =========================================================
90194 -----BEGIN CERTIFICATE-----
90195 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
90196 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
90197 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
90198 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
90199 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
90200 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
90201 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
90202 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
90203 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
90204 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
90205 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
90206 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
90207 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
90208 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
90209 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
90210 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
90211 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
90212 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
90213 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
90214 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
90215 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
90216 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
90217 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
90218 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
90219 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
90220 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
90221 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
90222 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
90223 -----END CERTIFICATE-----
90224
90225 Izenpe.com
90226 ==========
90227 -----BEGIN CERTIFICATE-----
90228 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
90229 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
90230 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
90231 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
90232 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
90233 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
90234 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
90235 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
90236 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
90237 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
90238 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
90239 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
90240 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
90241 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
90242 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
90243 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
90244 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
90245 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
90246 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
90247 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
90248 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
90249 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
90250 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
90251 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
90252 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
90253 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
90254 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
90255 -----END CERTIFICATE-----
90256
90257 Chambers of Commerce Root - 2008
90258 ================================
90259 -----BEGIN CERTIFICATE-----
90260 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
90261 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
90262 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
90263 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
90264 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
90265 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
90266 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
90267 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
90268 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
90269 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
90270 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
90271 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
90272 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
90273 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
90274 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
90275 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
90276 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
90277 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
90278 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
90279 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
90280 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
90281 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
90282 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
90283 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
90284 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
90285 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
90286 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
90287 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
90288 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
90289 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
90290 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
90291 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
90292 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
90293 -----END CERTIFICATE-----
90294
90295 Global Chambersign Root - 2008
90296 ==============================
90297 -----BEGIN CERTIFICATE-----
90298 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
90299 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
90300 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
90301 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
90302 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
90303 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
90304 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
90305 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
90306 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
90307 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
90308 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
90309 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
90310 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
90311 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
90312 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
90313 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
90314 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
90315 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
90316 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
90317 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
90318 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
90319 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
90320 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
90321 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
90322 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
90323 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
90324 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
90325 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
90326 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
90327 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
90328 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
90329 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
90330 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
90331 -----END CERTIFICATE-----
90332
90333 Go Daddy Root Certificate Authority - G2
90334 ========================================
90335 -----BEGIN CERTIFICATE-----
90336 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
90337 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
90338 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
90339 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
90340 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
90341 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
90342 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
90343 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
90344 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
90345 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
90346 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
90347 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
90348 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
90349 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
90350 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
90351 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
90352 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
90353 -----END CERTIFICATE-----
90354
90355 Starfield Root Certificate Authority - G2
90356 =========================================
90357 -----BEGIN CERTIFICATE-----
90358 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
90359 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
90360 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
90361 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
90362 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
90363 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
90364 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
90365 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
90366 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
90367 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
90368 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
90369 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
90370 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
90371 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
90372 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
90373 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
90374 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
90375 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
90376 -----END CERTIFICATE-----
90377
90378 Starfield Services Root Certificate Authority - G2
90379 ==================================================
90380 -----BEGIN CERTIFICATE-----
90381 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
90382 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
90383 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
90384 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
90385 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
90386 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
90387 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
90388 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
90389 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
90390 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
90391 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
90392 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
90393 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
90394 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
90395 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
90396 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
90397 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
90398 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
90399 -----END CERTIFICATE-----
90400
90401 AffirmTrust Commercial
90402 ======================
90403 -----BEGIN CERTIFICATE-----
90404 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
90405 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
90406 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
90407 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
90408 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
90409 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
90410 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
90411 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
90412 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
90413 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
90414 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
90415 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
90416 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
90417 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
90418 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
90419 -----END CERTIFICATE-----
90420
90421 AffirmTrust Networking
90422 ======================
90423 -----BEGIN CERTIFICATE-----
90424 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
90425 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
90426 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
90427 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
90428 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
90429 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
90430 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
90431 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
90432 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
90433 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
90434 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
90435 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
90436 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
90437 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
90438 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
90439 -----END CERTIFICATE-----
90440
90441 AffirmTrust Premium
90442 ===================
90443 -----BEGIN CERTIFICATE-----
90444 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
90445 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
90446 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
90447 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
90448 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
90449 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
90450 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
90451 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
90452 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
90453 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
90454 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
90455 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
90456 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
90457 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
90458 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
90459 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
90460 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
90461 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
90462 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
90463 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
90464 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
90465 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
90466 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
90467 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
90468 -----END CERTIFICATE-----
90469
90470 AffirmTrust Premium ECC
90471 =======================
90472 -----BEGIN CERTIFICATE-----
90473 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
90474 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
90475 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
90476 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
90477 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
90478 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
90479 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
90480 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
90481 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
90482 eQ==
90483 -----END CERTIFICATE-----
90484
90485 Certum Trusted Network CA
90486 =========================
90487 -----BEGIN CERTIFICATE-----
90488 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
90489 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
90490 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
90491 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
90492 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
90493 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
90494 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
90495 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
90496 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
90497 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
90498 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
90499 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
90500 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
90501 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
90502 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
90503 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
90504 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
90505 -----END CERTIFICATE-----
90506
90507 TWCA Root Certification Authority
90508 =================================
90509 -----BEGIN CERTIFICATE-----
90510 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
90511 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
90512 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
90513 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
90514 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
90515 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
90516 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
90517 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
90518 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
90519 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
90520 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
90521 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
90522 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
90523 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
90524 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
90525 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
90526 -----END CERTIFICATE-----
90527
90528 Security Communication RootCA2
90529 ==============================
90530 -----BEGIN CERTIFICATE-----
90531 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
90532 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
90533 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
90534 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
90535 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
90536 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
90537 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
90538 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
90539 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
90540 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
90541 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
90542 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
90543 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
90544 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
90545 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
90546 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
90547 -----END CERTIFICATE-----
90548
90549 EC-ACC
90550 ======
90551 -----BEGIN CERTIFICATE-----
90552 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
90553 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
90554 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
90555 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
90556 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
90557 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
90558 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
90559 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
90560 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
90561 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
90562 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
90563 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
90564 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
90565 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
90566 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
90567 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
90568 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
90569 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
90570 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
90571 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
90572 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
90573 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
90574 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
90575 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
90576 5EI=
90577 -----END CERTIFICATE-----
90578
90579 Hellenic Academic and Research Institutions RootCA 2011
90580 =======================================================
90581 -----BEGIN CERTIFICATE-----
90582 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
90583 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
90584 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
90585 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
90586 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
90587 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
90588 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
90589 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
90590 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
90591 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
90592 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
90593 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
90594 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
90595 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
90596 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
90597 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
90598 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
90599 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
90600 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
90601 -----END CERTIFICATE-----
90602
90603 Actalis Authentication Root CA
90604 ==============================
90605 -----BEGIN CERTIFICATE-----
90606 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
90607 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
90608 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
90609 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
90610 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
90611 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
90612 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
90613 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
90614 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
90615 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
90616 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
90617 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
90618 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
90619 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
90620 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
90621 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
90622 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
90623 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
90624 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
90625 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
90626 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
90627 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
90628 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
90629 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
90630 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
90631 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
90632 -----END CERTIFICATE-----
90633
90634 Trustis FPS Root CA
90635 ===================
90636 -----BEGIN CERTIFICATE-----
90637 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
90638 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
90639 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
90640 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
90641 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
90642 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
90643 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
90644 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
90645 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
90646 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
90647 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
90648 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
90649 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
90650 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
90651 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
90652 iB6XzCGcKQENZetX2fNXlrtIzYE=
90653 -----END CERTIFICATE-----
90654
90655 Buypass Class 2 Root CA
90656 =======================
90657 -----BEGIN CERTIFICATE-----
90658 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
90659 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
90660 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
90661 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
90662 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
90663 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
90664 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
90665 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
90666 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
90667 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
90668 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
90669 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
90670 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
90671 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
90672 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
90673 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
90674 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
90675 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
90676 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
90677 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
90678 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
90679 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
90680 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
90681 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
90682 rJgWVqA=
90683 -----END CERTIFICATE-----
90684
90685 Buypass Class 3 Root CA
90686 =======================
90687 -----BEGIN CERTIFICATE-----
90688 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
90689 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
90690 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
90691 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
90692 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
90693 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
90694 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
90695 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
90696 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
90697 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
90698 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
90699 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
90700 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
90701 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
90702 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
90703 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
90704 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
90705 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
90706 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
90707 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
90708 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
90709 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
90710 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
90711 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
90712 Cp/HuZc=
90713 -----END CERTIFICATE-----
90714
90715 T-TeleSec GlobalRoot Class 3
90716 ============================
90717 -----BEGIN CERTIFICATE-----
90718 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
90719 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
90720 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
90721 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
90722 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
90723 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
90724 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
90725 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
90726 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
90727 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
90728 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
90729 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
90730 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
90731 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
90732 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
90733 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
90734 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
90735 -----END CERTIFICATE-----
90736
90737 EE Certification Centre Root CA
90738 ===============================
90739 -----BEGIN CERTIFICATE-----
90740 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
90741 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
90742 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
90743 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
90744 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
90745 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
90746 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
90747 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
90748 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
90749 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
90750 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
90751 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
90752 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
90753 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
90754 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
90755 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
90756 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
90757 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
90758 dcGWxZ0=
90759 -----END CERTIFICATE-----
90760
90761 D-TRUST Root Class 3 CA 2 2009
90762 ==============================
90763 -----BEGIN CERTIFICATE-----
90764 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
90765 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
90766 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
90767 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
90768 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
90769 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
90770 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
90771 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
90772 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
90773 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
90774 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
90775 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
90776 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
90777 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
90778 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
90779 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
90780 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
90781 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
90782 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
90783 -----END CERTIFICATE-----
90784
90785 D-TRUST Root Class 3 CA 2 EV 2009
90786 =================================
90787 -----BEGIN CERTIFICATE-----
90788 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
90789 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
90790 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
90791 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
90792 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
90793 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
90794 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
90795 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
90796 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
90797 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
90798 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
90799 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
90800 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
90801 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
90802 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
90803 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
90804 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
90805 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
90806 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
90807 w9y4AyHqnxbxLFS1
90808 -----END CERTIFICATE-----
90809
90810 CA Disig Root R2
90811 ================
90812 -----BEGIN CERTIFICATE-----
90813 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
90814 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
90815 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
90816 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
90817 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
90818 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
90819 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
90820 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
90821 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
90822 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
90823 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
90824 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
90825 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
90826 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
90827 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
90828 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
90829 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
90830 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
90831 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
90832 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
90833 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
90834 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
90835 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
90836 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
90837 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
90838 -----END CERTIFICATE-----
90839
90840 ACCVRAIZ1
90841 =========
90842 -----BEGIN CERTIFICATE-----
90843 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
90844 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
90845 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
90846 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
90847 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
90848 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
90849 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
90850 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
90851 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
90852 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
90853 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
90854 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
90855 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
90856 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
90857 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
90858 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
90859 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
90860 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
90861 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
90862 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
90863 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
90864 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
90865 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
90866 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
90867 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
90868 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
90869 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
90870 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
90871 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
90872 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
90873 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
90874 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
90875 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
90876 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
90877 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
90878 EfbRD0tVNEYqi4Y7
90879 -----END CERTIFICATE-----
90880
90881 TWCA Global Root CA
90882 ===================
90883 -----BEGIN CERTIFICATE-----
90884 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
90885 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
90886 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
90887 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
90888 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
90889 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
90890 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
90891 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
90892 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
90893 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
90894 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
90895 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
90896 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
90897 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
90898 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
90899 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
90900 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
90901 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
90902 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
90903 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
90904 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
90905 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
90906 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
90907 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
90908 -----END CERTIFICATE-----
90909
90910 TeliaSonera Root CA v1
90911 ======================
90912 -----BEGIN CERTIFICATE-----
90913 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
90914 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
90915 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
90916 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
90917 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
90918 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
90919 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
90920 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
90921 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
90922 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
90923 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
90924 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
90925 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
90926 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
90927 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
90928 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
90929 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
90930 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
90931 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
90932 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
90933 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
90934 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
90935 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
90936 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
90937 -----END CERTIFICATE-----
90938
90939 E-Tugra Certification Authority
90940 ===============================
90941 -----BEGIN CERTIFICATE-----
90942 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
90943 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
90944 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
90945 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
90946 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
90947 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
90948 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
90949 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
90950 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
90951 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
90952 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
90953 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
90954 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
90955 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
90956 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
90957 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
90958 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
90959 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
90960 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
90961 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
90962 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
90963 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
90964 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
90965 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
90966 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
90967 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
90968 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
90969 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
90970 C7TbO6Orb1wdtn7os4I07QZcJA==
90971 -----END CERTIFICATE-----
90972
90973 T-TeleSec GlobalRoot Class 2
90974 ============================
90975 -----BEGIN CERTIFICATE-----
90976 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
90977 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
90978 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
90979 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
90980 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
90981 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
90982 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
90983 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
90984 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
90985 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
90986 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
90987 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
90988 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
90989 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
90990 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
90991 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
90992 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
90993 -----END CERTIFICATE-----
90994
90995 Atos TrustedRoot 2011
90996 =====================
90997 -----BEGIN CERTIFICATE-----
90998 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
90999 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
91000 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
91001 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
91002 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
91003 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
91004 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
91005 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
91006 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
91007 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
91008 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
91009 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
91010 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
91011 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
91012 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
91013 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
91014 -----END CERTIFICATE-----
91015
91016 QuoVadis Root CA 1 G3
91017 =====================
91018 -----BEGIN CERTIFICATE-----
91019 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
91020 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
91021 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
91022 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
91023 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
91024 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
91025 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
91026 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
91027 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
91028 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
91029 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
91030 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
91031 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
91032 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
91033 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
91034 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
91035 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
91036 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
91037 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
91038 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
91039 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
91040 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
91041 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
91042 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
91043 hMJKzRwuJIczYOXD
91044 -----END CERTIFICATE-----
91045
91046 QuoVadis Root CA 2 G3
91047 =====================
91048 -----BEGIN CERTIFICATE-----
91049 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
91050 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
91051 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
91052 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
91053 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
91054 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
91055 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
91056 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
91057 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
91058 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
91059 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
91060 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
91061 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
91062 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
91063 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
91064 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
91065 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
91066 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
91067 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
91068 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
91069 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
91070 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
91071 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
91072 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
91073 O3jtZsSOeWmD3n+M
91074 -----END CERTIFICATE-----
91075
91076 QuoVadis Root CA 3 G3
91077 =====================
91078 -----BEGIN CERTIFICATE-----
91079 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
91080 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
91081 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
91082 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
91083 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
91084 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
91085 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
91086 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
91087 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
91088 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
91089 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
91090 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
91091 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
91092 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
91093 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
91094 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
91095 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
91096 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
91097 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
91098 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
91099 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
91100 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
91101 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
91102 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
91103 PpxxVJkES/1Y+Zj0
91104 -----END CERTIFICATE-----
91105
91106 DigiCert Assured ID Root G2
91107 ===========================
91108 -----BEGIN CERTIFICATE-----
91109 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
91110 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
91111 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
91112 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
91113 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
91114 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
91115 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
91116 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
91117 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
91118 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
91119 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
91120 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
91121 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
91122 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
91123 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
91124 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
91125 IhNzbM8m9Yop5w==
91126 -----END CERTIFICATE-----
91127
91128 DigiCert Assured ID Root G3
91129 ===========================
91130 -----BEGIN CERTIFICATE-----
91131 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
91132 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
91133 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
91134 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
91135 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
91136 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
91137 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
91138 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
91139 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
91140 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
91141 1vUhZscv6pZjamVFkpUBtA==
91142 -----END CERTIFICATE-----
91143
91144 DigiCert Global Root G2
91145 =======================
91146 -----BEGIN CERTIFICATE-----
91147 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
91148 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
91149 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
91150 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
91151 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
91152 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
91153 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
91154 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
91155 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
91156 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
91157 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
91158 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
91159 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
91160 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
91161 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
91162 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
91163 MrY=
91164 -----END CERTIFICATE-----
91165
91166 DigiCert Global Root G3
91167 =======================
91168 -----BEGIN CERTIFICATE-----
91169 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
91170 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
91171 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
91172 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
91173 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
91174 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
91175 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
91176 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
91177 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
91178 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
91179 VOKa5Vt8sycX
91180 -----END CERTIFICATE-----
91181
91182 DigiCert Trusted Root G4
91183 ========================
91184 -----BEGIN CERTIFICATE-----
91185 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
91186 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
91187 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
91188 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
91189 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
91190 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
91191 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
91192 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
91193 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
91194 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
91195 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
91196 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
91197 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
91198 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
91199 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
91200 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
91201 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
91202 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
91203 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
91204 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
91205 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
91206 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
91207 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
91208 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
91209 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
91210 82Z+
91211 -----END CERTIFICATE-----
91212
91213 COMODO RSA Certification Authority
91214 ==================================
91215 -----BEGIN CERTIFICATE-----
91216 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
91217 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
91218 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
91219 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
91220 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
91221 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
91222 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
91223 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
91224 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
91225 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
91226 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
91227 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
91228 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
91229 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
91230 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
91231 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
91232 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
91233 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
91234 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
91235 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
91236 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
91237 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
91238 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
91239 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
91240 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
91241 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
91242 LaZRfyHBNVOFBkpdn627G190
91243 -----END CERTIFICATE-----
91244
91245 USERTrust RSA Certification Authority
91246 =====================================
91247 -----BEGIN CERTIFICATE-----
91248 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
91249 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
91250 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
91251 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
91252 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
91253 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
91254 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
91255 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
91256 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
91257 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
91258 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
91259 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
91260 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
91261 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
91262 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
91263 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
91264 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
91265 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
91266 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
91267 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
91268 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
91269 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
91270 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
91271 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
91272 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
91273 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
91274 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
91275 -----END CERTIFICATE-----
91276
91277 USERTrust ECC Certification Authority
91278 =====================================
91279 -----BEGIN CERTIFICATE-----
91280 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
91281 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
91282 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
91283 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
91284 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
91285 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
91286 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
91287 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
91288 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
91289 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
91290 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
91291 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
91292 -----END CERTIFICATE-----
91293
91294 GlobalSign ECC Root CA - R4
91295 ===========================
91296 -----BEGIN CERTIFICATE-----
91297 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
91298 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
91299 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
91300 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
91301 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
91302 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
91303 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
91304 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
91305 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
91306 -----END CERTIFICATE-----
91307
91308 GlobalSign ECC Root CA - R5
91309 ===========================
91310 -----BEGIN CERTIFICATE-----
91311 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
91312 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
91313 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
91314 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
91315 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
91316 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
91317 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
91318 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
91319 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
91320 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
91321 -----END CERTIFICATE-----
91322
91323 Staat der Nederlanden Root CA - G3
91324 ==================================
91325 -----BEGIN CERTIFICATE-----
91326 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
91327 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
91328 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
91329 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
91330 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
91331 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
91332 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
91333 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
91334 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
91335 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
91336 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
91337 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
91338 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
91339 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
91340 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
91341 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
91342 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
91343 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
91344 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
91345 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
91346 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
91347 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
91348 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
91349 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
91350 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
91351 -----END CERTIFICATE-----
91352
91353 Staat der Nederlanden EV Root CA
91354 ================================
91355 -----BEGIN CERTIFICATE-----
91356 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
91357 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
91358 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
91359 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
91360 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
91361 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
91362 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
91363 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
91364 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
91365 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
91366 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
91367 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
91368 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
91369 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
91370 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
91371 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
91372 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
91373 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
91374 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
91375 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
91376 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
91377 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
91378 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
91379 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
91380 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
91381 -----END CERTIFICATE-----
91382
91383 IdenTrust Commercial Root CA 1
91384 ==============================
91385 -----BEGIN CERTIFICATE-----
91386 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
91387 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
91388 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
91389 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
91390 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
91391 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
91392 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
91393 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
91394 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
91395 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
91396 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
91397 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
91398 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
91399 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
91400 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
91401 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
91402 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
91403 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
91404 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
91405 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
91406 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
91407 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
91408 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
91409 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
91410 cGzM7vRX+Bi6hG6H
91411 -----END CERTIFICATE-----
91412
91413 IdenTrust Public Sector Root CA 1
91414 =================================
91415 -----BEGIN CERTIFICATE-----
91416 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
91417 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
91418 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
91419 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
91420 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
91421 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
91422 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
91423 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
91424 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
91425 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
91426 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
91427 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
91428 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
91429 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
91430 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
91431 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
91432 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
91433 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
91434 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
91435 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
91436 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
91437 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
91438 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
91439 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
91440 3Wl9af0AVqW3rLatt8o+Ae+c
91441 -----END CERTIFICATE-----
91442
91443 Entrust Root Certification Authority - G2
91444 =========================================
91445 -----BEGIN CERTIFICATE-----
91446 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
91447 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
91448 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
91449 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
91450 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
91451 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
91452 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
91453 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
91454 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
91455 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
91456 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
91457 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
91458 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
91459 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
91460 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
91461 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
91462 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
91463 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
91464 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
91465 e4pIb4tF9g==
91466 -----END CERTIFICATE-----
91467
91468 Entrust Root Certification Authority - EC1
91469 ==========================================
91470 -----BEGIN CERTIFICATE-----
91471 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
91472 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
91473 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
91474 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
91475 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
91476 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
91477 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
91478 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
91479 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
91480 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
91481 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
91482 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
91483 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
91484 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
91485 -----END CERTIFICATE-----
91486
91487 CFCA EV ROOT
91488 ============
91489 -----BEGIN CERTIFICATE-----
91490 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
91491 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
91492 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
91493 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
91494 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
91495 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
91496 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
91497 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
91498 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
91499 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
91500 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
91501 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
91502 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
91503 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
91504 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
91505 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
91506 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
91507 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
91508 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
91509 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
91510 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
91511 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
91512 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
91513 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
91514 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
91515 -----END CERTIFICATE-----
91516
91517 OISTE WISeKey Global Root GB CA
91518 ===============================
91519 -----BEGIN CERTIFICATE-----
91520 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
91521 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
91522 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
91523 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
91524 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
91525 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
91526 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
91527 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
91528 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
91529 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
91530 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
91531 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
91532 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
91533 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
91534 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
91535 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
91536 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
91537 -----END CERTIFICATE-----
91538
91539 SZAFIR ROOT CA2
91540 ===============
91541 -----BEGIN CERTIFICATE-----
91542 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
91543 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
91544 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
91545 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
91546 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
91547 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
91548 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
91549 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
91550 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
91551 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
91552 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
91553 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
91554 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
91555 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
91556 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
91557 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
91558 -----END CERTIFICATE-----
91559
91560 Certum Trusted Network CA 2
91561 ===========================
91562 -----BEGIN CERTIFICATE-----
91563 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
91564 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
91565 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
91566 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
91567 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
91568 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
91569 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
91570 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
91571 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
91572 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
91573 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
91574 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
91575 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
91576 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
91577 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
91578 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
91579 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
91580 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
91581 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
91582 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
91583 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
91584 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
91585 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
91586 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
91587 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
91588 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
91589 zAYspsbiDrW5viSP
91590 -----END CERTIFICATE-----
91591
91592 Hellenic Academic and Research Institutions RootCA 2015
91593 =======================================================
91594 -----BEGIN CERTIFICATE-----
91595 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
91596 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
91597 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
91598 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
91599 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
91600 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
91601 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
91602 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
91603 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
91604 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
91605 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
91606 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
91607 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
91608 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
91609 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
91610 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
91611 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
91612 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
91613 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
91614 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
91615 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
91616 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
91617 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
91618 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
91619 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
91620 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
91621 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
91622 p/UsQu0yrbYhnr68
91623 -----END CERTIFICATE-----
91624
91625 Hellenic Academic and Research Institutions ECC RootCA 2015
91626 ===========================================================
91627 -----BEGIN CERTIFICATE-----
91628 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
91629 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
91630 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
91631 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
91632 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
91633 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
91634 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
91635 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
91636 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
91637 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
91638 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
91639 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
91640 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
91641 -----END CERTIFICATE-----
91642
91643 ISRG Root X1
91644 ============
91645 -----BEGIN CERTIFICATE-----
91646 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
91647 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
91648 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
91649 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
91650 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
91651 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
91652 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
91653 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
91654 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
91655 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
91656 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
91657 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
91658 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
91659 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
91660 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
91661 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
91662 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
91663 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
91664 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
91665 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
91666 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
91667 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
91668 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
91669 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
91670 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
91671 -----END CERTIFICATE-----
91672
91673 AC RAIZ FNMT-RCM
91674 ================
91675 -----BEGIN CERTIFICATE-----
91676 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
91677 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
91678 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
91679 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
91680 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
91681 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
91682 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
91683 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
91684 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
91685 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
91686 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
91687 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
91688 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
91689 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
91690 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
91691 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
91692 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
91693 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
91694 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
91695 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
91696 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
91697 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
91698 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
91699 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
91700 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
91701 -----END CERTIFICATE-----
91702
91703 Amazon Root CA 1
91704 ================
91705 -----BEGIN CERTIFICATE-----
91706 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
91707 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
91708 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
91709 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
91710 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
91711 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
91712 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
91713 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
91714 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
91715 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
91716 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
91717 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
91718 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
91719 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
91720 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
91721 -----END CERTIFICATE-----
91722
91723 Amazon Root CA 2
91724 ================
91725 -----BEGIN CERTIFICATE-----
91726 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
91727 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
91728 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
91729 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
91730 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
91731 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
91732 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
91733 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
91734 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
91735 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
91736 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
91737 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
91738 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
91739 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
91740 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
91741 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
91742 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
91743 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
91744 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
91745 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
91746 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
91747 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
91748 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
91749 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
91750 -----END CERTIFICATE-----
91751
91752 Amazon Root CA 3
91753 ================
91754 -----BEGIN CERTIFICATE-----
91755 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
91756 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
91757 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
91758 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
91759 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
91760 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
91761 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
91762 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
91763 -----END CERTIFICATE-----
91764
91765 Amazon Root CA 4
91766 ================
91767 -----BEGIN CERTIFICATE-----
91768 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
91769 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
91770 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
91771 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
91772 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
91773 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
91774 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
91775 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
91776 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
91777 -----END CERTIFICATE-----
91778
91779 LuxTrust Global Root 2
91780 ======================
91781 -----BEGIN CERTIFICATE-----
91782 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
91783 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
91784 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
91785 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
91786 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
91787 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
91788 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
91789 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
91790 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
91791 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
91792 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
91793 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
91794 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
91795 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
91796 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
91797 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
91798 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
91799 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
91800 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
91801 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
91802 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
91803 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
91804 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
91805 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
91806 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
91807 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
91808 -----END CERTIFICATE-----
91809
91810 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
91811 =============================================
91812 -----BEGIN CERTIFICATE-----
91813 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
91814 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
91815 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
91816 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
91817 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
91818 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
91819 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
91820 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
91821 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
91822 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
91823 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
91824 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
91825 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
91826 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
91827 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
91828 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
91829 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
91830 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
91831 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
91832 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
91833 -----END CERTIFICATE-----
91834
91835 GDCA TrustAUTH R5 ROOT
91836 ======================
91837 -----BEGIN CERTIFICATE-----
91838 MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
91839 BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
91840 DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
91841 YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
91842 IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
91843 AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
91844 AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
91845 OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
91846 pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
91847 9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
91848 xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
91849 R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
91850 D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
91851 oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
91852 9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
91853 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
91854 p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
91855 H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
91856 6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
91857 +PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
91858 HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
91859 F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
91860 8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
91861 /EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
91862 aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
91863 -----END CERTIFICATE-----
91864
91865 TrustCor RootCert CA-1
91866 ======================
91867 -----BEGIN CERTIFICATE-----
91868 MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP
91869 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
91870 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
91871 dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx
91872 MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu
91873 YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe
91874 VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy
91875 dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq
91876 jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4
91877 pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0
91878 JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h
91879 gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw
91880 /Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j
91881 BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
91882 AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5
91883 mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
91884 ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C
91885 qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P
91886 3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk=
91887 -----END CERTIFICATE-----
91888
91889 TrustCor RootCert CA-2
91890 ======================
91891 -----BEGIN CERTIFICATE-----
91892 MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w
91893 DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT
91894 eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0
91895 eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy
91896 MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h
91897 bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
91898 cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0
91899 IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb
91900 ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk
91901 RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1
91902 oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb
91903 XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1
91904 /p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q
91905 jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP
91906 eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg
91907 rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
91908 8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU
91909 2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD
91910 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h
91911 Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp
91912 kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv
91913 2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3
91914 S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw
91915 PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv
91916 DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU
91917 RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE
91918 xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX
91919 RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ
91920 -----END CERTIFICATE-----
91921
91922 TrustCor ECA-1
91923 ==============
91924 -----BEGIN CERTIFICATE-----
91925 MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP
91926 MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig
91927 U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp
91928 dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw
91929 N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5
91930 MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y
91931 IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG
91932 SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR
91933 MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23
91934 xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc
91935 p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+
91936 fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj
91937 YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL
91938 f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF
91939 AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u
91940 /ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
91941 hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs
91942 J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC
91943 jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g==
91944 -----END CERTIFICATE-----
91945
91946 SSL.com Root Certification Authority RSA
91947 ========================================
91948 -----BEGIN CERTIFICATE-----
91949 MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
91950 BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
91951 MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
91952 MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
91953 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
91954 LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
91955 ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
91956 Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
91957 P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
91958 oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
91959 k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
91960 fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
91961 gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
91962 UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
91963 1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
91964 bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
91965 HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
91966 AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
91967 dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
91968 ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
91969 u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
91970 erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
91971 MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
91972 vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
91973 Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
91974 wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
91975 WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
91976 -----END CERTIFICATE-----
91977
91978 SSL.com Root Certification Authority ECC
91979 ========================================
91980 -----BEGIN CERTIFICATE-----
91981 MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
91982 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
91983 BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
91984 MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
91985 BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
91986 bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
91987 BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
91988 8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
91989 hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
91990 jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
91991 e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
91992 5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
91993 -----END CERTIFICATE-----
91994
91995 SSL.com EV Root Certification Authority RSA R2
91996 ==============================================
91997 -----BEGIN CERTIFICATE-----
91998 MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
91999 DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
92000 MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
92001 MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
92002 DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
92003 VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
92004 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
92005 hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
92006 cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
92007 Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
92008 B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
92009 CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
92010 9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
92011 RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
92012 JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
92013 +qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
92014 HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
92015 qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
92016 ++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
92017 Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
92018 guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
92019 OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
92020 CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
92021 lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
92022 rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
92023 hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
92024 9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
92025 -----END CERTIFICATE-----
92026
92027 SSL.com EV Root Certification Authority ECC
92028 ===========================================
92029 -----BEGIN CERTIFICATE-----
92030 MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
92031 BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
92032 BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
92033 MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
92034 EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
92035 LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
92036 BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
92037 3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
92038 BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
92039 5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
92040 N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
92041 m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
92042 -----END CERTIFICATE-----
92043
92044 GlobalSign Root CA - R6
92045 =======================
92046 -----BEGIN CERTIFICATE-----
92047 MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
92048 R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
92049 b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
92050 YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
92051 U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
92052 grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
92053 3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
92054 vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
92055 PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
92056 azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
92057 WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
92058 CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
92059 0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
92060 b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
92061 AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
92062 HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
92063 nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
92064 lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
92065 BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
92066 Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
92067 3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
92068 0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
92069 uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
92070 oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
92071 JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
92072 -----END CERTIFICATE-----
92073
92074 OISTE WISeKey Global Root GC CA
92075 ===============================
92076 -----BEGIN CERTIFICATE-----
92077 MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
92078 SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
92079 MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
92080 Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
92081 ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
92082 bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
92083 VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
92084 NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
92085 BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
92086 AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
92087 AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
92088 -----END CERTIFICATE-----
92089
92090 GTS Root R1
92091 ===========
92092 -----BEGIN CERTIFICATE-----
92093 MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
92094 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
92095 b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
92096 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi
92097 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx
92098 9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r
92099 aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW
92100 r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM
92101 LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly
92102 4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr
92103 06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
92104 wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om
92105 3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu
92106 JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
92107 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM
92108 BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
92109 d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv
92110 fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm
92111 ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b
92112 gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq
92113 4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr
92114 tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo
92115 pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0
92116 sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql
92117 CFF1pkgl
92118 -----END CERTIFICATE-----
92119
92120 GTS Root R2
92121 ===========
92122 -----BEGIN CERTIFICATE-----
92123 MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
92124 EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
92125 b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
92126 A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi
92127 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk
92128 k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo
92129 7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI
92130 m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm
92131 dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu
92132 ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz
92133 cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
92134 Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl
92135 aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy
92136 5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
92137 VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM
92138 BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
92139 vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ
92140 +YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw
92141 c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da
92142 WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r
92143 n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu
92144 Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ
92145 7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs
92146 gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld
92147 o/DUhgkC
92148 -----END CERTIFICATE-----
92149
92150 GTS Root R3
92151 ===========
92152 -----BEGIN CERTIFICATE-----
92153 MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
92154 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
92155 UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
92156 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq
92157 hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU
92158 Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej
92159 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP
92160 0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0
92161 glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa
92162 KaqW04MjyaR7YbPMAuhd
92163 -----END CERTIFICATE-----
92164
92165 GTS Root R4
92166 ===========
92167 -----BEGIN CERTIFICATE-----
92168 MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
92169 UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
92170 UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
92171 ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq
92172 hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa
92173 6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj
92174 QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV
92175 2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI
92176 N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x
92177 zPKwTdb+mciUqXWi4w==
92178 -----END CERTIFICATE-----
92179
92180 UCA Global G2 Root
92181 ==================
92182 -----BEGIN CERTIFICATE-----
92183 MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG
92184 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x
92185 NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU
92186 cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
92187 MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT
92188 oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV
92189 8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS
92190 h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o
92191 LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/
92192 R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe
92193 KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa
92194 4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc
92195 OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97
92196 8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
92197 BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo
92198 5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
92199 1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A
92200 Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9
92201 yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX
92202 c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo
92203 jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk
92204 bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x
92205 ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn
92206 RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A==
92207 -----END CERTIFICATE-----
92208
92209 UCA Extended Validation Root
92210 ============================
92211 -----BEGIN CERTIFICATE-----
92212 MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
92213 EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u
92214 IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G
92215 A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi
92216 MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs
92217 iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF
92218 Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu
92219 eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR
92220 59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH
92221 0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR
92222 el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv
92223 B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth
92224 WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS
92225 NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS
92226 3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL
92227 BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
92228 ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM
92229 aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4
92230 dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb
92231 +7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW
92232 F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi
92233 GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc
92234 GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi
92235 djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr
92236 dhh2n1ax
92237 -----END CERTIFICATE-----
92238
92239 Certigna Root CA
92240 ================
92241 -----BEGIN CERTIFICATE-----
92242 MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE
92243 BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ
92244 MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda
92245 MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz
92246 MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
92247 DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX
92248 stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz
92249 KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8
92250 JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16
92251 XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq
92252 4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej
92253 wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ
92254 lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI
92255 jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/
92256 /TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
92257 HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
92258 1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy
92259 dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h
92260 LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl
92261 cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt
92262 OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP
92263 TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq
92264 7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3
92265 4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd
92266 8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS
92267 6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY
92268 tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
92269 aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
92270 E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
92271 -----END CERTIFICATE-----
92272
92273 emSign Root CA - G1
92274 ===================
92275 -----BEGIN CERTIFICATE-----
92276 MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
92277 MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
92278 ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
92279 ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
92280 aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
92281 IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
92282 LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
92283 cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
92284 DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
92285 6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
92286 hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
92287 MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
92288 vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
92289 NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
92290 +Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
92291 U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
92292 iN66zB+Afko=
92293 -----END CERTIFICATE-----
92294
92295 emSign ECC Root CA - G3
92296 =======================
92297 -----BEGIN CERTIFICATE-----
92298 MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
92299 A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
92300 MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
92301 MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
92302 ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
92303 RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
92304 58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
92305 MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
92306 AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
92307 CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
92308 jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
92309 -----END CERTIFICATE-----
92310
92311 emSign Root CA - C1
92312 ===================
92313 -----BEGIN CERTIFICATE-----
92314 MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
92315 EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
92316 Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
92317 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
92318 ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
92319 ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
92320 Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
92321 OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
92322 I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
92323 lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
92324 XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
92325 ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
92326 /6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
92327 NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
92328 wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
92329 BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
92330 -----END CERTIFICATE-----
92331
92332 emSign ECC Root CA - C3
92333 =======================
92334 -----BEGIN CERTIFICATE-----
92335 MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
92336 A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
92337 Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
92338 BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
92339 ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
92340 6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
92341 SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
92342 B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
92343 MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
92344 ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
92345 -----END CERTIFICATE-----
92346
92347 Hongkong Post Root CA 3
92348 =======================
92349 -----BEGIN CERTIFICATE-----
92350 MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
92351 A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
92352 Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
92353 MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
92354 bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
92355 SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
92356 iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
92357 jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
92358 5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
92359 sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
92360 0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
92361 JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
92362 y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
92363 +bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
92364 xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
92365 AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
92366 i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
92367 AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
92368 W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
92369 y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
92370 +BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
92371 eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
92372 9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
92373 nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
92374 hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
92375 60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
92376 dBb9HxEGmpv0
92377 -----END CERTIFICATE-----
92378
92379 Entrust Root Certification Authority - G4
92380 =========================================
92381 -----BEGIN CERTIFICATE-----
92382 MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV
92383 BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu
92384 bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1
92385 dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
92386 dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT
92387 AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
92388 L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv
92389 cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv
92390 cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D
92391 umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV
92392 3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds
92393 8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ
92394 e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7
92395 ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X
92396 xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV
92397 7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
92398 dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW
92399 Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T
92400 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n
92401 MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q
92402 jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht
92403 7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK
92404 YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt
92405 jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+
92406 m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW
92407 RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA
92408 JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G
92409 +TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT
92410 kcpG2om3PVODLAgfi49T3f+sHw==
92411 -----END CERTIFICATE-----
92412 <?php
92413
92414 if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
92415     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
92416 }
92417
92418 setlocale(LC_ALL, 'C');
92419 require __DIR__.'/../src/bootstrap.php';
92420
92421 use Composer\Console\Application;
92422 use Composer\XdebugHandler\XdebugHandler;
92423
92424 error_reporting(-1);
92425
92426 // Restart without Xdebug
92427 $xdebug = new XdebugHandler('Composer', '--ansi');
92428 $xdebug->check();
92429 unset($xdebug);
92430
92431 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '4.0', '>=')) {
92432     echo 'HHVM 4.0 has dropped support for Composer, please use PHP instead. Aborting.'.PHP_EOL;
92433     exit(1);
92434 }
92435
92436 if (function_exists('ini_set')) {
92437     @ini_set('display_errors', 1);
92438
92439     $memoryInBytes = function ($value) {
92440         $unit = strtolower(substr($value, -1, 1));
92441         $value = (int) $value;
92442         switch($unit) {
92443             case 'g':
92444                 $value *= 1024;
92445                 // no break (cumulative multiplier)
92446             case 'm':
92447                 $value *= 1024;
92448                 // no break (cumulative multiplier)
92449             case 'k':
92450                 $value *= 1024;
92451         }
92452
92453         return $value;
92454     };
92455
92456     $memoryLimit = trim(ini_get('memory_limit'));
92457     // Increase memory_limit if it is lower than 1.5GB
92458     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
92459         @ini_set('memory_limit', '1536M');
92460     }
92461     // Set user defined memory limit
92462     if ($memoryLimit = getenv('COMPOSER_MEMORY_LIMIT')) {
92463         @ini_set('memory_limit', $memoryLimit);
92464     }
92465     unset($memoryInBytes, $memoryLimit);
92466 }
92467
92468 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
92469
92470 // run the command application
92471 $application = new Application();
92472 $application->run();
92473
92474 Copyright (c) Nils Adermann, Jordi Boggiano
92475
92476 Permission is hereby granted, free of charge, to any person obtaining a copy
92477 of this software and associated documentation files (the "Software"), to deal
92478 in the Software without restriction, including without limitation the rights
92479 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
92480 copies of the Software, and to permit persons to whom the Software is furnished
92481 to do so, subject to the following conditions:
92482
92483 The above copyright notice and this permission notice shall be included in all
92484 copies or substantial portions of the Software.
92485
92486 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
92487 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92488 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
92489 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
92490 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
92491 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
92492 THE SOFTWARE.
92493
92494 \ 6!)¸÷Ç{3bá«\1d\83ã\1a\ f\ 4\8c\ 2\0\0\0GBMB